summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx5
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx5')
-rw-r--r--arch/arm/mach-mx5/Kconfig109
-rw-r--r--arch/arm/mach-mx5/Makefile16
-rw-r--r--arch/arm/mach-mx5/Makefile.boot12
-rw-r--r--arch/arm/mach-mx5/board-mx51_babbage.c10
-rw-r--r--arch/arm/mach-mx5/bus_freq.c1108
-rw-r--r--arch/arm/mach-mx5/clock-mx51.c871
-rw-r--r--arch/arm/mach-mx5/clock.c5140
-rw-r--r--arch/arm/mach-mx5/clock_mx50.c3523
-rw-r--r--arch/arm/mach-mx5/cpu.c205
-rw-r--r--arch/arm/mach-mx5/crm_regs.h669
-rw-r--r--arch/arm/mach-mx5/devices-imx51.h26
-rw-r--r--arch/arm/mach-mx5/devices.c1866
-rw-r--r--arch/arm/mach-mx5/devices.h97
-rw-r--r--arch/arm/mach-mx5/dma-apbh.c225
-rw-r--r--arch/arm/mach-mx5/dma-apbh.h35
-rw-r--r--arch/arm/mach-mx5/dma.c1724
-rw-r--r--arch/arm/mach-mx5/dmaengine.c682
-rw-r--r--arch/arm/mach-mx5/dummy_gpio.c119
-rw-r--r--arch/arm/mach-mx5/early_setup.c29
-rw-r--r--arch/arm/mach-mx5/iomux.c268
-rw-r--r--arch/arm/mach-mx5/iomux.h202
-rw-r--r--arch/arm/mach-mx5/lpmodes.c308
-rw-r--r--arch/arm/mach-mx5/mm.c85
-rw-r--r--arch/arm/mach-mx5/mx50_arm2.c1260
-rw-r--r--arch/arm/mach-mx5/mx50_arm2_pmic_mc13892.c434
-rw-r--r--arch/arm/mach-mx5/mx50_ddr_freq.S832
-rw-r--r--arch/arm/mach-mx5/mx50_rdp.c1595
-rw-r--r--arch/arm/mach-mx5/mx50_rdp_pmic_mc13892.c435
-rw-r--r--arch/arm/mach-mx5/mx50_suspend.S234
-rw-r--r--arch/arm/mach-mx5/mx50_wfi.S124
-rw-r--r--arch/arm/mach-mx5/mx51_3stack.c1078
-rw-r--r--arch/arm/mach-mx5/mx51_3stack_gpio.c852
-rw-r--r--arch/arm/mach-mx5/mx51_3stack_pmic_mc13892.c370
-rw-r--r--arch/arm/mach-mx5/mx51_babbage.c1325
-rw-r--r--arch/arm/mach-mx5/mx51_babbage_pmic_mc13892.c436
-rw-r--r--arch/arm/mach-mx5/mx51_pins.h409
-rw-r--r--arch/arm/mach-mx5/mx53_ard.c1322
-rw-r--r--arch/arm/mach-mx5/mx53_ard_pmic_ltc3589.c228
-rw-r--r--arch/arm/mach-mx5/mx53_evk.c1562
-rw-r--r--arch/arm/mach-mx5/mx53_evk_pmic_mc13892.c351
-rw-r--r--arch/arm/mach-mx5/mx53_loco.c839
-rw-r--r--arch/arm/mach-mx5/mx53_loco_pmic_da9053.c270
-rw-r--r--arch/arm/mach-mx5/mx53_smd.c1122
-rw-r--r--arch/arm/mach-mx5/mx53_smd_pmic_da9053.c298
-rw-r--r--arch/arm/mach-mx5/mx53_smd_rfkill.c136
-rw-r--r--arch/arm/mach-mx5/mx53_wp.c159
-rw-r--r--arch/arm/mach-mx5/mx53_wp.h43
-rw-r--r--arch/arm/mach-mx5/pm.c300
-rw-r--r--arch/arm/mach-mx5/pm_da9053.c385
-rw-r--r--arch/arm/mach-mx5/regs-apbh.h512
-rw-r--r--arch/arm/mach-mx5/sdma_script_code_mx50.h129
-rw-r--r--arch/arm/mach-mx5/sdma_script_code_mx51.h256
-rw-r--r--arch/arm/mach-mx5/sdma_script_code_mx53.h206
-rw-r--r--arch/arm/mach-mx5/sdram_autogating.c201
-rw-r--r--arch/arm/mach-mx5/serial.c282
-rw-r--r--arch/arm/mach-mx5/serial.h71
-rw-r--r--arch/arm/mach-mx5/suspend.S153
-rw-r--r--arch/arm/mach-mx5/system.c316
-rw-r--r--arch/arm/mach-mx5/usb.h48
-rw-r--r--arch/arm/mach-mx5/usb_dr.c314
-rw-r--r--arch/arm/mach-mx5/usb_h1.c252
-rw-r--r--arch/arm/mach-mx5/usb_h2.c198
-rw-r--r--arch/arm/mach-mx5/wfi.S426
63 files changed, 35862 insertions, 1230 deletions
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 1576d51e676c..2dc41de79f15 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -2,17 +2,122 @@ if ARCH_MX5
config ARCH_MX51
bool
- default y
+ select USB_ARCH_HAS_EHCI
+ select MXC_TZIC
+ select ARCH_MXC_IOMUX_V3
+
+config ARCH_MX53
+ bool
+ select USB_ARCH_HAS_EHCI
select MXC_TZIC
select ARCH_MXC_IOMUX_V3
-comment "MX5 platforms:"
+config ARCH_MX50
+ bool
+ select ARCH_HAS_RNGC
+
+config FORCE_MAX_ZONEORDER
+ int "MAX_ORDER"
+ default "13"
+
+config MX5_MULTI_ARCH
+ bool
+ default y
+ select RUNTIME_PHYS_OFFSET
+ depends on ARCH_MX51
+ depends on ARCH_MX50 || ARCH_MX53
+
+config MACH_MX51_3DS
+ bool "Support MX51 3-Stack platform"
+ select ARCH_MX51
+ help
+ Include support for MX51 3-Stack platform. This includes specific
+ configurations for the board and its peripherals.
config MACH_MX51_BABBAGE
bool "Support MX51 BABBAGE platforms"
+ select ARCH_MX51
help
Include support for MX51 Babbage platform, also known as MX51EVK in
u-boot. This includes specific configurations for the board and its
peripherals.
+config MACH_MX53_EVK
+ bool "Support MX53 EVK platform"
+ select ARCH_MX53
+ help
+ Include support for MX53 EVK platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX53_ARD
+ bool "Support MX53 ARD platform"
+ select ARCH_MX53
+ help
+ Include support for MX53 ARD platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX53_SMD
+ bool "Support MX53 SMD platform"
+ select ARCH_MX53
+ help
+ Include support for MX53 SMD platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX53_LOCO
+ bool "Support MX53 LOCO platform"
+ select ARCH_MX53
+ help
+ Include support for MX53 LOCO platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX50_ARM2
+ bool "Support MX50 Armadillo2 platform"
+ select ARCH_MX50
+ help
+ Include support for MX50 EVK platform. This includes specific
+ configurations for the board and its peripherals.
+
+config MACH_MX50_RDP
+ bool "Support MX50 Reference Design Platform"
+ select ARCH_MX50
+ help
+ Include support for MX50 RDP platform. This includes specific
+ configurations for the board and its peripherals.
+
+comment "MX5x Options:"
+
+config MXC_SDMA_API
+ bool "Use SDMA API"
+ default y
+ help
+ This selects the Freescale MXC SDMA API.
+ If unsure, say N.
+
+config ARCH_MXC_HAS_NFC_V3
+ bool "MXC NFC Hardware Version 3"
+ depends on ARCH_MX5
+ default y
+ help
+ This selects the Freescale MXC Nand Flash Controller Hardware Version 3
+ If unsure, say N.
+
+config ARCH_MXC_HAS_NFC_V3_2
+ bool "MXC NFC Hardware Version 3.2"
+ depends on ARCH_MXC_HAS_NFC_V3
+ default y
+ help
+ This selects the Freescale MXC Nand Flash Controller Hardware Version 3.1
+ If unsure, say N.
+
+config SDMA_IRAM
+ bool "Use Internal RAM for SDMA transfer"
+ depends on MXC_SDMA_API
+ help
+ Support Internal RAM as SDMA buffer or control structures
+
+config MXC_BLUETOOTH_RFKILL
+ tristate "MXC Bluetooth rfkill interface support"
+ depends on RFKILL
+ ---help---
+ Say Y to get the standard rfkill interface of Bluetooth
endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index bf23f869ef51..2ef2ceb29859 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,7 +3,19 @@
#
# Object file lists.
-obj-y := cpu.o mm.o clock-mx51.o devices.o
+obj-y := system.o iomux.o cpu.o mm.o devices.o serial.o dma.o lpmodes.o pm.o \
+sdram_autogating.o bus_freq.o usb_dr.o usb_h1.o usb_h2.o dummy_gpio.o early_setup.o
-obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
+obj-$(CONFIG_ARCH_MX51) += clock.o suspend.o
+obj-$(CONFIG_ARCH_MX53) += clock.o suspend.o mx53_wp.o pm_da9053.o
+obj-$(CONFIG_ARCH_MX50) += clock_mx50.o dmaengine.o dma-apbh.o mx50_suspend.o mx50_ddr_freq.o mx50_wfi.o
+obj-$(CONFIG_MACH_MX51_3DS) += mx51_3stack.o mx51_3stack_gpio.o mx51_3stack_pmic_mc13892.o
+obj-$(CONFIG_MACH_MX51_BABBAGE) += mx51_babbage.o mx51_babbage_pmic_mc13892.o
+obj-$(CONFIG_MACH_MX53_EVK) += mx53_evk.o mx53_evk_pmic_mc13892.o
+obj-$(CONFIG_MACH_MX53_ARD) += mx53_ard.o mx53_ard_pmic_ltc3589.o
+obj-$(CONFIG_MACH_MX53_SMD) += mx53_smd.o mx53_smd_pmic_da9053.o
+obj-$(CONFIG_MACH_MX53_LOCO) += mx53_loco.o mx53_loco_pmic_da9053.o
+obj-$(CONFIG_MACH_MX50_ARM2) += mx50_arm2.o mx50_arm2_pmic_mc13892.o
+obj-$(CONFIG_MACH_MX50_RDP) += mx50_rdp.o mx50_rdp_pmic_mc13892.o
+obj-$(CONFIG_MXC_BLUETOOTH_RFKILL) += mx53_smd_rfkill.o
diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot
index 9939a19d99a1..434ef85a32dc 100644
--- a/arch/arm/mach-mx5/Makefile.boot
+++ b/arch/arm/mach-mx5/Makefile.boot
@@ -1,3 +1,9 @@
- zreladdr-y := 0x90008000
-params_phys-y := 0x90000100
-initrd_phys-y := 0x90800000
+ zreladdr-$(CONFIG_ARCH_MX51) := 0x90008000
+params_phys-$(CONFIG_ARCH_MX51) := 0x90000100
+initrd_phys-$(CONFIG_ARCH_MX51) := 0x90800000
+ zreladdr-$(CONFIG_ARCH_MX53) := 0x70008000
+params_phys-$(CONFIG_ARCH_MX53) := 0x70000100
+initrd_phys-$(CONFIG_ARCH_MX53) := 0x70800000
+ zreladdr-$(CONFIG_ARCH_MX50) := 0x70008000
+params_phys-$(CONFIG_ARCH_MX50) := 0x70000100
+initrd_phys-$(CONFIG_ARCH_MX50) := 0x70800000
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index ed885f9d7b73..9968164f5271 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -19,7 +19,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
-#include <mach/imx-uart.h>
#include <mach/iomux-mx51.h>
#include <mach/mxc_ehci.h>
@@ -29,6 +28,7 @@
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
+#include "devices-imx51.h"
#include "devices.h"
#define BABBAGE_USB_HUB_RESET (0*32 + 7) /* GPIO_1_7 */
@@ -83,15 +83,15 @@ static struct pad_desc mx51babbage_pads[] = {
/* Serial ports */
#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static struct imxuart_platform_data uart_pdata = {
+static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
static inline void mxc_init_imx_uart(void)
{
- mxc_register_device(&mxc_uart_device0, &uart_pdata);
- mxc_register_device(&mxc_uart_device1, &uart_pdata);
- mxc_register_device(&mxc_uart_device2, &uart_pdata);
+ imx51_add_imx_uart(0, &uart_pdata);
+ imx51_add_imx_uart(1, &uart_pdata);
+ imx51_add_imx_uart(2, &uart_pdata);
}
#else /* !SERIAL_IMX */
static inline void mxc_init_imx_uart(void)
diff --git a/arch/arm/mach-mx5/bus_freq.c b/arch/arm/mach-mx5/bus_freq.c
new file mode 100644
index 000000000000..d598a0663e68
--- /dev/null
+++ b/arch/arm/mach-mx5/bus_freq.c
@@ -0,0 +1,1108 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file bus_freq.c
+ *
+ * @brief A common API for the Freescale Semiconductor i.MXC CPUfreq module
+ * and DVFS CORE module.
+ *
+ * The APIs are for setting bus frequency to low or high.
+ *
+ * @ingroup PM
+ */
+#include <asm/io.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/iram_alloc.h>
+#include <linux/mutex.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/sdram_autogating.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+#include "crm_regs.h"
+
+#define LP_LOW_VOLTAGE 1050000
+#define LP_NORMAL_VOLTAGE 1250000
+#define LP_APM_CLK 24000000
+#define NAND_LP_APM_CLK 12000000
+#define AXI_A_NORMAL_CLK 166250000
+#define AXI_A_CLK_NORMAL_DIV 4
+#define AXI_B_CLK_NORMAL_DIV 5
+#define AHB_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV
+#define EMI_SLOW_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV
+#define NFC_CLK_NORMAL_DIV 4
+#define SPIN_DELAY 1000000 /* in nanoseconds */
+#define HW_QOS_DISABLE 0x70
+#define HW_QOS_DISABLE_SET 0x74
+#define HW_QOS_DISABLE_CLR 0x78
+#define DDR_TYPE_DDR3 0x0
+#define DDR_TYPE_DDR2 0x1
+
+DEFINE_SPINLOCK(ddr_freq_lock);
+
+static unsigned long lp_normal_rate;
+static unsigned long lp_med_rate;
+static unsigned long ddr_normal_rate;
+static unsigned long ddr_med_rate;
+static unsigned long ddr_low_rate;
+static int cur_ddr_rate;
+static unsigned char mx53_ddr_type;
+
+static struct clk *ddr_clk;
+static struct clk *pll1_sw_clk;
+static struct clk *pll1;
+static struct clk *pll2;
+static struct clk *pll3;
+static struct clk *pll4;
+static struct clk *main_bus_clk;
+static struct clk *axi_a_clk;
+static struct clk *axi_b_clk;
+static struct clk *cpu_clk;
+static struct clk *ddr_hf_clk;
+static struct clk *ahb_clk;
+static struct clk *ddr_clk;
+static struct clk *periph_apm_clk;
+static struct clk *lp_apm;
+static struct clk *gpc_dvfs_clk;
+static struct clk *emi_garb_clk;
+static struct clk *epdc_clk;
+
+static void __iomem *pll1_base;
+static void __iomem *pll4_base;
+
+static void __iomem *qosc_base;
+
+struct regulator *pll_regulator;
+
+struct regulator *lp_regulator;
+int low_bus_freq_mode;
+int high_bus_freq_mode;
+int med_bus_freq_mode;
+
+int bus_freq_scaling_initialized;
+char *gp_reg_id;
+char *lp_reg_id;
+
+static struct cpu_wp *cpu_wp_tbl;
+static struct device *busfreq_dev;
+static int busfreq_suspended;
+static int cpu_podf;
+/* True if bus_frequency is scaled not using DVFS-PER */
+int bus_freq_scaling_is_active;
+
+int cpu_wp_nr;
+int lp_high_freq;
+int lp_med_freq;
+
+static int lp_voltage;
+struct workqueue_struct *voltage_wq;
+static struct work_struct voltage_change_handler;
+struct completion voltage_change_cmpl;
+
+void enter_lpapm_mode_mx50(void);
+void enter_lpapm_mode_mx51(void);
+void enter_lpapm_mode_mx53(void);
+void exit_lpapm_mode_mx50(int high_bus_freq);
+void exit_lpapm_mode_mx51(void);
+void exit_lpapm_mode_mx53(void);
+int low_freq_bus_used(void);
+void set_ddr_freq(int ddr_freq);
+void *ddr_freq_change_iram_base;
+void (*change_ddr_freq)(void *ccm_addr, void *databahn_addr, u32 freq) = NULL;
+
+extern void mx50_ddr_freq_change(u32 ccm_base,
+ u32 databahn_addr, u32 freq);
+extern int dvfs_core_is_active;
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void __iomem *ccm_base;
+extern void __iomem *databahn_base;
+
+struct dvfs_wp dvfs_core_setpoint[] = {
+ {33, 8, 33, 10, 10, 0x08},
+ {26, 0, 33, 20, 10, 0x08},
+ {28, 8, 33, 20, 30, 0x08},
+ {29, 0, 33, 20, 10, 0x08},};
+
+static DEFINE_SPINLOCK(voltage_lock);
+struct mutex bus_freq_mutex;
+
+struct timeval start_time;
+struct timeval end_time;
+
+static void voltage_work_handler(struct work_struct *work)
+{
+ if (lp_regulator != NULL) {
+ u32 ret = 0;
+ ret = regulator_set_voltage(lp_regulator,
+ lp_voltage, lp_voltage);
+ udelay(400);
+ if (ret < 0) {
+ printk(KERN_ERR "COULD NOT SET LP VOLTAGE!!!!!!\n");
+ return;
+ }
+ }
+ complete_all(&voltage_change_cmpl);
+}
+
+int set_low_bus_freq(void)
+{
+ if (busfreq_suspended)
+ return 0;
+ if (bus_freq_scaling_initialized) {
+ /* can not enter low bus freq, when cpu is in higher freq
+ * or only have one working point */
+ if ((clk_get_rate(cpu_clk) >
+ cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate)
+ || (cpu_wp_nr == 1)) {
+ return 0;
+ }
+
+ mutex_lock(&bus_freq_mutex);
+
+ stop_dvfs_per();
+
+ stop_sdram_autogating();
+
+ if (cpu_is_mx50())
+ enter_lpapm_mode_mx50();
+ else if (cpu_is_mx51())
+ enter_lpapm_mode_mx51();
+ else
+ enter_lpapm_mode_mx53();
+ mutex_unlock(&bus_freq_mutex);
+ }
+ return 0;
+}
+
+void enter_lpapm_mode_mx50()
+{
+ u32 reg;
+ unsigned long flags;
+ spin_lock_irqsave(&ddr_freq_lock, flags);
+
+ set_ddr_freq(LP_APM_CLK);
+ /* Set the parent of main_bus_clk to be PLL3 */
+ clk_set_parent(main_bus_clk, pll3);
+
+ /* Set the AHB dividers to be 2.
+ * Set the dividers so that clock rates
+ * are not greater than current clock rate.
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ | 0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0x0F)
+ udelay(10);
+
+ low_bus_freq_mode = 1;
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 0;
+
+ /* Set the source of main_bus_clk to be lp-apm. */
+ clk_set_parent(main_bus_clk, lp_apm);
+
+ /* Set the AHB dividers to be 1. */
+ /* Set the dividers to be 1, so the clock rates
+ * are at 24Mhz
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 0 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 0 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ | 0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0x0F)
+ udelay(10);
+
+ spin_unlock_irqrestore(&ddr_freq_lock, flags);
+
+ spin_lock_irqsave(&voltage_lock, flags);
+ lp_voltage = LP_LOW_VOLTAGE;
+ INIT_COMPLETION(voltage_change_cmpl);
+ queue_work(voltage_wq, &voltage_change_handler);
+ spin_unlock_irqrestore(&voltage_lock, flags);
+
+ if (clk_get_usecount(pll1_sw_clk) == 1) {
+ /* Relock PLL1 to 160MHz. */
+ clk_set_parent(pll1_sw_clk, pll2);
+ /* Set the divider to ARM_PODF to 3. */
+ __raw_writel(0x02, MXC_CCM_CACRR);
+
+ clk_set_rate(pll1, 160000000);
+ clk_set_parent(pll1_sw_clk, pll1);
+ /* Set the divider to ARM_PODF to 1. */
+ __raw_writel(0x0, MXC_CCM_CACRR);
+ }
+
+ udelay(100);
+}
+
+void enter_lpapm_mode_mx51()
+{
+ u32 reg;
+ /* Set PLL3 to 133Mhz if no-one is using it. */
+ if (clk_get_usecount(pll3) == 0) {
+ u32 pll3_rate = clk_get_rate(pll3);
+
+ clk_enable(pll3);
+ clk_set_rate(pll3, clk_round_rate(pll3, 133000000));
+
+ /*Change the DDR freq to 133Mhz. */
+ clk_set_rate(ddr_hf_clk,
+ clk_round_rate(ddr_hf_clk, ddr_low_rate));
+
+ /* Set the parent of Periph_apm_clk to be PLL3 */
+ clk_set_parent(periph_apm_clk, pll3);
+ clk_set_parent(main_bus_clk, periph_apm_clk);
+
+ /* Set the dividers to be 1, so the clock rates
+ * are at 133MHz.
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MXC_CCM_CBCDR_EMI_PODF_MASK
+ | MXC_CCM_CBCDR_NFC_PODF_OFFSET);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 0 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 0 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ | 0 << MXC_CCM_CBCDR_EMI_PODF_OFFSET
+ | 3 << MXC_CCM_CBCDR_NFC_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ clk_enable(emi_garb_clk);
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0x1F)
+ udelay(10);
+ clk_disable(emi_garb_clk);
+
+ low_bus_freq_mode = 1;
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 0;
+
+ /* Set the source of Periph_APM_Clock to be lp-apm. */
+ clk_set_parent(periph_apm_clk, lp_apm);
+
+ /* Set PLL3 back to original rate. */
+ clk_set_rate(pll3, clk_round_rate(pll3, pll3_rate));
+ clk_disable(pll3);
+ }
+}
+
+void enter_lpapm_mode_mx53()
+{
+ u32 reg;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+ /* TBD: Reduce DDR frequency for DDR2 */
+ /* if (mx53_ddr_type == DDR_TYPE_DDR2) {
+ } */
+
+ /* move cpu clk to pll2, 400 / 3 = 133Mhz for cpu */
+ /* Change the source of pll1_sw_clk to be the step_clk */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ cpu_podf = __raw_readl(MXC_CCM_CACRR);
+ reg = __raw_readl(MXC_CCM_CDHIPR);
+ if ((reg & MXC_CCM_CDHIPR_ARM_PODF_BUSY) == 0)
+ __raw_writel(0x2, MXC_CCM_CACRR);
+ else
+ printk(KERN_DEBUG "ARM_PODF still in busy!!!!\n");
+ clk_set_parent(pll1_sw_clk, pll2);
+
+ /* ahb = pll2/8, axi_b = pll2/8, axi_a = pll2/1*/
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 7 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 7 << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ (MXC_CCM_CDHIPR_AXI_A_PODF_BUSY |
+ MXC_CCM_CDHIPR_AXI_B_PODF_BUSY |
+ MXC_CCM_CDHIPR_AHB_PODF_BUSY)) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec
+ > SPIN_DELAY)
+ panic("low bus freq set rate error\n");
+ }
+
+ /* keep this infront of propagating */
+ low_bus_freq_mode = 1;
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 0;
+
+ if (clk_get_usecount(pll1) == 0) {
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
+ reg &= ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
+ }
+ if (clk_get_usecount(pll4) == 0) {
+ reg = __raw_readl(pll4_base + MXC_PLL_DP_CTL);
+ reg &= ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pll4_base + MXC_PLL_DP_CTL);
+ }
+}
+
+int set_high_bus_freq(int high_bus_freq)
+{
+ u32 reg;
+ if (bus_freq_scaling_initialized) {
+ mutex_lock(&bus_freq_mutex);
+ /*
+ * If the CPU freq is 800MHz, set the bus to the high
+ * setpoint (133MHz) and DDR to 200MHz.
+ */
+ if ((clk_get_rate(cpu_clk) >
+ cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate)
+ || lp_high_freq)
+ high_bus_freq = 1;
+
+ stop_sdram_autogating();
+
+ if (low_bus_freq_mode) {
+ /* Relock PLL3 to 133MHz */
+ if (cpu_is_mx50())
+ exit_lpapm_mode_mx50(high_bus_freq);
+ else if (cpu_is_mx51())
+ exit_lpapm_mode_mx51();
+ else
+ exit_lpapm_mode_mx53();
+ start_dvfs_per();
+ }
+ if (bus_freq_scaling_is_active) {
+ if (!high_bus_freq_mode && high_bus_freq) {
+ if (cpu_is_mx50()) {
+ if (med_bus_freq_mode) {
+ /* Increase SYS_CLK */
+ reg = __raw_readl(MXC_CCM_CLK_SYS);
+ reg &= ~MXC_CCM_CLK_SYS_DIV_PLL_MASK;
+ reg |= 4 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CLK_SYS);
+
+ /* Set the dividers to the default dividers */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ |1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ |2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ |0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
+ udelay(10);
+ }
+ } else {
+ clk_set_rate(ahb_clk,
+ clk_round_rate(ahb_clk,
+ lp_normal_rate));
+ clk_set_rate(ddr_hf_clk,
+ clk_round_rate(ddr_hf_clk,
+ ddr_normal_rate));
+ }
+ /* Set to the high setpoint. */
+ high_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ med_bus_freq_mode = 0;
+ } else if (!med_bus_freq_mode && !high_bus_freq) {
+ if (cpu_is_mx50()) {
+ /* Set the dividers to the medium setpoint dividers */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ |3 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ |5 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ |0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
+ udelay(10);
+ /* Reduce SYS_CLK */
+ reg = __raw_readl(MXC_CCM_CLK_SYS);
+ reg &= ~MXC_CCM_CLK_SYS_DIV_PLL_MASK;
+ reg |= 8 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CLK_SYS);
+ } else {
+ if (cpu_is_mx51())
+ clk_set_rate(ddr_hf_clk,
+ clk_round_rate(
+ ddr_hf_clk,
+ ddr_low_rate));
+ clk_set_rate(ahb_clk,
+ clk_round_rate(
+ ahb_clk, lp_med_rate));
+ }
+ /* Set to the medium setpoint. */
+ high_bus_freq_mode = 0;
+ low_bus_freq_mode = 0;
+ med_bus_freq_mode = 1;
+ }
+ if (cpu_is_mx50()) {
+ if (med_bus_freq_mode &&
+ (cur_ddr_rate != ddr_med_rate))
+ set_ddr_freq(ddr_med_rate);
+ if (high_bus_freq_mode &&
+ (cur_ddr_rate != ddr_normal_rate))
+ set_ddr_freq(ddr_normal_rate);
+ }
+ }
+ start_sdram_autogating();
+ mutex_unlock(&bus_freq_mutex);
+ }
+ return 0;
+}
+
+void exit_lpapm_mode_mx50(int high_bus_freq)
+{
+ u32 reg;
+ unsigned long flags;
+
+ if (clk_get_usecount(pll1_sw_clk) == 1) {
+ /* Relock PLL1 to 800MHz. */
+ clk_set_parent(pll1_sw_clk, pll2);
+ /* Set the divider to ARM_PODF to 3, cpu is at 160MHz. */
+ __raw_writel(0x02, MXC_CCM_CACRR);
+
+ clk_set_rate(pll1, 800000000);
+ clk_set_parent(pll1_sw_clk, pll1);
+ /* Set the divider to ARM_PODF to 5. */
+ __raw_writel(0x4, MXC_CCM_CACRR);
+ }
+
+ if (!completion_done(&voltage_change_cmpl))
+ wait_for_completion_interruptible(&voltage_change_cmpl);
+ spin_lock_irqsave(&voltage_lock, flags);
+ if (lp_voltage != LP_NORMAL_VOLTAGE) {
+ INIT_COMPLETION(voltage_change_cmpl);
+ lp_voltage = LP_NORMAL_VOLTAGE;
+ if (!queue_work(voltage_wq, &voltage_change_handler))
+ printk(KERN_ERR "WORK_NOT_ADDED\n");
+ spin_unlock_irqrestore(&voltage_lock, flags);
+ wait_for_completion_interruptible(&voltage_change_cmpl);
+ } else {
+ spin_unlock_irqrestore(&voltage_lock, flags);
+ if (!completion_done(&voltage_change_cmpl))
+ wait_for_completion_interruptible(&voltage_change_cmpl);
+ }
+
+ spin_lock_irqsave(&ddr_freq_lock, flags);
+ if (!low_bus_freq_mode) {
+ spin_unlock_irqrestore(&ddr_freq_lock, flags);
+ return;
+ }
+
+ /* Temporarily set the dividers when the source is PLL3.
+ * No clock rate is above 133MHz.
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ |1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ |1 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ |0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
+ udelay(10);
+
+ clk_set_parent(main_bus_clk, pll3);
+
+ if (bus_freq_scaling_is_active && !high_bus_freq) {
+ /* Set the dividers to the medium setpoint dividers */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ |3 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ |5 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ |0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
+ udelay(10);
+
+ /*Set the main_bus_clk parent to be PLL2. */
+ clk_set_parent(main_bus_clk, pll2);
+
+ /* Set to the medium setpoint. */
+ high_bus_freq_mode = 0;
+ low_bus_freq_mode = 0;
+ med_bus_freq_mode = 1;
+ set_ddr_freq(ddr_med_rate);
+ } else {
+ /* Set the dividers to the default dividers */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MX50_CCM_CBCDR_WEIM_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ |1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ |2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ |0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
+ udelay(10);
+
+ /*Set the main_bus_clk parent to be PLL2. */
+ clk_set_parent(main_bus_clk, pll2);
+
+ /* Set to the high setpoint. */
+ high_bus_freq_mode = 1;
+ low_bus_freq_mode = 0;
+ med_bus_freq_mode = 0;
+ set_ddr_freq(ddr_normal_rate);
+ }
+
+ spin_unlock_irqrestore(&ddr_freq_lock, flags);
+
+ udelay(100);
+}
+
+void exit_lpapm_mode_mx51()
+{
+ u32 reg;
+
+ /* Temporarily Set the dividers is PLL3.
+ * No clock rate is above 133MHz.
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MXC_CCM_CBCDR_EMI_PODF_MASK
+ | MXC_CCM_CBCDR_NFC_PODF_OFFSET);
+ reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_EMI_PODF_OFFSET
+ | 3 << MXC_CCM_CBCDR_NFC_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ clk_enable(emi_garb_clk);
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0x1F)
+ udelay(10);
+ clk_disable(emi_garb_clk);
+
+ clk_set_parent(periph_apm_clk, pll3);
+
+ /* Set the dividers to the default dividers */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK
+ | MXC_CCM_CBCDR_EMI_PODF_MASK
+ | MXC_CCM_CBCDR_NFC_PODF_OFFSET);
+ reg |= (3 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 4 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 4 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
+ | 4 << MXC_CCM_CBCDR_EMI_PODF_OFFSET
+ | 3 << MXC_CCM_CBCDR_NFC_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ clk_enable(emi_garb_clk);
+ while (__raw_readl(MXC_CCM_CDHIPR) & 0x1F)
+ udelay(10);
+
+ low_bus_freq_mode = 0;
+ high_bus_freq_mode = 1;
+ clk_disable(emi_garb_clk);
+
+ /*Set the main_bus_clk parent to be PLL2. */
+ clk_set_parent(main_bus_clk, pll2);
+
+ /*Change the DDR freq to 200MHz*/
+ clk_set_rate(ddr_hf_clk,
+ clk_round_rate(ddr_hf_clk, ddr_normal_rate));
+}
+
+void exit_lpapm_mode_mx53()
+{
+ u32 reg;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+
+ /* move cpu clk to pll1 */
+ reg = __raw_readl(MXC_CCM_CDHIPR);
+ if ((reg & MXC_CCM_CDHIPR_ARM_PODF_BUSY) != 0)
+ __raw_writel(cpu_podf & 0x7,
+ MXC_CCM_CACRR);
+ else
+ printk(KERN_DEBUG
+ "ARM_PODF still in busy!!!!\n");
+
+ clk_set_parent(pll1_sw_clk, pll1);
+
+
+ /* ahb = 400/3, axi_b = 400/2, axi_a = 400*/
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ (MXC_CCM_CDHIPR_AXI_A_PODF_BUSY |
+ MXC_CCM_CDHIPR_AXI_B_PODF_BUSY |
+ MXC_CCM_CDHIPR_AHB_PODF_BUSY)) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec
+ - nstimeofday.tv_nsec
+ > SPIN_DELAY)
+ panic("bus freq error\n");
+ }
+
+ /* keep this infront of propagating */
+ low_bus_freq_mode = 0;
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+
+ /* TBD: Restore DDR frequency for DDR2 */
+ /* if (mx53_ddr_type == DDR_TYPE_DDR2) {
+ } */
+}
+
+int can_change_ddr_freq(void)
+{
+ if (clk_get_usecount(epdc_clk) == 0)
+ return 1;
+ return 0;
+}
+
+void set_ddr_freq(int ddr_rate)
+{
+ u32 reg;
+ unsigned long flags;
+
+ if (!can_change_ddr_freq())
+ return;
+
+ spin_lock_irqsave(&ddr_freq_lock, flags);
+ local_flush_tlb_all();
+ flush_cache_all();
+
+ /* Disable all masters from accessing the DDR. */
+ reg = __raw_readl(qosc_base + HW_QOS_DISABLE);
+ reg |= 0xFFE;
+ __raw_writel(reg, qosc_base + HW_QOS_DISABLE_SET);
+ udelay(100);
+
+ /* Set the DDR to default freq.
+ */
+ change_ddr_freq(ccm_base, databahn_base, ddr_rate);
+
+ /* Enable all masters to access the DDR. */
+ __raw_writel(reg, qosc_base + HW_QOS_DISABLE_CLR);
+
+ spin_unlock_irqrestore(&ddr_freq_lock, flags);
+ cur_ddr_rate = ddr_rate;
+ udelay(100);
+}
+
+int low_freq_bus_used(void)
+{
+ if ((lp_high_freq == 0)
+ && (lp_med_freq == 0))
+ return 1;
+ else
+ return 0;
+}
+
+void setup_pll(void)
+{
+}
+
+static ssize_t bus_freq_scaling_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (bus_freq_scaling_is_active)
+ return sprintf(buf, "Bus frequency scaling is enabled\n");
+ else
+ return sprintf(buf, "Bus frequency scaling is disabled\n");
+}
+
+static ssize_t bus_freq_scaling_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ u32 reg;
+
+ if (strncmp(buf, "1", 1) == 0) {
+ if (dvfs_per_active()) {
+ printk(KERN_INFO "bus frequency scaling cannot be\
+ enabled when DVFS-PER is active\n");
+ return size;
+ }
+ if (!cpu_is_mx50()) {
+ /* Initialize DVFS-PODF to 0. */
+ reg = __raw_readl(MXC_CCM_CDCR);
+ reg &= ~MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK;
+ __raw_writel(reg, MXC_CCM_CDCR);
+ clk_set_parent(main_bus_clk, pll2);
+ }
+ bus_freq_scaling_is_active = 1;
+ set_high_bus_freq(0);
+ } else if (strncmp(buf, "0", 1) == 0) {
+ if (bus_freq_scaling_is_active)
+ set_high_bus_freq(1);
+ bus_freq_scaling_is_active = 0;
+ }
+
+ return size;
+}
+
+static int busfreq_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ if (low_bus_freq_mode)
+ set_high_bus_freq(1);
+ busfreq_suspended = 1;
+ return 0;
+}
+
+static int busfreq_resume(struct platform_device *pdev)
+{
+ busfreq_suspended = 0;
+ return 0;
+}
+
+static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
+ bus_freq_scaling_enable_store);
+
+/*!
+ * This is the probe routine for the bus frequency driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ *
+ */
+static int __devinit busfreq_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ unsigned long pll2_rate, pll1_rate;
+ unsigned long iram_paddr;
+ struct mxc_bus_freq_platform_data *p_bus_freq_data;
+
+ p_bus_freq_data = pdev->dev.platform_data;
+ gp_reg_id = p_bus_freq_data->gp_reg_id;
+ lp_reg_id = p_bus_freq_data->lp_reg_id;
+
+ pll1_base = ioremap(MX53_BASE_ADDR(PLL1_BASE_ADDR), SZ_4K);
+ if (cpu_is_mx53())
+ pll4_base = ioremap(MX53_BASE_ADDR(PLL4_BASE_ADDR), SZ_4K);
+
+ busfreq_dev = &pdev->dev;
+
+ main_bus_clk = clk_get(NULL, "main_bus_clk");
+ if (IS_ERR(main_bus_clk)) {
+ printk(KERN_DEBUG "%s: failed to get main_bus_clk\n",
+ __func__);
+ return PTR_ERR(main_bus_clk);
+ }
+
+ pll1_sw_clk = clk_get(NULL, "pll1_sw_clk");
+ if (IS_ERR(pll1_sw_clk)) {
+ printk(KERN_DEBUG "%s: failed to get pll1_sw_clk\n", __func__);
+ return PTR_ERR(pll1_sw_clk);
+ }
+
+ pll1 = clk_get(NULL, "pll1_main_clk");
+ if (IS_ERR(pll1)) {
+ printk(KERN_DEBUG "%s: failed to get pll1\n", __func__);
+ return PTR_ERR(pll1);
+ }
+
+ pll2 = clk_get(NULL, "pll2");
+ if (IS_ERR(pll2)) {
+ printk(KERN_DEBUG "%s: failed to get pll2\n", __func__);
+ return PTR_ERR(pll2);
+ }
+
+ pll3 = clk_get(NULL, "pll3");
+ if (IS_ERR(pll3)) {
+ printk(KERN_DEBUG "%s: failed to get pll3\n", __func__);
+ return PTR_ERR(pll3);
+ }
+
+ if (cpu_is_mx53()) {
+ pll4 = clk_get(NULL, "pll4");
+ if (IS_ERR(pll4)) {
+ printk(KERN_DEBUG "%s: failed to get pll4\n", __func__);
+ return PTR_ERR(pll4);
+ }
+ }
+
+ axi_a_clk = clk_get(NULL, "axi_a_clk");
+ if (IS_ERR(axi_a_clk)) {
+ printk(KERN_DEBUG "%s: failed to get axi_a_clk\n",
+ __func__);
+ return PTR_ERR(axi_a_clk);
+ }
+
+ axi_b_clk = clk_get(NULL, "axi_b_clk");
+ if (IS_ERR(axi_b_clk)) {
+ printk(KERN_DEBUG "%s: failed to get axi_b_clk\n",
+ __func__);
+ return PTR_ERR(axi_b_clk);
+ }
+
+ ddr_clk = clk_get(NULL, "ddr_clk");
+ if (IS_ERR(ddr_clk)) {
+ printk(KERN_DEBUG "%s: failed to get ddr_clk\n",
+ __func__);
+ return PTR_ERR(ddr_clk);
+ }
+
+ ddr_hf_clk = clk_get_parent(ddr_clk);
+
+ if (IS_ERR(ddr_hf_clk)) {
+ printk(KERN_DEBUG "%s: failed to get ddr_hf_clk\n",
+ __func__);
+ return PTR_ERR(ddr_hf_clk);
+ }
+
+ ahb_clk = clk_get(NULL, "ahb_clk");
+ if (IS_ERR(ahb_clk)) {
+ printk(KERN_DEBUG "%s: failed to get ahb_clk\n",
+ __func__);
+ return PTR_ERR(ahb_clk);
+ }
+
+ cpu_clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_DEBUG "%s: failed to get cpu_clk\n",
+ __func__);
+ return PTR_ERR(cpu_clk);
+ }
+
+ if (cpu_is_mx51())
+ emi_garb_clk = clk_get(NULL, "emi_intr_clk.1");
+ else if (cpu_is_mx53())
+ emi_garb_clk = clk_get(NULL, "emi_intr_clk.1");
+ else
+ emi_garb_clk = clk_get(NULL, "ocram_clk");
+ if (IS_ERR(emi_garb_clk)) {
+ printk(KERN_DEBUG "%s: failed to get emi_garb_clk\n",
+ __func__);
+ return PTR_ERR(emi_garb_clk);
+ }
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ periph_apm_clk = clk_get(NULL, "periph_apm_clk");
+ if (IS_ERR(periph_apm_clk)) {
+ printk(KERN_DEBUG "%s: failed to get periph_apm_clk\n",
+ __func__);
+ return PTR_ERR(periph_apm_clk);
+ }
+ }
+
+ lp_apm = clk_get(NULL, "lp_apm");
+ if (IS_ERR(lp_apm)) {
+ printk(KERN_DEBUG "%s: failed to get lp_apm\n",
+ __func__);
+ return PTR_ERR(lp_apm);
+ }
+
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk");
+ if (IS_ERR(gpc_dvfs_clk)) {
+ printk(KERN_DEBUG "%s: failed to get gpc_dvfs_clk\n", __func__);
+ return PTR_ERR(gpc_dvfs_clk);
+ }
+
+ err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
+ if (err) {
+ printk(KERN_ERR
+ "Unable to register sysdev entry for BUSFREQ");
+ return err;
+ }
+
+ pll1_rate = clk_get_rate(pll1_sw_clk);
+ pll2_rate = clk_get_rate(pll2);
+
+ if (pll2_rate == 665000000) {
+ /* for mx51 */
+ lp_normal_rate = pll2_rate / 5;
+ lp_med_rate = pll2_rate / 8;
+ ddr_normal_rate = pll1_rate / 4; /* 200M */
+ ddr_low_rate = pll1_rate / 6; /* 133M */
+ } else if (pll2_rate == 600000000) {
+ /* for mx53 evk rev.A */
+ lp_normal_rate = pll2_rate / 5;
+ lp_med_rate = pll2_rate / 8;
+ ddr_normal_rate = pll2_rate / 2;
+ ddr_low_rate = pll2_rate / 2;
+ } else if (pll2_rate == 400000000) {
+ if (cpu_is_mx50()) {
+ lp_normal_rate = pll2_rate / 3;
+ ddr_normal_rate = clk_get_rate(ddr_clk);
+ lp_med_rate = pll2_rate / 6;
+ ddr_low_rate = LP_APM_CLK;
+ ddr_med_rate = pll2_rate / 3;
+ }
+ }
+
+ /* for mx53 */
+ if (cpu_is_mx53()) {
+ /* set DDR type */
+ if (machine_is_mx53_evk() || machine_is_mx53_ard())
+ mx53_ddr_type = DDR_TYPE_DDR2;
+ else
+ mx53_ddr_type = DDR_TYPE_DDR3;
+ if (mx53_ddr_type == DDR_TYPE_DDR2) {
+ /* DDR2 */
+ lp_normal_rate = pll2_rate / 3;
+ lp_med_rate = pll2_rate / 5;
+ ddr_normal_rate = pll2_rate / 1;
+ ddr_low_rate = pll2_rate / 3;
+ } else {
+ /* DDR3: DDR3 frequency can not be lower than 300MHZ */
+ lp_normal_rate = pll2_rate / 3;
+ lp_med_rate = pll2_rate / 5;
+ ddr_normal_rate = pll2_rate / 1;
+ ddr_low_rate = pll2_rate / 1;
+ }
+ }
+
+ if (cpu_is_mx50()) {
+ u32 reg;
+
+ iram_alloc(SZ_8K, &iram_paddr);
+ /* Need to remap the area here since we want the memory region
+ to be executable. */
+ ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
+ SZ_8K, MT_HIGH_VECTORS);
+ memcpy(ddr_freq_change_iram_base, mx50_ddr_freq_change, SZ_8K);
+ change_ddr_freq = (void *)ddr_freq_change_iram_base;
+ cur_ddr_rate = ddr_normal_rate;
+
+ lp_regulator = regulator_get(NULL, lp_reg_id);
+ if (IS_ERR(lp_regulator)) {
+ printk(KERN_DEBUG
+ "%s: failed to get lp regulator\n", __func__);
+ return PTR_ERR(lp_regulator);
+ }
+
+ qosc_base = ioremap(QOSC_BASE_ADDR, SZ_4K);
+ /* Enable the QoSC */
+ reg = __raw_readl(qosc_base);
+ reg &= ~0xC0000000;
+ __raw_writel(reg, qosc_base);
+
+ voltage_wq = create_rt_workqueue("voltage_change");
+ INIT_WORK(&voltage_change_handler, voltage_work_handler);
+
+ init_completion(&voltage_change_cmpl);
+
+ epdc_clk = clk_get(NULL, "epdc_axi");
+ if (IS_ERR(epdc_clk)) {
+ printk(KERN_DEBUG "%s: failed to get epdc_axi_clk\n",
+ __func__);
+ return PTR_ERR(epdc_clk);
+ }
+ }
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ low_bus_freq_mode = 0;
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ bus_freq_scaling_is_active = 0;
+ bus_freq_scaling_initialized = 1;
+
+ mutex_init(&bus_freq_mutex);
+ return 0;
+}
+
+static struct platform_driver busfreq_driver = {
+ .driver = {
+ .name = "busfreq",
+ },
+ .probe = busfreq_probe,
+ .suspend = busfreq_suspend,
+ .resume = busfreq_resume,
+};
+
+/*!
+ * Initialise the busfreq_driver.
+ *
+ * @return The function always returns 0.
+ */
+
+static int __init busfreq_init(void)
+{
+ if (platform_driver_register(&busfreq_driver) != 0) {
+ printk(KERN_ERR "busfreq_driver register failed\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "Bus freq driver module loaded\n");
+ return 0;
+}
+
+static void __exit busfreq_cleanup(void)
+{
+ sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
+
+ /* Unregister the device structure */
+ platform_driver_unregister(&busfreq_driver);
+ bus_freq_scaling_initialized = 0;
+}
+
+module_init(busfreq_init);
+module_exit(busfreq_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("BusFreq driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
deleted file mode 100644
index d9f612d3370e..000000000000
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ /dev/null
@@ -1,871 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * 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/mm.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <asm/clkdev.h>
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/clock.h>
-
-#include "crm_regs.h"
-
-/* External clock values passed-in by the board code */
-static unsigned long external_high_reference, external_low_reference;
-static unsigned long oscillator_reference, ckih2_reference;
-
-static struct clk osc_clk;
-static struct clk pll1_main_clk;
-static struct clk pll1_sw_clk;
-static struct clk pll2_sw_clk;
-static struct clk pll3_sw_clk;
-static struct clk lp_apm_clk;
-static struct clk periph_apm_clk;
-static struct clk ahb_clk;
-static struct clk ipg_clk;
-static struct clk usboh3_clk;
-
-#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
-
-static int _clk_ccgr_enable(struct clk *clk)
-{
- u32 reg;
-
- reg = __raw_readl(clk->enable_reg);
- reg |= MXC_CCM_CCGRx_MOD_ON << clk->enable_shift;
- __raw_writel(reg, clk->enable_reg);
-
- return 0;
-}
-
-static void _clk_ccgr_disable(struct clk *clk)
-{
- u32 reg;
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(MXC_CCM_CCGRx_MOD_OFF << clk->enable_shift);
- __raw_writel(reg, clk->enable_reg);
-
-}
-
-static void _clk_ccgr_disable_inwait(struct clk *clk)
-{
- u32 reg;
-
- reg = __raw_readl(clk->enable_reg);
- reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
- reg |= MXC_CCM_CCGRx_MOD_IDLE << clk->enable_shift;
- __raw_writel(reg, clk->enable_reg);
-}
-
-/*
- * For the 4-to-1 muxed input clock
- */
-static inline u32 _get_mux(struct clk *parent, struct clk *m0,
- struct clk *m1, struct clk *m2, struct clk *m3)
-{
- if (parent == m0)
- return 0;
- else if (parent == m1)
- return 1;
- else if (parent == m2)
- return 2;
- else if (parent == m3)
- return 3;
- else
- BUG();
-
- return -EINVAL;
-}
-
-static inline void __iomem *_get_pll_base(struct clk *pll)
-{
- if (pll == &pll1_main_clk)
- return MX51_DPLL1_BASE;
- else if (pll == &pll2_sw_clk)
- return MX51_DPLL2_BASE;
- else if (pll == &pll3_sw_clk)
- return MX51_DPLL3_BASE;
- else
- BUG();
-
- return NULL;
-}
-
-static unsigned long clk_pll_get_rate(struct clk *clk)
-{
- long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
- unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
- void __iomem *pllbase;
- s64 temp;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- pllbase = _get_pll_base(clk);
-
- dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
- dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
-
- if (pll_hfsm == 0) {
- dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
- dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
- dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
- } else {
- dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
- dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
- dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
- }
- pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
- mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
- mfi = (mfi <= 5) ? 5 : mfi;
- mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
- mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
- /* Sign extend to 32-bits */
- if (mfn >= 0x04000000) {
- mfn |= 0xFC000000;
- mfn_abs = -mfn;
- }
-
- ref_clk = 2 * parent_rate;
- if (dbl != 0)
- ref_clk *= 2;
-
- ref_clk /= (pdf + 1);
- temp = (u64) ref_clk * mfn_abs;
- do_div(temp, mfd + 1);
- if (mfn < 0)
- temp = -temp;
- temp = (ref_clk * mfi) + temp;
-
- return temp;
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg;
- void __iomem *pllbase;
-
- long mfi, pdf, mfn, mfd = 999999;
- s64 temp64;
- unsigned long quad_parent_rate;
- unsigned long pll_hfsm, dp_ctl;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- pllbase = _get_pll_base(clk);
-
- quad_parent_rate = 4 * parent_rate;
- pdf = mfi = -1;
- while (++pdf < 16 && mfi < 5)
- mfi = rate * (pdf+1) / quad_parent_rate;
- if (mfi > 15)
- return -EINVAL;
- pdf--;
-
- temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
- do_div(temp64, quad_parent_rate/1000000);
- mfn = (long)temp64;
-
- dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- /* use dpdck0_2 */
- __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
- pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
- if (pll_hfsm == 0) {
- reg = mfi << 4 | pdf;
- __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
- __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
- __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
- } else {
- reg = mfi << 4 | pdf;
- __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
- __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
- __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
- }
-
- return 0;
-}
-
-static int _clk_pll_enable(struct clk *clk)
-{
- u32 reg;
- void __iomem *pllbase;
- int i = 0;
-
- pllbase = _get_pll_base(clk);
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-
- /* Wait for lock */
- do {
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
- if (reg & MXC_PLL_DP_CTL_LRF)
- break;
-
- udelay(1);
- } while (++i < MAX_DPLL_WAIT_TRIES);
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- pr_err("MX5: pll locking failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void _clk_pll_disable(struct clk *clk)
-{
- u32 reg;
- void __iomem *pllbase;
-
- pllbase = _get_pll_base(clk);
- reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-}
-
-static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg, step;
-
- reg = __raw_readl(MXC_CCM_CCSR);
-
- /* When switching from pll_main_clk to a bypass clock, first select a
- * multiplexed clock in 'step_sel', then shift the glitchless mux
- * 'pll1_sw_clk_sel'.
- *
- * When switching back, do it in reverse order
- */
- if (parent == &pll1_main_clk) {
- /* Switch to pll1_main_clk */
- reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- __raw_writel(reg, MXC_CCM_CCSR);
- /* step_clk mux switched to lp_apm, to save power. */
- reg = __raw_readl(MXC_CCM_CCSR);
- reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
- reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
- MXC_CCM_CCSR_STEP_SEL_OFFSET);
- } else {
- if (parent == &lp_apm_clk) {
- step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
- } else if (parent == &pll2_sw_clk) {
- step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
- } else if (parent == &pll3_sw_clk) {
- step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
- } else
- return -EINVAL;
-
- reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
- reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
-
- __raw_writel(reg, MXC_CCM_CCSR);
- /* Switch to step_clk */
- reg = __raw_readl(MXC_CCM_CCSR);
- reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- }
- __raw_writel(reg, MXC_CCM_CCSR);
- return 0;
-}
-
-static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
-{
- u32 reg, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CCSR);
-
- if (clk->parent == &pll2_sw_clk) {
- div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
- MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
- } else if (clk->parent == &pll3_sw_clk) {
- div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
- MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
- } else
- div = 1;
- return parent_rate / div;
-}
-
-static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CCSR);
-
- if (parent == &pll2_sw_clk)
- reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
- else
- reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-
- __raw_writel(reg, MXC_CCM_CCSR);
- return 0;
-}
-
-static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- if (parent == &osc_clk)
- reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
- else
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_CCSR);
-
- return 0;
-}
-
-static unsigned long clk_arm_get_rate(struct clk *clk)
-{
- u32 cacrr, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
- cacrr = __raw_readl(MXC_CCM_CACRR);
- div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
-
- return parent_rate / div;
-}
-
-static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg, mux;
- int i = 0;
-
- mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
-
- reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
- reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
- __raw_writel(reg, MXC_CCM_CBCMR);
-
- /* Wait for lock */
- do {
- reg = __raw_readl(MXC_CCM_CDHIPR);
- if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
- break;
-
- udelay(1);
- } while (++i < MAX_DPLL_WAIT_TRIES);
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- pr_err("MX5: Set parent for periph_apm clock failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
-
- if (parent == &pll2_sw_clk)
- reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
- else if (parent == &periph_apm_clk)
- reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
- else
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- return 0;
-}
-
-static struct clk main_bus_clk = {
- .parent = &pll2_sw_clk,
- .set_parent = _clk_main_bus_set_parent,
-};
-
-static unsigned long clk_ahb_get_rate(struct clk *clk)
-{
- u32 reg, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
- MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
- return parent_rate / div;
-}
-
-
-static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
-{
- u32 reg, div;
- unsigned long parent_rate;
- int i = 0;
-
- parent_rate = clk_get_rate(clk->parent);
-
- div = parent_rate / rate;
- if (div > 8 || div < 1 || ((parent_rate / div) != rate))
- return -EINVAL;
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
- reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- /* Wait for lock */
- do {
- reg = __raw_readl(MXC_CCM_CDHIPR);
- if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
- break;
-
- udelay(1);
- } while (++i < MAX_DPLL_WAIT_TRIES);
-
- if (i == MAX_DPLL_WAIT_TRIES) {
- pr_err("MX5: clk_ahb_set_rate failed\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned long _clk_ahb_round_rate(struct clk *clk,
- unsigned long rate)
-{
- u32 div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- div = parent_rate / rate;
- if (div > 8)
- div = 8;
- else if (div == 0)
- div++;
- return parent_rate / div;
-}
-
-
-static int _clk_max_enable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_enable(clk);
-
- /* Handshake with MAX when LPM is entered. */
- reg = __raw_readl(MXC_CCM_CLPCR);
- reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-
- return 0;
-}
-
-static void _clk_max_disable(struct clk *clk)
-{
- u32 reg;
-
- _clk_ccgr_disable_inwait(clk);
-
- /* No Handshake with MAX when LPM is entered as its disabled. */
- reg = __raw_readl(MXC_CCM_CLPCR);
- reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
- __raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static unsigned long clk_ipg_get_rate(struct clk *clk)
-{
- u32 reg, div;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CBCDR);
- div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
- MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
-
- return parent_rate / div;
-}
-
-static unsigned long clk_ipg_per_get_rate(struct clk *clk)
-{
- u32 reg, prediv1, prediv2, podf;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
- /* the main_bus_clk is the one before the DVFS engine */
- reg = __raw_readl(MXC_CCM_CBCDR);
- prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
- MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
- prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
- MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
- podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
- MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
- return parent_rate / (prediv1 * prediv2 * podf);
- } else if (clk->parent == &ipg_clk)
- return parent_rate;
- else
- BUG();
-}
-
-static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg;
-
- reg = __raw_readl(MXC_CCM_CBCMR);
-
- reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
- reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-
- if (parent == &ipg_clk)
- reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
- else if (parent == &lp_apm_clk)
- reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
- else if (parent != &main_bus_clk)
- return -EINVAL;
-
- __raw_writel(reg, MXC_CCM_CBCMR);
-
- return 0;
-}
-
-static unsigned long clk_uart_get_rate(struct clk *clk)
-{
- u32 reg, prediv, podf;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CSCDR1);
- prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
- MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
- podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
- MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
-
- return parent_rate / (prediv * podf);
-}
-
-static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg, mux;
-
- mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
- &lp_apm_clk);
- reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
- reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-static unsigned long clk_usboh3_get_rate(struct clk *clk)
-{
- u32 reg, prediv, podf;
- unsigned long parent_rate;
-
- parent_rate = clk_get_rate(clk->parent);
-
- reg = __raw_readl(MXC_CCM_CSCDR1);
- prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
- MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
- podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
- MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
-
- return parent_rate / (prediv * podf);
-}
-
-static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
-{
- u32 reg, mux;
-
- mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
- &lp_apm_clk);
- reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
- reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
- __raw_writel(reg, MXC_CCM_CSCMR1);
-
- return 0;
-}
-
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
-{
- return external_high_reference;
-}
-
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
-{
- return external_low_reference;
-}
-
-static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
-{
- return oscillator_reference;
-}
-
-static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
-{
- return ckih2_reference;
-}
-
-/* External high frequency clock */
-static struct clk ckih_clk = {
- .get_rate = get_high_reference_clock_rate,
-};
-
-static struct clk ckih2_clk = {
- .get_rate = get_ckih2_reference_clock_rate,
-};
-
-static struct clk osc_clk = {
- .get_rate = get_oscillator_reference_clock_rate,
-};
-
-/* External low frequency (32kHz) clock */
-static struct clk ckil_clk = {
- .get_rate = get_low_reference_clock_rate,
-};
-
-static struct clk pll1_main_clk = {
- .parent = &osc_clk,
- .get_rate = clk_pll_get_rate,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* Clock tree block diagram (WIP):
- * CCM: Clock Controller Module
- *
- * PLL output -> |
- * | CCM Switcher -> CCM_CLK_ROOT_GEN ->
- * PLL bypass -> |
- *
- */
-
-/* PLL1 SW supplies to ARM core */
-static struct clk pll1_sw_clk = {
- .parent = &pll1_main_clk,
- .set_parent = _clk_pll1_sw_set_parent,
- .get_rate = clk_pll1_sw_get_rate,
-};
-
-/* PLL2 SW supplies to AXI/AHB/IP buses */
-static struct clk pll2_sw_clk = {
- .parent = &osc_clk,
- .get_rate = clk_pll_get_rate,
- .set_rate = _clk_pll_set_rate,
- .set_parent = _clk_pll2_sw_set_parent,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
-static struct clk pll3_sw_clk = {
- .parent = &osc_clk,
- .set_rate = _clk_pll_set_rate,
- .get_rate = clk_pll_get_rate,
- .enable = _clk_pll_enable,
- .disable = _clk_pll_disable,
-};
-
-/* Low-power Audio Playback Mode clock */
-static struct clk lp_apm_clk = {
- .parent = &osc_clk,
- .set_parent = _clk_lp_apm_set_parent,
-};
-
-static struct clk periph_apm_clk = {
- .parent = &pll1_sw_clk,
- .set_parent = _clk_periph_apm_set_parent,
-};
-
-static struct clk cpu_clk = {
- .parent = &pll1_sw_clk,
- .get_rate = clk_arm_get_rate,
-};
-
-static struct clk ahb_clk = {
- .parent = &main_bus_clk,
- .get_rate = clk_ahb_get_rate,
- .set_rate = _clk_ahb_set_rate,
- .round_rate = _clk_ahb_round_rate,
-};
-
-/* Main IP interface clock for access to registers */
-static struct clk ipg_clk = {
- .parent = &ahb_clk,
- .get_rate = clk_ipg_get_rate,
-};
-
-static struct clk ipg_perclk = {
- .parent = &lp_apm_clk,
- .get_rate = clk_ipg_per_get_rate,
- .set_parent = _clk_ipg_per_set_parent,
-};
-
-static struct clk uart_root_clk = {
- .parent = &pll2_sw_clk,
- .get_rate = clk_uart_get_rate,
- .set_parent = _clk_uart_set_parent,
-};
-
-static struct clk usboh3_clk = {
- .parent = &pll2_sw_clk,
- .get_rate = clk_usboh3_get_rate,
- .set_parent = _clk_usboh3_set_parent,
-};
-
-static struct clk ahb_max_clk = {
- .parent = &ahb_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
- .enable = _clk_max_enable,
- .disable = _clk_max_disable,
-};
-
-static struct clk aips_tz1_clk = {
- .parent = &ahb_clk,
- .secondary = &ahb_max_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk aips_tz2_clk = {
- .parent = &ahb_clk,
- .secondary = &ahb_max_clk,
- .enable_reg = MXC_CCM_CCGR0,
- .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
- .enable = _clk_ccgr_enable,
- .disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk gpt_32k_clk = {
- .id = 0,
- .parent = &ckil_clk,
-};
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \
- static struct clk name = { \
- .id = i, \
- .enable_reg = er, \
- .enable_shift = es, \
- .get_rate = gr, \
- .set_rate = sr, \
- .enable = _clk_ccgr_enable, \
- .disable = _clk_ccgr_disable, \
- .parent = p, \
- .secondary = s, \
- }
-
-/* DEFINE_CLOCK(name, id, enable_reg, enable_shift,
- get_rate, set_rate, parent, secondary); */
-
-/* Shared peripheral bus arbiter */
-DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-
-/* UART */
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
- NULL, NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
- NULL, NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
- NULL, NULL, &uart_root_clk, NULL);
-DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
- NULL, NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
- NULL, NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
- NULL, NULL, &ipg_clk, &spba_clk);
-
-/* GPT */
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-
-/* FEC */
-DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
- NULL, NULL, &ipg_clk, NULL);
-
-#define _REGISTER_CLOCK(d, n, c) \
- { \
- .dev_id = d, \
- .con_id = n, \
- .clk = &c, \
- },
-
-static struct clk_lookup lookups[] = {
- _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
- _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
- _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
- _REGISTER_CLOCK(NULL, "gpt", gpt_clk)
- _REGISTER_CLOCK("fec.0", NULL, fec_clk)
- _REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
- _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk)
- _REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
- _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk)
- _REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
- _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-};
-
-static void clk_tree_init(void)
-{
- u32 reg;
-
- ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
-
- /*
- * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
- * 8MHz, its derived from lp_apm.
- *
- * FIXME: Verify if true for all boards
- */
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
- reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
- reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
- reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
- __raw_writel(reg, MXC_CCM_CBCDR);
-}
-
-int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
- unsigned long ckih1, unsigned long ckih2)
-{
- int i;
-
- external_low_reference = ckil;
- external_high_reference = ckih1;
- ckih2_reference = ckih2;
- oscillator_reference = osc;
-
- for (i = 0; i < ARRAY_SIZE(lookups); i++)
- clkdev_add(&lookups[i]);
-
- clk_tree_init();
-
- clk_enable(&cpu_clk);
- clk_enable(&main_bus_clk);
-
- /* set the usboh3_clk parent to pll2_sw_clk */
- clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-
- /* System timer */
- mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
- MX51_MXC_INT_GPT);
- return 0;
-}
diff --git a/arch/arm/mach-mx5/clock.c b/arch/arm/mach-mx5/clock.c
new file mode 100644
index 000000000000..8c91002f4149
--- /dev/null
+++ b/arch/arm/mach-mx5/clock.c
@@ -0,0 +1,5140 @@
+/*
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/sdram_autogating.h>
+
+#include "crm_regs.h"
+#include "serial.h"
+#include "mx53_wp.h"
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+
+static struct clk pll1_main_clk;
+static struct clk pll1_sw_clk;
+static struct clk pll2_sw_clk;
+static struct clk pll3_sw_clk;
+static struct clk pll4_sw_clk;
+static struct clk lp_apm_clk;
+static struct clk tve_clk;
+static struct clk emi_fast_clk;
+static struct clk emi_slow_clk;
+static struct clk emi_intr_clk[];
+static struct clk ddr_clk;
+static struct clk ipu_clk[];
+static struct clk ldb_di_clk[];
+static struct clk axi_a_clk;
+static struct clk axi_b_clk;
+static struct clk ddr_hf_clk;
+static struct clk mipi_hsp_clk;
+static struct clk gpu3d_clk;
+static struct clk gpu2d_clk;
+static struct clk vpu_clk[];
+static int cpu_curr_wp;
+static struct cpu_wp *cpu_wp_tbl;
+
+static void __iomem *pll1_base;
+static void __iomem *pll2_base;
+static void __iomem *pll3_base;
+static void __iomem *pll4_base;
+
+extern int cpu_wp_nr;
+extern int lp_high_freq;
+extern int lp_med_freq;
+static int max_axi_a_clk;
+static int max_axi_b_clk;
+static int max_ahb_clk;
+static int max_emi_slow_clk;
+extern int dvfs_core_is_active;
+
+#define SPIN_DELAY 1000000 /* in nanoseconds */
+#define MAX_AXI_A_CLK_MX51 166250000
+#define MAX_AXI_A_CLK_MX53 400000000
+#define MAX_AXI_B_CLK_MX51 133000000
+#define MAX_AXI_B_CLK_MX53 200000000
+#define MAX_AHB_CLK_MX51 133000000
+#define MAX_EMI_SLOW_CLK_MX51 133000000
+#define MAX_AHB_CLK_MX53 133333333
+#define MAX_EMI_SLOW_CLK_MX53 133333333
+#define MAX_DDR_HF_RATE 200000000
+/* To keep compatible with some NAND flash, limit
+ * max NAND clk to 34MHZ. The user can modify it for
+ * dedicate NAND flash */
+#define MAX_NFC_CLK 34000000
+
+extern int mxc_jtag_enabled;
+extern int uart_at_24;
+extern int cpufreq_trig_needed;
+extern int low_bus_freq_mode;
+
+static int cpu_clk_set_wp(int wp);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+
+static struct clk esdhc3_clk[];
+
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
+{
+ u32 min_pre, temp_pre, old_err, err;
+
+ if (div >= 512) {
+ *pre = 8;
+ *post = 64;
+ } else if (div >= 8) {
+ min_pre = (div - 1) / 64 + 1;
+ old_err = 8;
+ for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+ err = div % temp_pre;
+ if (err == 0) {
+ *pre = temp_pre;
+ break;
+ }
+ err = temp_pre - err;
+ if (err < old_err) {
+ old_err = err;
+ *pre = temp_pre;
+ }
+ }
+ *post = (div + *pre - 1) / *pre;
+ } else if (div < 8) {
+ *pre = div;
+ *post = 1;
+ }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg |= MXC_CCM_CCGRx_CG_MASK << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq++;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq++;
+
+ return 0;
+}
+
+static int _clk_enable_inrun(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+ return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq--;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq--;
+}
+
+static void _clk_disable_inwait(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+ struct clk *m1, struct clk *m2, struct clk *m3)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else
+ BUG();
+
+ return 0;
+}
+
+/*
+ * For the ddr muxed input clock
+ */
+static inline u32 _get_mux_ddr(struct clk *parent, struct clk *m0,
+ struct clk *m1, struct clk *m2, struct clk *m3, struct clk *m4)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else if (parent == m4)
+ return 4;
+ else
+ BUG();
+
+ return 0;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+ if (pll == &pll1_main_clk)
+ return pll1_base;
+ else if (pll == &pll2_sw_clk)
+ return pll2_base;
+ else if (pll == &pll3_sw_clk)
+ return pll3_base;
+ else if (pll == &pll4_sw_clk)
+ return pll4_base;
+ else
+ BUG();
+
+ return NULL;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+ return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+ return external_low_reference;
+}
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+ return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+ return ckih2_reference;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+ .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static unsigned long _fpm_get_rate(struct clk *clk)
+{
+ u32 rate = ckil_clk.get_rate(&ckil_clk) * 512;
+ if ((__raw_readl(MXC_CCM_CCR) & MXC_CCM_CCR_FPM_MULT_MASK) != 0)
+ rate *= 2;
+ return rate;
+}
+
+static int _fpm_enable(struct clk *clk)
+{
+ u32 reg = __raw_readl(MXC_CCM_CCR);
+ reg |= MXC_CCM_CCR_FPM_EN;
+ __raw_writel(reg, MXC_CCM_CCR);
+ return 0;
+}
+
+static void _fpm_disable(struct clk *clk)
+{
+ u32 reg = __raw_readl(MXC_CCM_CCR);
+ reg &= ~MXC_CCM_CCR_FPM_EN;
+ __raw_writel(reg, MXC_CCM_CCR);
+}
+
+static struct clk fpm_clk = {
+ .parent = &ckil_clk,
+ .get_rate = _fpm_get_rate,
+ .enable = _fpm_enable,
+ .disable = _fpm_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _fpm_div2_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk fpm_div2_clk = {
+ .parent = &fpm_clk,
+ .get_rate = _fpm_div2_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_pll_get_rate(struct clk *clk)
+{
+ long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+ unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+ void __iomem *pllbase;
+ s64 temp;
+
+ pllbase = _get_pll_base(clk);
+
+ dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+ dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+ if (pll_hfsm == 0) {
+ dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+ dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+ dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+ } else {
+ dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+ dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+ dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+ }
+ pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+ mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+ mfi = (mfi <= 5) ? 5 : mfi;
+ mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+ mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+ /* Sign extend to 32-bits */
+ if (mfn >= 0x04000000) {
+ mfn |= 0xFC000000;
+ mfn_abs = -mfn;
+ }
+
+ ref_clk = 2 * clk_get_rate(clk->parent);
+ if (dbl != 0)
+ ref_clk *= 2;
+
+ ref_clk /= (pdf + 1);
+ temp = (u64) ref_clk * mfn_abs;
+ do_div(temp, mfd + 1);
+ if (mfn < 0)
+ temp = -temp;
+ temp = (ref_clk * mfi) + temp;
+
+ return temp;
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, reg1;
+ void __iomem *pllbase;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+ long mfi, pdf, mfn, mfd = 999999;
+ s64 temp64;
+ unsigned long quad_parent_rate;
+ unsigned long pll_hfsm, dp_ctl;
+
+ pllbase = _get_pll_base(clk);
+
+ quad_parent_rate = 4 * clk_get_rate(clk->parent);
+ pdf = mfi = -1;
+ while (++pdf < 16 && mfi < 5)
+ mfi = rate * (pdf+1) / quad_parent_rate;
+ if (mfi > 15)
+ return -1;
+ pdf--;
+
+ temp64 = rate*(pdf+1) - quad_parent_rate*mfi;
+ do_div(temp64, quad_parent_rate/1000000);
+ mfn = (long)temp64;
+
+ dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ /* use dpdck0_2 */
+ __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+ pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+ if (pll_hfsm == 0) {
+ reg = mfi<<4 | pdf;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+ __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+ __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+ } else {
+ reg = mfi<<4 | pdf;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+ __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+ __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+ }
+ /* If auto restart is disabled, restart the PLL and
+ * wait for it to lock.
+ */
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ if (reg & MXC_PLL_DP_CTL_UPEN) {
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CONFIG);
+ if (!(reg & MXC_PLL_DP_CONFIG_AREN)) {
+ reg1 = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ reg1 |= MXC_PLL_DP_CTL_RST;
+ __raw_writel(reg1, pllbase + MXC_PLL_DP_CTL);
+ }
+ /* Wait for lock */
+ getnstimeofday(&nstimeofday);
+ while (!(__raw_readl(pllbase + MXC_PLL_DP_CTL)
+ & MXC_PLL_DP_CTL_LRF)) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("pll_set_rate: pll relock failed\n");
+ }
+ }
+ return 0;
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+ u32 reg;
+ void __iomem *pllbase;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+ pllbase = _get_pll_base(clk);
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+
+ if (reg & MXC_PLL_DP_CTL_UPEN)
+ return 0;
+
+ reg |= MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+ /* Wait for lock */
+ getnstimeofday(&nstimeofday);
+ while (!(__raw_readl(pllbase + MXC_PLL_DP_CTL) & MXC_PLL_DP_CTL_LRF)) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("pll relock failed\n");
+ }
+ return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+ u32 reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static struct clk pll1_main_clk = {
+ .parent = &osc_clk,
+ .get_rate = _clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll1_main_clk) {
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set the step_clk parent to be lp_apm, to save power. */
+ mux = _get_mux(&lp_apm_clk, &lp_apm_clk, NULL, &pll2_sw_clk,
+ &pll3_sw_clk);
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) |
+ (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ } else {
+ if (parent == &lp_apm_clk) {
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ reg = __raw_readl(MXC_CCM_CCSR);
+ mux = _get_mux(parent, &lp_apm_clk, NULL, &pll2_sw_clk,
+ &pll3_sw_clk);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) |
+ (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ } else {
+ mux = _get_mux(parent, &lp_apm_clk, NULL, &pll2_sw_clk,
+ &pll3_sw_clk);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) |
+ (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCSR);
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+
+ }
+ }
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ return 0;
+}
+
+static unsigned long _clk_pll1_sw_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ div = 1;
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (clk->parent == &pll2_sw_clk) {
+ div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+ MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+ } else if (clk->parent == &pll3_sw_clk) {
+ div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+ MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+/* pll1 switch clock */
+static struct clk pll1_sw_clk = {
+ .parent = &pll1_main_clk,
+ .set_parent = _clk_pll1_sw_set_parent,
+ .get_rate = _clk_pll1_sw_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll2_sw_clk) {
+ reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+ } else {
+ reg = (reg & ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL);
+ reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+ }
+ __raw_writel(reg, MXC_CCM_CCSR);
+ return 0;
+}
+
+/* same as pll2_main_clk. These two clocks should always be the same */
+static struct clk pll2_sw_clk = {
+ .parent = &osc_clk,
+ .get_rate = _clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_pll_set_rate,
+ .set_parent = _clk_pll2_sw_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_sw_clk = {
+ .parent = &osc_clk,
+ .set_rate = _clk_pll_set_rate,
+ .get_rate = _clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+/* same as pll4_main_clk. These two clocks should always be the same */
+static struct clk pll4_sw_clk = {
+ .parent = &osc_clk,
+ .set_rate = _clk_pll_set_rate,
+ .get_rate = _clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ if (parent == &osc_clk)
+ reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+ else if (parent == &fpm_clk)
+ reg = __raw_readl(MXC_CCM_CCSR) | MXC_CCM_CCSR_LP_APM_SEL;
+ else
+ return -EINVAL;
+
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ return 0;
+}
+
+static struct clk lp_apm_clk = {
+ .parent = &osc_clk,
+ .set_parent = _clk_lp_apm_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_arm_get_rate(struct clk *clk)
+{
+ u32 cacrr, div;
+
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 i;
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (rate == cpu_wp_tbl[i].cpu_rate)
+ break;
+ }
+ if (i >= cpu_wp_nr)
+ return -EINVAL;
+ cpu_clk_set_wp(i);
+
+ return 0;
+}
+
+static unsigned long _clk_cpu_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 i;
+ u32 wp;
+
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (rate == cpu_wp_tbl[i].cpu_rate)
+ break;
+ }
+
+ if (i > cpu_wp_nr)
+ wp = 0;
+
+ return cpu_wp_tbl[wp].cpu_rate;
+}
+
+
+static struct clk cpu_clk = {
+ .parent = &pll1_sw_clk,
+ .get_rate = _clk_arm_get_rate,
+ .set_rate = _clk_cpu_set_rate,
+ .round_rate = _clk_cpu_round_rate,
+};
+
+static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+
+ reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("pll _clk_periph_apm_set_parent failed\n");
+ }
+ return 0;
+}
+
+static struct clk periph_apm_clk = {
+ .parent = &pll1_sw_clk,
+ .set_parent = _clk_periph_apm_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+/* TODO: Need to sync with GPC to determine if DVFS is in place so that
+ * the DVFS_PODF divider can be applied in CDCR register.
+ */
+static unsigned long _clk_main_bus_get_rate(struct clk *clk)
+{
+ u32 div = 0;
+
+ if (dvfs_per_divider_active() || low_bus_freq_mode)
+ div = (__raw_readl(MXC_CCM_CDCR) & 0x3);
+ return clk_get_rate(clk->parent) / (div + 1);
+}
+
+static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+ if (parent == &pll2_sw_clk) {
+ reg = __raw_readl(MXC_CCM_CBCDR) &
+ ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ } else if (parent == &periph_apm_clk) {
+ reg = __raw_readl(MXC_CCM_CBCDR) | MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+ } else {
+ return -EINVAL;
+ }
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static struct clk main_bus_clk = {
+ .parent = &pll2_sw_clk,
+ .set_parent = _clk_main_bus_set_parent,
+ .get_rate = _clk_main_bus_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_axi_a_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AXI_A_PODF_MASK) >>
+ MXC_CCM_CBCDR_AXI_A_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_axi_a_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AXI_A_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AXI_A_PODF_BUSY) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("pll _clk_axi_a_set_rate failed\n");
+ }
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static unsigned long _clk_axi_a_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (parent_rate / div > max_axi_a_clk)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+
+static struct clk axi_a_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = _clk_axi_a_get_rate,
+ .set_rate = _clk_axi_a_set_rate,
+ .round_rate = _clk_axi_a_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
+ MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_ddr_hf_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (parent_rate / div > MAX_DDR_HF_RATE)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+static int _clk_ddr_hf_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_DDR_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_DDR_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_DDR_PODF_BUSY) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("clk_ddr_hf_set_rate failed\n");
+ }
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static struct clk ddr_hf_clk = {
+ .parent = &pll1_sw_clk,
+ .get_rate = _clk_ddr_hf_get_rate,
+ .round_rate = _clk_ddr_hf_round_rate,
+ .set_rate = _clk_ddr_hf_set_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_axi_b_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AXI_B_PODF_MASK) >>
+ MXC_CCM_CBCDR_AXI_B_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_axi_b_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AXI_B_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AXI_B_PODF_BUSY) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("_clk_axi_b_set_rate failed\n");
+ }
+
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static unsigned long _clk_axi_b_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (parent_rate / div > max_axi_b_clk)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+
+static struct clk axi_b_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = _clk_axi_b_get_rate,
+ .set_rate = _clk_axi_b_set_rate,
+ .round_rate = _clk_axi_b_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_ahb_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+ MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AHB_PODF_BUSY) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec > SPIN_DELAY)
+ panic("_clk_ahb_set_rate failed\n");
+ }
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (parent_rate / div > max_ahb_clk)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+
+static struct clk ahb_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = _clk_ahb_get_rate,
+ .set_rate = _clk_ahb_set_rate,
+ .round_rate = _clk_ahb_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_max_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+
+ /* Handshake with MAX when LPM is entered. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ if (cpu_is_mx51())
+ reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX51;
+ else
+ reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+
+static void _clk_max_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_disable_inwait(clk);
+
+ /* No Handshake with MAX when LPM is entered as its disabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ if (cpu_is_mx51())
+ reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX51;
+ else
+ reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+
+static struct clk ahb_max_clk = {
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+};
+
+static int _clk_emi_slow_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ if (parent == &ahb_clk) {
+ reg |= MXC_CCM_CBCDR_EMI_CLK_SEL;
+ } else if (parent == &main_bus_clk) {
+ reg &= ~MXC_CCM_CBCDR_EMI_CLK_SEL;
+ } else {
+ BUG();
+ }
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static unsigned long _clk_emi_slow_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+ MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_emi_slow_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_EMI_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_EMI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_EMI_PODF_BUSY) {
+ getnstimeofday(&curtime);
+ if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY)
+ panic("_clk_emi_slow_set_rate failed\n");
+ }
+
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+
+ return 0;
+}
+
+static unsigned long _clk_emi_slow_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (parent_rate / div > max_emi_slow_clk)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+
+static struct clk emi_slow_clk = {
+ .parent = &main_bus_clk,
+ .set_parent = _clk_emi_slow_set_parent,
+ .get_rate = _clk_emi_slow_get_rate,
+ .set_rate = _clk_emi_slow_set_rate,
+ .round_rate = _clk_emi_slow_round_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .disable = _clk_disable_inwait,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk ahbmux1_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk ahbmux2_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .disable = _clk_disable_inwait,
+};
+
+
+static struct clk emi_fast_clk = {
+ .parent = &ddr_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk emi_intr_clk[] = {
+ {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahbmux2_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+ },
+ {
+ /* On MX51 - this clock is name emi_garb_clk, and controls the
+ * access of ARM to GARB.
+ */
+ .id = 1,
+ .parent = &ahb_clk,
+ .secondary = &ahbmux2_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+ }
+};
+
+static unsigned long _clk_ipg_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+ MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static struct clk ipg_clk = {
+ .parent = &ahb_clk,
+ .get_rate = _clk_ipg_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_ipg_per_get_rate(struct clk *clk)
+{
+ u32 reg, prediv1, prediv2, podf;
+
+ if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+ /* the main_bus_clk is the one before the DVFS engine */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
+ prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / (prediv1 * prediv2 * podf);
+ } else if (clk->parent == &ipg_clk) {
+ return clk_get_rate(&ipg_clk);
+ }
+ BUG();
+ return 0;
+}
+
+static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &main_bus_clk, &lp_apm_clk, &ipg_clk, NULL);
+ if (mux == 2) {
+ reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+ } else {
+ reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+ if (mux == 0)
+ reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+ else
+ reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+ }
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk ipg_perclk = {
+ .parent = &lp_apm_clk,
+ .get_rate = _clk_ipg_per_get_rate,
+ .set_parent = _clk_ipg_per_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_ipmux_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+
+ return 0;
+}
+
+static void _clk_ipmux_disable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(0x1 << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static struct clk ipumux1_clk = {
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGR5_CG6_1_OFFSET,
+ .enable = _clk_ipmux_enable,
+ .disable = _clk_ipmux_disable,
+};
+
+static struct clk ipumux2_clk = {
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGR5_CG6_2_OFFSET,
+ .enable = _clk_ipmux_enable,
+ .disable = _clk_ipmux_disable,
+};
+
+static int _clk_ocram_enable(struct clk *clk)
+{
+ return 0;
+}
+
+static void _clk_ocram_disable(struct clk *clk)
+{
+}
+
+static struct clk ocram_clk = {
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_ocram_enable,
+ .disable = _clk_ocram_disable,
+};
+
+
+static struct clk aips_tz1_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk aips_tz2_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk gpc_dvfs_clk = {
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static int _clk_sdma_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+
+ /* Handshake with SDMA when LPM is entered. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ if (cpu_is_mx51())
+ reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX51;
+ else
+ reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static void _clk_sdma_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_disable(clk);
+ /* No handshake with SDMA as its not enabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ if (cpu_is_mx51())
+ reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX51;
+ else
+ reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+
+static struct clk sdma_clk[] = {
+ {
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .enable = _clk_sdma_enable,
+ .disable = _clk_sdma_disable,
+ },
+ {
+ .parent = &ipg_clk,
+#ifdef CONFIG_SDMA_IRAM
+ .secondary = &emi_intr_clk[0],
+#endif
+ },
+};
+
+static int _clk_ipu_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+ /* Handshake with IPU when certain clock rates are changed. */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ if (cpu_is_mx51())
+ reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+ else
+ reg &= ~MXC_CCM_CCDR_IPU_HS_MX53_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ /* Handshake with IPU when LPM is entered as its enabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ start_sdram_autogating();
+
+ return 0;
+}
+
+static void _clk_ipu_disable(struct clk *clk)
+{
+ u32 reg;
+
+ if (sdram_autogating_active())
+ stop_sdram_autogating();
+
+ _clk_disable(clk);
+
+ /* No handshake with IPU whe dividers are changed
+ * as its not enabled. */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ if (cpu_is_mx51())
+ reg |= MXC_CCM_CCDR_IPU_HS_MASK;
+ else
+ reg |= MXC_CCM_CCDR_IPU_HS_MX53_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ /* No handshake with IPU when LPM is entered as its not enabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static int _clk_ipu_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &ahb_clk,
+ &emi_slow_clk);
+ reg = (reg & ~MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+
+static struct clk ipu_clk[] = {
+ {
+ .parent = &ahb_clk,
+ .secondary = &ipu_clk[1],
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_ipu_enable,
+ .disable = _clk_ipu_disable,
+ .set_parent = _clk_ipu_set_parent,
+ .flags = CPU_FREQ_TRIG_UPDATE | AHB_MED_SET_POINT | RATE_PROPAGATES,
+ },
+ {
+ .parent = &emi_fast_clk,
+ .secondary = &ahbmux1_clk,
+ }
+};
+
+static int _clk_ipu_di_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ reg &= ~MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(clk->id);
+ if (parent == &pll3_sw_clk)
+ ;
+ else if (parent == &osc_clk)
+ reg |= 1 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ else if (parent == &ckih_clk)
+ reg |= 2 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ else if ((parent == &pll4_sw_clk) && (clk->id == 0)) {
+ if (cpu_is_mx51())
+ return -EINVAL;
+ reg |= 3 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ } else if ((parent == &tve_clk) && (clk->id == 1))
+ reg |= 3 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ else if ((parent == &ldb_di_clk[clk->id]) && cpu_is_mx53())
+ reg |= 5 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ else /* Assume any other clock is external clock pin */
+ reg |= 4 << MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static int priv_div;
+static unsigned long _clk_ipu_di_get_rate(struct clk *clk)
+{
+ u32 reg, mux;
+ u32 div = 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ mux = (reg & MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(clk->id)) >>
+ MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(clk->id);
+ if (mux == 0) {
+ reg = __raw_readl(MXC_CCM_CDCDR) &
+ MXC_CCM_CDCDR_DI1_CLK_PRED_MASK;
+ div = (reg >> MXC_CCM_CDCDR_DI1_CLK_PRED_OFFSET) + 1;
+ } else if ((mux == 3) && (clk->id == 1)) {
+ if (priv_div)
+ div = priv_div;
+ } else if ((mux == 3) && (clk->id == 0)) {
+ reg = __raw_readl(MXC_CCM_CDCDR) &
+ MXC_CCM_CDCDR_DI_PLL4_PODF_MASK;
+ div = (reg >> MXC_CCM_CDCDR_DI_PLL4_PODF_OFFSET) + 1;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ipu_di_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ if ((clk->parent == &pll4_sw_clk) && (clk->id == 0)) {
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~MXC_CCM_CDCDR_DI_PLL4_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CDCDR_DI_PLL4_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+ } else if (clk->parent == &pll3_sw_clk) {
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~MXC_CCM_CDCDR_DI1_CLK_PRED_MASK;
+ reg |= (div - 1) << MXC_CCM_CDCDR_DI1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+ } else if (((clk->parent == &tve_clk) && (clk->id == 1)) ||
+ ((clk->parent == &ldb_di_clk[clk->id]) && cpu_is_mx53())) {
+ priv_div = div;
+ return 0;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static unsigned long _clk_ipu_di_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if ((clk->parent == &ldb_di_clk[clk->id]) && cpu_is_mx53())
+ return parent_rate;
+ else {
+ div = (parent_rate + rate/2) / rate;
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+ return parent_rate / div;
+ }
+}
+
+static struct clk ipu_di_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .get_rate = _clk_ipu_di_get_rate,
+ .set_parent = _clk_ipu_di_set_parent,
+ .round_rate = _clk_ipu_di_round_rate,
+ .set_rate = _clk_ipu_di_set_rate,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .flags = RATE_PROPAGATES,
+ },
+ {
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .get_rate = _clk_ipu_di_get_rate,
+ .set_parent = _clk_ipu_di_set_parent,
+ .round_rate = _clk_ipu_di_round_rate,
+ .set_rate = _clk_ipu_di_set_rate,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .flags = RATE_PROPAGATES,
+ },
+};
+
+static int _clk_ldb_di_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+
+ if ((parent == &pll3_sw_clk)) {
+ if (clk->id == 0)
+ reg &= ~(MXC_CCM_CSCMR2_LDB_DI0_CLK_SEL);
+ else
+ reg &= ~(MXC_CCM_CSCMR2_LDB_DI1_CLK_SEL);
+ } else if ((parent == &pll4_sw_clk)) {
+ if (clk->id == 0)
+ reg |= MXC_CCM_CSCMR2_LDB_DI0_CLK_SEL;
+ else
+ reg |= MXC_CCM_CSCMR2_LDB_DI1_CLK_SEL;
+ } else {
+ BUG();
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+ return 0;
+}
+
+static unsigned long _clk_ldb_di_get_rate(struct clk *clk)
+{
+ u32 div;
+
+ if (clk->id == 0)
+ div = __raw_readl(MXC_CCM_CSCMR2) &
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
+ else
+ div = __raw_readl(MXC_CCM_CSCMR2) &
+ MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
+
+ if (div)
+ return clk_get_rate(clk->parent) / 7;
+
+ return (2 * clk_get_rate(clk->parent)) / 7;
+}
+
+static unsigned long _clk_ldb_di_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (rate * 7 <= parent_rate + parent_rate/20)
+ return parent_rate / 7;
+ else
+ return 2 * parent_rate / 7;
+}
+
+static int _clk_ldb_di_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div = 0;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (rate * 7 <= parent_rate + parent_rate/20) {
+ div = 7;
+ rate = parent_rate / 7;
+ } else
+ rate = 2 * parent_rate / 7;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (div == 7)
+ reg |= (clk->id ? MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV :
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+ else
+ reg &= ~(clk->id ? MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV :
+ MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static int _clk_ldb_di_enable(struct clk *clk)
+{
+ _clk_enable(clk);
+ ipu_di_clk[clk->id].set_parent(&ipu_di_clk[clk->id], clk);
+ ipu_di_clk[clk->id].parent = clk;
+ ipu_di_clk[clk->id].enable(&ipu_di_clk[clk->id]);
+ ipu_di_clk[clk->id].usecount++;
+ return 0;
+}
+
+static void _clk_ldb_di_disable(struct clk *clk)
+{
+ _clk_disable(clk);
+ ipu_di_clk[clk->id].disable(&ipu_di_clk[clk->id]);
+ ipu_di_clk[clk->id].usecount--;
+}
+
+static struct clk ldb_di_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll4_sw_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .get_rate = _clk_ldb_di_get_rate,
+ .set_parent = _clk_ldb_di_set_parent,
+ .round_rate = _clk_ldb_di_round_rate,
+ .set_rate = _clk_ldb_di_set_rate,
+ .enable = _clk_ldb_di_enable,
+ .disable = _clk_ldb_di_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT,
+ },
+ {
+ .id = 1,
+ .parent = &pll4_sw_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .get_rate = _clk_ldb_di_get_rate,
+ .set_parent = _clk_ldb_di_set_parent,
+ .round_rate = _clk_ldb_di_round_rate,
+ .set_rate = _clk_ldb_di_set_rate,
+ .enable = _clk_ldb_di_enable,
+ .disable = _clk_ldb_di_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT,
+ },
+};
+
+static int _clk_csi0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, NULL);
+ reg = (reg & ~MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_csi0_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR4);
+ pred = ((reg & MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent)/(pred * podf);
+}
+
+static unsigned long _clk_csi0_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_csi0_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set CSI clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR4) &
+ ~(MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK |
+ MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR4);
+
+ return 0;
+}
+
+static struct clk csi0_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_csi0_set_parent,
+ .get_rate = _clk_csi0_get_rate,
+ .round_rate = _clk_csi0_round_rate,
+ .set_rate = _clk_csi0_set_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+};
+
+static int _clk_csi1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, NULL);
+ reg = (reg & ~MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_csi1_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR4);
+ pred = ((reg & MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent)/(pred * podf) ;
+}
+
+static unsigned long _clk_csi1_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_csi1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set CSI clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR4) &
+ ~(MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK |
+ MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR4);
+
+ return 0;
+}
+
+static struct clk csi1_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_csi1_set_parent,
+ .get_rate = _clk_csi1_get_rate,
+ .round_rate = _clk_csi1_round_rate,
+ .set_rate = _clk_csi1_set_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable,
+};
+
+
+static int _clk_hsc_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+ /* Handshake with IPU when certain clock rates are changed. */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static void _clk_hsc_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_disable(clk);
+ /* No handshake with HSC as its not enabled. */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk mipi_esc_clk = {
+ .parent = &pll2_sw_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+};
+
+static struct clk mipi_hsc2_clk = {
+ .parent = &pll2_sw_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .secondary = &mipi_esc_clk,
+};
+
+static struct clk mipi_hsc1_clk = {
+ .parent = &pll2_sw_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .secondary = &mipi_hsc2_clk,
+};
+
+static struct clk mipi_hsp_clk = {
+ .parent = &ipu_clk[0],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_hsc_enable,
+ .disable = _clk_hsc_disable,
+ .secondary = &mipi_hsc1_clk,
+};
+
+static int _clk_tve_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+
+ if ((parent == &pll3_sw_clk) && cpu_is_mx51()) {
+ reg &= ~(MXC_CCM_CSCMR1_TVE_CLK_SEL);
+ } else if ((parent == &pll4_sw_clk) && cpu_is_mx53()) {
+ reg &= ~(MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL);
+ } else if ((parent == &osc_clk) && cpu_is_mx51()) {
+ reg |= MXC_CCM_CSCMR1_TVE_CLK_SEL;
+ reg &= ~MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL;
+ } else if (parent == &ckih_clk) {
+ reg |= MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL;
+ reg |= MXC_CCM_CSCMR1_TVE_CLK_SEL; /* Reserved on MX53 */
+ } else {
+ BUG();
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+ return 0;
+}
+
+static unsigned long _clk_tve_get_rate(struct clk *clk)
+{
+ u32 reg, div = 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if ((reg & (MXC_CCM_CSCMR1_TVE_CLK_SEL | MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL)) == 0) {
+ reg = __raw_readl(MXC_CCM_CDCDR) &
+ MXC_CCM_CDCDR_TVE_CLK_PRED_MASK;
+ div = (reg >> MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET) + 1;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_tve_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (cpu_is_mx51() && (reg & MXC_CCM_CSCMR1_TVE_CLK_SEL))
+ return -EINVAL;
+ if (cpu_is_mx53() && (reg & MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL))
+ return -EINVAL;
+
+ div = (parent_rate + rate/2) / rate;
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+ return parent_rate / div;
+}
+
+static int _clk_tve_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (cpu_is_mx51() && (reg & MXC_CCM_CSCMR1_TVE_CLK_SEL))
+ return -EINVAL;
+ if (cpu_is_mx53() && (reg & MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL))
+ return -EINVAL;
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ div--;
+ reg = __raw_readl(MXC_CCM_CDCDR) & ~MXC_CCM_CDCDR_TVE_CLK_PRED_MASK;
+ reg |= div << MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+ return 0;
+}
+
+static struct clk tve_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_tve_set_parent,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .get_rate = _clk_tve_get_rate,
+ .round_rate = _clk_tve_round_rate,
+ .set_rate = _clk_tve_set_rate,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk spba_clk = {
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_uart_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent)/(prediv * podf) ;
+}
+
+static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk uart_main_clk = {
+ .parent = &pll2_sw_clk,
+ .get_rate = _clk_uart_get_rate,
+ .set_parent = _clk_uart_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk uart1_clk[] = {
+ {
+ .id = 0,
+ .parent = &uart_main_clk,
+ .secondary = &uart1_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART1_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+#if UART1_DMA_ENABLE
+ .secondary = &aips_tz1_clk,
+#endif
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart2_clk[] = {
+ {
+ .id = 1,
+ .parent = &uart_main_clk,
+ .secondary = &uart2_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART2_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+#if UART2_DMA_ENABLE
+ .secondary = &aips_tz1_clk,
+#endif
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart3_clk[] = {
+ {
+ .id = 2,
+ .parent = &uart_main_clk,
+ .secondary = &uart3_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART3_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 2,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart4_clk[] = {
+ {
+ .id = 3,
+ .parent = &uart_main_clk,
+ .secondary = &uart4_clk[1],
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART4_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 3,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart5_clk[] = {
+ {
+ .id = 4,
+ .parent = &uart_main_clk,
+ .secondary = &uart5_clk[1],
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART5_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 4,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk gpt_clk[] = {
+ {
+ .parent = &ipg_perclk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &gpt_clk[1],
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ckil_clk,
+ },
+};
+
+static struct clk pwm1_clk[] = {
+ {
+ .parent = &ipg_perclk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &pwm1_clk[1],
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ckil_clk,
+ },
+};
+
+static struct clk pwm2_clk[] = {
+ {
+ .parent = &ipg_perclk,
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &pwm2_clk[1],
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ckil_clk,
+ },
+};
+
+static struct clk i2c_clk[] = {
+ {
+ .id = 0,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 2,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_hsi2c_serial_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR3);
+ prediv = ((reg & MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static struct clk hsi2c_serial_clk = {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .get_rate = _clk_hsi2c_serial_get_rate,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static struct clk hsi2c_clk = {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_cspi_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ prediv = ((reg & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_cspi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk cspi_main_clk = {
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_cspi_get_rate,
+ .set_parent = _clk_cspi_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk cspi1_clk[] = {
+ {
+ .id = 0,
+ .parent = &cspi_main_clk,
+ .secondary = &cspi1_clk[1],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk cspi2_clk[] = {
+ {
+ .id = 1,
+ .parent = &cspi_main_clk,
+ .secondary = &cspi2_clk[1],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &aips_tz2_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk cspi3_clk = {
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &aips_tz2_clk,
+};
+
+static unsigned long _clk_ieee_rtc_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ prediv = ((reg & MXC_CCM_CSCDR2_IEEE_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR2_IEEE_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CSCDR2_IEEE_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR2_IEEE_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ieee_rtc_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ reg &= ~(MXC_CCM_CSCDR2_IEEE_CLK_PRED_MASK |
+ MXC_CCM_CSCDR2_IEEE_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR2_IEEE_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR2_IEEE_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static unsigned long _clk_ieee_rtc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_ieee_rtc_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll3_sw_clk, &pll4_sw_clk,
+ NULL, NULL);
+ reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_IEEE_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR2_IEEE_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static struct clk ieee_rtc_clk = {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ieee_rtc_set_parent,
+ .set_rate = _clk_ieee_rtc_set_rate,
+ .round_rate = _clk_ieee_rtc_round_rate,
+ .get_rate = _clk_ieee_rtc_get_rate,
+};
+
+static int _clk_ssi_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &ckih_clk, &lp_apm_clk, &ckih2_clk, NULL);
+ reg = __raw_readl(MXC_CCM_CSCMR1) &
+ ~MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi_lp_apm_clk = {
+ .parent = &ckih_clk,
+ .set_parent = _clk_ssi_lp_apm_set_parent,
+};
+
+static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+ &pll3_sw_clk, &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi1_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi1_set_parent,
+ .secondary = &ssi1_clk[1],
+ .get_rate = _clk_ssi1_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &ssi1_clk[2],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &aips_tz2_clk,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &emi_intr_clk[0],
+#else
+ .secondary = &emi_fast_clk,
+#endif
+ },
+};
+
+static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ prediv = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK) >>
+ MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK) >>
+ MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+ &pll3_sw_clk, &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi2_clk[] = {
+ {
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi2_set_parent,
+ .secondary = &ssi2_clk[1],
+ .get_rate = _clk_ssi2_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &ssi2_clk[2],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &spba_clk,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &emi_intr_clk[0],
+#else
+ .secondary = &emi_fast_clk,
+#endif
+ },
+};
+
+static int _clk_ssi3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI3_CLK_SEL;
+
+ if (parent == &ssi1_clk[0])
+ reg &= ~MXC_CCM_CSCMR1_SSI3_CLK_SEL;
+ else if (parent == &ssi2_clk[0])
+ reg |= MXC_CCM_CSCMR1_SSI3_CLK_SEL;
+ else {
+ printk(KERN_ERR"Set ssi3 clock parent failed!\n");
+ printk(KERN_ERR"ssi3 only support");
+ printk(KERN_ERR"ssi1 and ssi2 as parent clock\n");
+ return -1;
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+ return 0;
+}
+
+static struct clk ssi3_clk[] = {
+ {
+ .id = 2,
+ .parent = &ssi1_clk[0],
+ .set_parent = _clk_ssi3_set_parent,
+ .secondary = &ssi3_clk[1],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 2,
+ .parent = &ipg_clk,
+ .secondary = &ssi3_clk[2],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 2,
+ .parent = &aips_tz2_clk,
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ .secondary = &emi_intr_clk,
+#else
+ .secondary = &emi_fast_clk,
+#endif
+ },
+};
+
+static unsigned long _clk_ssi_ext1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+ u32 div = 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if ((reg & MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL) == 0) {
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET) + 1;
+ div = prediv * podf;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ssi_ext1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK |
+ MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static int _clk_ssi_ext1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &ssi1_clk[0]) {
+ reg |= MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL;
+ } else {
+ reg &= ~MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL;
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &ssi_lp_apm_clk);
+ reg = (reg & ~MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET);
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_ssi_ext1_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static struct clk ssi_ext1_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi_ext1_set_parent,
+ .set_rate = _clk_ssi_ext1_set_rate,
+ .round_rate = _clk_ssi_ext1_round_rate,
+ .get_rate = _clk_ssi_ext1_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_ssi_ext2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+ u32 div = 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if ((reg & MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL) == 0) {
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ prediv = ((reg & MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK) >>
+ MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK) >>
+ MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET) + 1;
+ div = prediv * podf;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ssi_ext2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &ssi2_clk[0]) {
+ reg |= MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL;
+ } else {
+ reg &= ~MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL;
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &ssi_lp_apm_clk);
+ reg = (reg & ~MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET);
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi_ext2_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi_ext2_set_parent,
+ .get_rate = _clk_ssi_ext2_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static int _clk_esai_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (parent == &pll1_sw_clk || parent == &pll2_sw_clk ||
+ parent == &pll3_sw_clk) {
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ NULL);
+ reg &= ~MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET;
+ reg &= ~MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK;
+ reg |= 0 << MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET;
+ /* divider setting */
+ } else {
+ mux = _get_mux(parent, &ssi1_clk[0], &ssi2_clk[0], &ckih_clk,
+ &ckih2_clk);
+ reg &= ~MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK;
+ reg |= (mux + 1) << MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET;
+ /* divider setting */
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ /* set podf = 0 */
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static unsigned long _clk_esai_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ if (clk->parent == &pll1_sw_clk || clk->parent == &pll2_sw_clk ||
+ clk->parent == &pll3_sw_clk) {
+ pred = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (pred * podf);
+ } else {
+ podf = ((reg & MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / podf;
+ }
+}
+
+static struct clk esai_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_esai_set_parent,
+ .get_rate = _clk_esai_get_rate,
+ .secondary = &esai_clk[1],
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk iim_clk = {
+ .parent = &ipg_clk,
+ .secondary = &aips_tz2_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk tmax1_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ };
+
+static struct clk tmax2_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk tmax3_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_usboh3_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk usboh3_clk[] = {
+ {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_usboh3_set_parent,
+ .get_rate = _clk_usboh3_get_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &usboh3_clk[1],
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &tmax2_clk,
+#if defined(CONFIG_USB_STATIC_IRAM) \
+ || defined(CONFIG_USB_STATIC_IRAM_PPH)
+ .secondary = &emi_intr_clk[0],
+#else
+ .secondary = &emi_fast_clk,
+#endif
+ },
+};
+
+static struct clk usb_ahb_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_usb_phy_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+ u32 div = 1;
+
+ if (clk->parent == &pll3_sw_clk) {
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ prediv = ((reg & MXC_CCM_CDCDR_USB_PHY_PRED_MASK) >>
+ MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CDCDR_USB_PHY_PODF_MASK) >>
+ MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET) + 1;
+
+ div = (prediv * podf);
+ }
+
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usb_phy_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &osc_clk)
+ reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+ else if (parent == &pll3_sw_clk)
+ reg |= MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+ else
+ BUG();
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+ return 0;
+}
+
+static struct clk usb_phy_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .secondary = &tmax3_clk,
+ .set_parent = _clk_usb_phy_set_parent,
+ .get_rate = _clk_usb_phy_get_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .secondary = &tmax3_clk,
+ .set_parent = _clk_usb_phy_set_parent,
+ .get_rate = _clk_usb_phy_get_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .disable = _clk_disable,
+ }
+};
+
+static struct clk esdhc_dep_clks = {
+ .parent = &spba_clk,
+ .secondary = &emi_fast_clk,
+};
+
+static unsigned long _clk_esdhc1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_esdhc1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) &
+ ~MXC_CCM_CSCMR1_ESDHC1_MSHC2_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_ESDHC1_MSHC2_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+
+static int _clk_sdhc1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set sdhc1 clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR1) &
+ ~(MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_MASK |
+ MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk esdhc1_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll2_sw_clk,
+ .set_parent = _clk_esdhc1_set_parent,
+ .get_rate = _clk_esdhc1_get_rate,
+ .set_rate = _clk_sdhc1_set_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc1_clk[1],
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &esdhc1_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &tmax3_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+
+};
+
+static unsigned long _clk_esdhc2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ if (cpu_is_mx51()) {
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+ }
+ return clk_get_rate(clk->parent);
+}
+
+static int _clk_esdhc2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ if (cpu_is_mx51()) {
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) &
+ ~MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_OFFSET;
+ } else { /* MX53 */
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk[0])
+ reg &= ~MXC_CCM_CSCMR1_ESDHC2_CLK_SEL;
+ else if (parent == &esdhc3_clk[0])
+ reg |= MXC_CCM_CSCMR1_ESDHC2_CLK_SEL;
+ else
+ BUG();
+ }
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+ return 0;
+}
+
+static int _clk_esdhc2_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (cpu_is_mx51()) {
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set sdhc1 clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR1) &
+ ~(MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK |
+ MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK);
+ reg |= (post - 1) <<
+ MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) <<
+ MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+ }
+ return 0;
+}
+
+static struct clk esdhc2_clk[] = {
+ {
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_esdhc2_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc2_clk[1],
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &esdhc2_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &tmax2_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+};
+
+static int _clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ if (cpu_is_mx51()) {
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk[0])
+ reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_MX51;
+ else if (parent == &esdhc2_clk[0])
+ reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_MX51;
+ else
+ BUG();
+ } else { /* MX53 */
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) &
+ ~MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_OFFSET;
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_esdhc3_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_sdhc3_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ if (cpu_is_mx53()) {
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set sdhc1 clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR1) &
+ ~(MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK |
+ MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+ }
+ return 0;
+}
+
+
+static struct clk esdhc3_clk[] = {
+ {
+ .id = 2,
+ .parent = &esdhc1_clk[0],
+ .set_parent = _clk_esdhc3_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc3_clk[1],
+ },
+ {
+ .id = 2,
+ .parent = &ipg_clk,
+ .secondary = &esdhc3_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ahb_max_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+};
+
+static int _clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+ if (cpu_is_mx51()) {
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk[0])
+ reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else if (parent == &esdhc2_clk[0])
+ reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else
+ BUG();
+ } else {/*MX53 */
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk[0])
+ reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else if (parent == &esdhc3_clk[0])
+ reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else
+ BUG();
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk esdhc4_clk[] = {
+ {
+ .id = 3,
+ .parent = &esdhc1_clk[0],
+ .set_parent = _clk_esdhc4_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc4_clk[1],
+ },
+ {
+ .id = 3,
+ .parent = &ipg_clk,
+ .secondary = &esdhc4_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &tmax3_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+};
+
+static struct clk sata_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk ieee_1588_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk mlb_clk[] = {
+ {
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &mlb_clk[1],
+ },
+ {
+ .parent = &emi_fast_clk,
+ .secondary = &emi_intr_clk[1],
+ },
+};
+
+static int _can_root_clk_set(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &ipg_clk, &ckih_clk, &ckih2_clk, &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static struct clk can1_clk[] = {
+ {
+ .id = 0,
+ .parent = &lp_apm_clk,
+ .set_parent = _can_root_clk_set,
+ .enable = _clk_enable,
+ .secondary = &can1_clk[1],
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk can2_clk[] = {
+ {
+ .id = 1,
+ .parent = &lp_apm_clk,
+ .set_parent = _can_root_clk_set,
+ .enable = _clk_enable,
+ .secondary = &can2_clk[1],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable,
+ },
+};
+
+static int _clk_sim_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk, NULL);
+ reg = __raw_readl(MXC_CCM_CSCMR2) & ~MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_sim_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ pred = ((reg & MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / (pred * podf);
+}
+
+static unsigned long _clk_sim_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static int _clk_sim_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set SIM clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR2) &
+ ~(MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK |
+ MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+
+}
+
+static struct clk sim_clk[] = {
+ {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_sim_set_parent,
+ .secondary = &sim_clk[1],
+ .get_rate = _clk_sim_get_rate,
+ .round_rate = _clk_sim_round_rate,
+ .set_rate = _clk_sim_set_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_nfc_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+ MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_nfc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ /*
+ * Compute the divider we'd have to use to reach the target rate.
+ */
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (parent_rate / div > MAX_NFC_CLK)
+ div++;
+
+ /*
+ * The divider for this clock is 3 bits wide, so we can't possibly
+ * divide the parent by more than eight.
+ */
+
+ if (div > 8)
+ return -EINVAL;
+
+ return parent_rate / div;
+
+}
+
+static int _clk_nfc_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.enable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.enable(&emi_slow_clk);
+
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+ getnstimeofday(&curtime);
+ if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY)
+ panic("_clk_nfc_set_rate failed\n");
+ }
+ if (emi_fast_clk.usecount == 0)
+ emi_fast_clk.disable(&emi_fast_clk);
+ if (emi_slow_clk.usecount == 0)
+ emi_slow_clk.disable(&emi_slow_clk);
+
+ return 0;
+}
+
+static struct clk emi_enfc_clk = {
+ .parent = &emi_slow_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .disable = _clk_disable_inwait,
+ .get_rate = _clk_nfc_get_rate,
+ .round_rate = _clk_nfc_round_rate,
+ .set_rate = _clk_nfc_set_rate,
+};
+
+static int _clk_spdif_xtal_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &osc_clk, &ckih_clk, &ckih2_clk, NULL);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk spdif_xtal_clk = {
+ .parent = &osc_clk,
+ .set_parent = _clk_spdif_xtal_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_disable,
+};
+
+static int _clk_spdif0_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ reg |= MXC_CCM_CSCMR2_SPDIF0_COM;
+ if (parent != &ssi1_clk[0]) {
+ reg &= ~MXC_CCM_CSCMR2_SPDIF0_COM;
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &spdif_xtal_clk);
+ reg = (reg & ~MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET);
+ }
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_spdif0_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+ u32 div = 1;
+
+ if (clk->parent != &ssi1_clk[0]) {
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ pred = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK) >>
+ MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK) >>
+ MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET) + 1;
+ div = (pred * podf);
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static struct clk spdif0_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_spdif0_set_parent,
+ .get_rate = _clk_spdif0_get_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_disable,
+ },
+};
+
+static int _clk_spdif1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ reg |= MXC_CCM_CSCMR2_SPDIF1_COM;
+ if (parent != &ssi2_clk[0]) {
+ reg &= ~MXC_CCM_CSCMR2_SPDIF1_COM;
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &spdif_xtal_clk);
+ reg = (reg & ~MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET);
+ }
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_spdif1_get_rate(struct clk *clk)
+{
+ u32 reg, pred, podf;
+ u32 div = 1;
+
+ if (clk->parent != &ssi2_clk[0]) {
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ pred = ((reg & MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK) >>
+ MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK) >>
+ MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET) + 1;
+ div = (pred * podf);
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static struct clk spdif1_clk[] = {
+ {
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_spdif1_set_parent,
+ .get_rate = _clk_spdif1_get_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_disable,
+ },
+};
+
+static int _clk_ddr_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, reg2, mux;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ reg2 = __raw_readl(MXC_CCM_CBCDR);
+ if (cpu_is_mx51()) {
+ clk->parent = &ddr_hf_clk;
+ mux = _get_mux_ddr(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk, &ddr_hf_clk);
+ } else {
+ clk->parent = &axi_a_clk;
+ mux = _get_mux_ddr(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk, NULL);
+ }
+ if (mux < 4) {
+ reg = (reg & ~MXC_CCM_CBCMR_DDR_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+ if (cpu_is_mx51())
+ reg2 = (reg2 & ~MXC_CCM_CBCDR_DDR_HF_SEL);
+ } else {
+ reg2 = (reg2 & ~MXC_CCM_CBCDR_DDR_HF_SEL) |
+ (MXC_CCM_CBCDR_DDR_HF_SEL);
+ }
+ if (cpu_is_mx51()) {
+ __raw_writel(reg2, MXC_CCM_CBCDR);
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY){
+ getnstimeofday(&curtime);
+ if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY)
+ panic("_clk_ddr_set_parent failed\n");
+ }
+ }
+ return 0;
+}
+
+static struct clk ddr_clk = {
+ .parent = &axi_b_clk,
+ .set_parent = _clk_ddr_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_arm_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk);
+ reg = (reg & ~MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk arm_axi_clk = {
+ .parent = &axi_a_clk,
+ .set_parent = _clk_arm_axi_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+};
+
+static int _clk_vpu_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk);
+ reg = (reg & ~MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static int _clk_vpu_enable(struct clk *clk)
+{
+ /* Set VPU's parent to be axi_a or ahb when its enabled. */
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) {
+ clk_set_parent(&vpu_clk[0], &ahb_clk);
+ clk_set_parent(&vpu_clk[1], &ahb_clk);
+ } else if (cpu_is_mx51()) {
+ clk_set_parent(&vpu_clk[0], &axi_a_clk);
+ clk_set_parent(&vpu_clk[1], &axi_a_clk);
+ }
+
+ return _clk_enable(clk);
+
+}
+
+static void _clk_vpu_disable(struct clk *clk)
+{
+ _clk_disable(clk);
+
+ /* Set VPU's parent to be axi_b when its disabled. */
+ if (cpu_is_mx51()) {
+ clk_set_parent(&vpu_clk[0], &axi_b_clk);
+ clk_set_parent(&vpu_clk[1], &axi_b_clk);
+ }
+}
+
+static struct clk vpu_clk[] = {
+ {
+ .set_parent = _clk_vpu_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &vpu_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .set_parent = _clk_vpu_set_parent,
+ .enable = _clk_vpu_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_vpu_disable,
+ .secondary = &vpu_clk[2],
+ },
+ {
+ .parent = &emi_fast_clk,
+#ifdef CONFIG_MXC_VPU_IRAM
+ .secondary = &emi_intr_clk[0],
+#endif
+ }
+};
+
+static int _clk_lpsr_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ mux = _get_mux(parent, &ckil_clk, &osc_clk, NULL, NULL);
+ reg = (reg & ~MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static struct clk lpsr_clk = {
+ .parent = &ckil_clk,
+ .set_parent = _clk_lpsr_set_parent,
+};
+
+static unsigned long _clk_pgc_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = (reg & MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET;
+ div = 1 >> div;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static struct clk pgc_clk = {
+ .parent = &ipg_clk,
+ .get_rate = _clk_pgc_get_rate,
+};
+
+static unsigned long _clk_usb_get_rate(struct clk *clk)
+{
+ return 60000000;
+}
+
+/*usb OTG clock */
+static struct clk usb_clk = {
+ .get_rate = _clk_usb_get_rate,
+};
+
+static struct clk usb_utmi_clk = {
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CSCMR1,
+ .enable_shift = MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk rtc_clk = {
+ .parent = &ckil_clk,
+ .secondary = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk ata_clk = {
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk owire_clk = {
+ .parent = &ipg_perclk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .disable = _clk_disable,
+};
+
+
+static struct clk fec_clk[] = {
+ {
+ .parent = &ipg_clk,
+ .secondary = &fec_clk[1],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &tmax2_clk,
+ .secondary = &fec_clk[2],
+ },
+ {
+ .parent = &aips_tz2_clk,
+ .secondary = &emi_fast_clk,
+ },
+};
+
+static struct clk sahara_clk[] = {
+ {
+ .parent = &ahb_clk,
+ .secondary = &sahara_clk[1],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .parent = &tmax1_clk,
+ .secondary = &emi_fast_clk,
+ }
+};
+
+static struct clk scc_clk[] = {
+ {
+ .parent = &ahb_clk,
+ .secondary = &scc_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .parent = &tmax1_clk,
+ .secondary = &emi_fast_clk,
+ }
+};
+
+
+static int _clk_gpu3d_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk);
+ reg = (reg & ~MXC_CCM_CBCMR_GPU_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+
+static struct clk garb_clk = {
+ .parent = &axi_a_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk gpu3d_clk = {
+ .parent = &axi_a_clk,
+ .set_parent = _clk_gpu3d_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ .secondary = &garb_clk,
+};
+
+static int _clk_gpu2d_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &emi_slow_clk, &ahb_clk);
+ reg = (reg & ~MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk gpu2d_clk = {
+ .parent = &axi_a_clk,
+ .set_parent = _clk_gpu2d_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long cko1_get_rate(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= MXC_CCM_CCOSR_CKOL_DIV_MASK;
+ reg = reg >> MXC_CCM_CCOSR_CKOL_DIV_OFFSET;
+ return clk_get_rate(clk->parent) / (reg + 1);
+}
+
+static int cko1_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg |= MXC_CCM_CCOSR_CKOL_EN;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static void cko1_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKOL_EN;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+}
+
+static int cko1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = (parent_rate/rate - 1) & 0x7;
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKOL_DIV_MASK;
+ reg |= div << MXC_CCM_CCOSR_CKOL_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long cko1_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ div = div < 1 ? 1 : div;
+ div = div > 8 ? 8 : div;
+ return parent_rate / div;
+}
+
+static int cko1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, reg;
+
+ if (parent == &cpu_clk)
+ sel = 0;
+ else if (parent == &pll1_sw_clk)
+ sel = 1;
+ else if (parent == &pll2_sw_clk)
+ sel = 2;
+ else if (parent == &pll3_sw_clk)
+ sel = 3;
+ else if (parent == &emi_slow_clk)
+ sel = 4;
+ else if (parent == &pll4_sw_clk)
+ sel = 5;
+ else if (parent == &emi_enfc_clk)
+ sel = 6;
+ else if (parent == &ipu_di_clk[0])
+ sel = 8;
+ else if (parent == &ahb_clk)
+ sel = 11;
+ else if (parent == &ipg_clk)
+ sel = 12;
+ else if (parent == &ipg_perclk)
+ sel = 13;
+ else if (parent == &ckil_clk)
+ sel = 14;
+ else
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MXC_CCM_CCOSR_CKOL_SEL_MASK;
+ reg |= sel << MXC_CCM_CCOSR_CKOL_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+static struct clk cko1_clk = {
+ .get_rate = cko1_get_rate,
+ .enable = cko1_enable,
+ .disable = cko1_disable,
+ .set_rate = cko1_set_rate,
+ .round_rate = cko1_round_rate,
+ .set_parent = cko1_set_parent,
+};
+static int _clk_asrc_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR2);
+ if (parent == &pll4_sw_clk)
+ reg |= MXC_CCM_CSCMR2_ASRC_CLK_SEL;
+ else
+ reg &= ~MXC_CCM_CSCMR2_ASRC_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CSCMR2);
+
+ return 0;
+}
+
+static unsigned long _clk_asrc_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ prediv = ((reg & MXC_CCM_CSCDR2_ASRC_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR2_ASRC_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CSCDR2_ASRC_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR2_ASRC_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_asrc_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CSCDR2) &
+ ~(MXC_CCM_CSCDR2_ASRC_CLK_PRED_MASK |
+ MXC_CCM_CSCDR2_ASRC_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR2_ASRC_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR2_ASRC_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR2);
+
+ return 0;
+}
+
+static unsigned long _clk_asrc_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static struct clk asrc_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll4_sw_clk,
+ .set_parent = _clk_asrc_set_parent,
+ .get_rate = _clk_asrc_get_rate,
+ .set_rate = _clk_asrc_set_rate,
+ .round_rate = _clk_asrc_round_rate,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ }
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK(NULL, "osc", osc_clk),
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+ _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk),
+ _REGISTER_CLOCK(NULL, "ckil", ckil_clk),
+ _REGISTER_CLOCK(NULL, "pll1_main_clk", pll1_main_clk),
+ _REGISTER_CLOCK(NULL, "pll1_sw_clk", pll1_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll2", pll2_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll3", pll3_sw_clk),
+ _REGISTER_CLOCK(NULL, "gpc_dvfs_clk", gpc_dvfs_clk),
+ _REGISTER_CLOCK(NULL, "lp_apm", lp_apm_clk),
+ _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk),
+ _REGISTER_CLOCK(NULL, "periph_apm_clk", periph_apm_clk),
+ _REGISTER_CLOCK(NULL, "main_bus_clk", main_bus_clk),
+ _REGISTER_CLOCK(NULL, "axi_a_clk", axi_a_clk),
+ _REGISTER_CLOCK(NULL, "axi_b_clk", axi_b_clk),
+ _REGISTER_CLOCK(NULL, "ahb_clk", ahb_clk),
+ _REGISTER_CLOCK(NULL, "ahb_max_clk", ahb_max_clk),
+ _REGISTER_CLOCK(NULL, "vpu_clk", vpu_clk[0]),
+ _REGISTER_CLOCK(NULL, "vpu_core_clk", vpu_clk[1]),
+ _REGISTER_CLOCK(NULL, "nfc_clk", emi_enfc_clk),
+ _REGISTER_CLOCK("mxc_sdma", "sdma_ahb_clk", sdma_clk[0]),
+ _REGISTER_CLOCK("mxc_sdma", "sdma_ipg_clk", sdma_clk[1]),
+ _REGISTER_CLOCK(NULL, "ipu_clk", ipu_clk[0]),
+ _REGISTER_CLOCK(NULL, "ipu_di0_clk", ipu_di_clk[0]),
+ _REGISTER_CLOCK(NULL, "ipu_di1_clk", ipu_di_clk[1]),
+ _REGISTER_CLOCK(NULL, "csi_mclk1", csi0_clk),
+ _REGISTER_CLOCK(NULL, "csi_mclk2", csi1_clk),
+ _REGISTER_CLOCK(NULL, "tve_clk", tve_clk),
+ _REGISTER_CLOCK("mxcintuart.0", NULL, uart1_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.1", NULL, uart2_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.2", NULL, uart3_clk[0]),
+ _REGISTER_CLOCK(NULL, "i2c_clk", i2c_clk[0]),
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk[1]),
+ _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk[0]),
+ _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk[0]),
+ _REGISTER_CLOCK("mxc_spi.0", NULL, cspi1_clk[0]),
+ _REGISTER_CLOCK("mxc_spi.1", NULL, cspi2_clk[0]),
+ _REGISTER_CLOCK("mxc_spi.2", NULL, cspi3_clk),
+ _REGISTER_CLOCK(NULL, "ssi_lp_apm_clk", ssi_lp_apm_clk),
+ _REGISTER_CLOCK("mxc_ssi.0", NULL, ssi1_clk[0]),
+ _REGISTER_CLOCK("mxc_ssi.1", NULL, ssi2_clk[0]),
+ _REGISTER_CLOCK("mxc_ssi.2", NULL, ssi3_clk[0]),
+ _REGISTER_CLOCK(NULL, "ssi_ext1_clk", ssi_ext1_clk),
+ _REGISTER_CLOCK(NULL, "ssi_ext2_clk", ssi_ext2_clk),
+ _REGISTER_CLOCK(NULL, "iim_clk", iim_clk),
+ _REGISTER_CLOCK(NULL, "usboh3_clk", usboh3_clk[0]),
+ _REGISTER_CLOCK(NULL, "usb_ahb_clk", usb_ahb_clk),
+ _REGISTER_CLOCK(NULL, "usb_phy1_clk", usb_phy_clk[0]),
+ _REGISTER_CLOCK(NULL, "usb_utmi_clk", usb_utmi_clk),
+ _REGISTER_CLOCK(NULL, "usb_clk", usb_clk),
+ _REGISTER_CLOCK("mxsdhci.0", NULL, esdhc1_clk[0]),
+ _REGISTER_CLOCK("mxsdhci.1", NULL, esdhc2_clk[0]),
+ _REGISTER_CLOCK("mxsdhci.2", NULL, esdhc3_clk[0]),
+ _REGISTER_CLOCK("mxsdhci.3", NULL, esdhc4_clk[0]),
+ _REGISTER_CLOCK(NULL, "emi_slow_clk", emi_slow_clk),
+ _REGISTER_CLOCK(NULL, "ddr_clk", ddr_clk),
+ _REGISTER_CLOCK(NULL, "emi_enfc_clk", emi_enfc_clk),
+ _REGISTER_CLOCK(NULL, "emi_fast_clk", emi_fast_clk),
+ _REGISTER_CLOCK(NULL, "emi_intr_clk.0", emi_intr_clk[0]),
+ _REGISTER_CLOCK(NULL, "emi_intr_clk.1", emi_intr_clk[1]),
+ _REGISTER_CLOCK(NULL, "spdif_xtal_clk", spdif_xtal_clk),
+ _REGISTER_CLOCK("mxc_alsa_spdif.0", NULL, spdif0_clk[0]),
+ _REGISTER_CLOCK("mxc_vpu.0", NULL, vpu_clk[0]),
+ _REGISTER_CLOCK(NULL, "lpsr_clk", lpsr_clk),
+ _REGISTER_CLOCK("mxc_rtc.0", NULL, rtc_clk),
+ _REGISTER_CLOCK("pata_fsl", NULL, ata_clk),
+ _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk),
+ _REGISTER_CLOCK(NULL, "sahara_clk", sahara_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpu3d_clk", gpu3d_clk),
+ _REGISTER_CLOCK(NULL, "garb_clk", garb_clk),
+ _REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_clk),
+ _REGISTER_CLOCK("mxc_scc.0", NULL, scc_clk[0]),
+ _REGISTER_CLOCK(NULL, "cko1", cko1_clk),
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk[0]),
+ _REGISTER_CLOCK("fec.0", NULL, fec_clk[0]),
+ _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk),
+};
+
+static struct clk_lookup mx51_lookups[] = {
+ _REGISTER_CLOCK("mxc_i2c_hs.3", NULL, hsi2c_serial_clk),
+ _REGISTER_CLOCK("mxc_sim.0", NULL, sim_clk[0]),
+ _REGISTER_CLOCK("mxc_alsa_spdif.0", NULL, spdif1_clk[0]),
+ _REGISTER_CLOCK(NULL, "mipi_hsp_clk", mipi_hsp_clk),
+ _REGISTER_CLOCK(NULL, "ddr_hf_clk", ddr_hf_clk),
+};
+
+static struct clk_lookup mx53_lookups[] = {
+ _REGISTER_CLOCK(NULL, "pll4", pll4_sw_clk),
+ _REGISTER_CLOCK("mxcintuart.3", NULL, uart4_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.4", NULL, uart5_clk[0]),
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]),
+ _REGISTER_CLOCK(NULL, "usb_phy2_clk", usb_phy_clk[1]),
+ _REGISTER_CLOCK(NULL, "ocram_clk", ocram_clk),
+ _REGISTER_CLOCK(NULL, "imx_sata_clk", sata_clk),
+ _REGISTER_CLOCK(NULL, "ieee_1588_clk", ieee_1588_clk),
+ _REGISTER_CLOCK(NULL, "ieee_rtc_clk", ieee_rtc_clk),
+ _REGISTER_CLOCK("mxc_mlb.0", NULL, mlb_clk[0]),
+ _REGISTER_CLOCK("FlexCAN.0", "can_clk", can1_clk[0]),
+ _REGISTER_CLOCK("FlexCAN.1", "can_clk", can2_clk[0]),
+ _REGISTER_CLOCK(NULL, "ldb_di0_clk", ldb_di_clk[0]),
+ _REGISTER_CLOCK(NULL, "ldb_di1_clk", ldb_di_clk[1]),
+ _REGISTER_CLOCK(NULL, "esai_clk", esai_clk[0]),
+ _REGISTER_CLOCK(NULL, "esai_ipg_clk", esai_clk[1]),
+ _REGISTER_CLOCK(NULL, "asrc_clk", asrc_clk[1]),
+ _REGISTER_CLOCK(NULL, "asrc_serial_clk", asrc_clk[0]),
+};
+
+static struct mxc_clk mx51_clks[ARRAY_SIZE(lookups) + ARRAY_SIZE(mx51_lookups)];
+static struct mxc_clk mx53_clks[ARRAY_SIZE(lookups) + ARRAY_SIZE(mx53_lookups)];
+
+static void clk_tree_init(void)
+{
+ u32 reg, dp_ctl;
+
+ ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+
+ /*
+ *Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+ * 8MHz, its derived from lp_apm.
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+ reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* set pll1_main_clk parent */
+ pll1_main_clk.parent = &osc_clk;
+
+ /* set pll2_sw_clk parent */
+ pll2_sw_clk.parent = &osc_clk;
+
+ /* set pll3_clk parent */
+ pll3_sw_clk.parent = &osc_clk;
+
+ if (cpu_is_mx51()) {
+ dp_ctl = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
+ if ((dp_ctl & MXC_PLL_DP_CTL_REF_CLK_SEL_MASK) == 0)
+ pll1_main_clk.parent = &fpm_clk;
+
+ dp_ctl = __raw_readl(pll2_base + MXC_PLL_DP_CTL);
+ if ((dp_ctl & MXC_PLL_DP_CTL_REF_CLK_SEL_MASK) == 0)
+ pll2_sw_clk.parent = &fpm_clk;
+
+ dp_ctl = __raw_readl(pll3_base + MXC_PLL_DP_CTL);
+ if ((dp_ctl & MXC_PLL_DP_CTL_REF_CLK_SEL_MASK) == 0)
+ pll3_sw_clk.parent = &fpm_clk;
+ } else {
+ /* set pll4_clk parent */
+ pll4_sw_clk.parent = &osc_clk;
+ }
+
+ /* set emi_slow_clk parent */
+ emi_slow_clk.parent = &main_bus_clk;
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ if ((reg & MXC_CCM_CBCDR_EMI_CLK_SEL) != 0)
+ emi_slow_clk.parent = &ahb_clk;
+
+ /* set ipg_perclk parent */
+ ipg_perclk.parent = &lp_apm_clk;
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ if ((reg & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) != 0) {
+ ipg_perclk.parent = &ipg_clk;
+ } else {
+ if ((reg & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL) == 0)
+ ipg_perclk.parent = &main_bus_clk;
+ }
+}
+
+
+int __init mx51_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2)
+{
+ __iomem void *base;
+ struct clk *tclk;
+ int i = 0, j = 0, reg;
+ int wp_cnt = 0;
+ u32 pll1_rate;
+
+ pll1_base = ioremap(PLL1_BASE_ADDR, SZ_4K);
+ pll2_base = ioremap(PLL2_BASE_ADDR, SZ_4K);
+ pll3_base = ioremap(PLL3_BASE_ADDR, SZ_4K);
+
+ /* Turn off all possible clocks */
+ if (mxc_jtag_enabled) {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG3_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG4_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG14_OFFSET, MXC_CCM_CCGR0);
+ } else {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG3_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG14_OFFSET, MXC_CCM_CCGR0);
+ }
+ __raw_writel(0, MXC_CCM_CCGR1);
+ __raw_writel(0, MXC_CCM_CCGR2);
+ __raw_writel(0, MXC_CCM_CCGR3);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR4);
+
+ __raw_writel(1 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 1 << MXC_CCM_CCGR5_CG6_1_OFFSET |
+ 1 << MXC_CCM_CCGR5_CG6_2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG7_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG10_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR5);
+
+ __raw_writel(1 << MXC_CCM_CCGRx_CG4_OFFSET, MXC_CCM_CCGR6);
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ ckih2_reference = ckih2;
+ oscillator_reference = osc;
+
+ /* Fix up clocks unique to MX51. */
+ esdhc2_clk[0].get_rate = _clk_esdhc2_get_rate;
+ esdhc2_clk[0].set_rate = _clk_esdhc2_set_rate;
+
+ clk_tree_init();
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+ clkdev_add(&lookups[i]);
+ mx51_clks[i].reg_clk = lookups[i].clk;
+ if (lookups[i].con_id != NULL)
+ strcpy(mx51_clks[i].name, lookups[i].con_id);
+ else
+ strcpy(mx51_clks[i].name, lookups[i].dev_id);
+ clk_register(&mx51_clks[i]);
+ }
+
+ j = ARRAY_SIZE(lookups);
+ for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++) {
+ clkdev_add(&mx51_lookups[i]);
+ mx51_clks[i+j].reg_clk = mx51_lookups[i].clk;
+ if (mx51_lookups[i].con_id != NULL)
+ strcpy(mx51_clks[i+j].name, mx51_lookups[i].con_id);
+ else
+ strcpy(mx51_clks[i+j].name, mx51_lookups[i].dev_id);
+ clk_register(&mx51_clks[i+j]);
+ }
+
+ max_axi_a_clk = MAX_AXI_A_CLK_MX51;
+ max_axi_b_clk = MAX_AXI_B_CLK_MX51;
+ max_ahb_clk = MAX_AHB_CLK_MX51;
+ max_emi_slow_clk = MAX_AHB_CLK_MX51;
+
+ /* set DDR clock parent */
+ reg = 0;
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) >= 1) {
+ reg = __raw_readl(MXC_CCM_CBCDR) & MXC_CCM_CBCDR_DDR_HF_SEL;
+ reg >>= MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET;
+
+ if (reg)
+ tclk = &ddr_hf_clk;
+ }
+ if (reg == 0) {
+ reg = __raw_readl(MXC_CCM_CBCMR) &
+ MXC_CCM_CBCMR_DDR_CLK_SEL_MASK;
+ reg >>= MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET;
+
+ if (reg == 0) {
+ tclk = &axi_a_clk;
+ } else if (reg == 1) {
+ tclk = &axi_b_clk;
+ } else if (reg == 2) {
+ tclk = &emi_slow_clk;
+ } else {
+ tclk = &ahb_clk;
+ }
+ }
+ clk_set_parent(&ddr_clk, tclk);
+
+ /*Setup the LPM bypass bits */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS
+ | MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS
+ | MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS
+ | MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS_MX51
+ | MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX51;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ /* Disable the handshake with HSC block as its not
+ * initialised right now.
+ */
+ reg = __raw_readl(MXC_CCM_CCDR);
+ reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+ __raw_writel(reg, MXC_CCM_CCDR);
+
+ clk_enable(&cpu_clk);
+
+ /* Set SDHC parents to be PLL2 */
+ clk_set_parent(&esdhc1_clk[0], &pll2_sw_clk);
+ clk_set_parent(&esdhc2_clk[0], &pll2_sw_clk);
+
+ /* set SDHC root clock as 166.25MHZ*/
+ clk_set_rate(&esdhc1_clk[0], 166250000);
+ clk_set_rate(&esdhc2_clk[0], 166250000);
+
+ /* Initialise the parents to be axi_b, parents are set to
+ * axi_a when the clocks are enabled.
+ */
+ clk_set_parent(&vpu_clk[0], &axi_b_clk);
+ clk_set_parent(&vpu_clk[1], &axi_b_clk);
+ clk_set_parent(&gpu3d_clk, &axi_a_clk);
+ clk_set_parent(&gpu2d_clk, &axi_a_clk);
+
+ /* move cspi to 24MHz */
+ clk_set_parent(&cspi_main_clk, &lp_apm_clk);
+ clk_set_rate(&cspi_main_clk, 12000000);
+ /*move the spdif0 to spdif_xtal_ckl */
+ clk_set_parent(&spdif0_clk[0], &spdif_xtal_clk);
+ /*set the SPDIF dividers to 1 */
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ /* move the spdif1 to 24MHz */
+ clk_set_parent(&spdif1_clk[0], &spdif_xtal_clk);
+ /* set the spdif1 dividers to 1 */
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ /* Move SSI clocks to SSI_LP_APM clock */
+ clk_set_parent(&ssi_lp_apm_clk, &lp_apm_clk);
+
+ clk_set_parent(&ssi1_clk[0], &ssi_lp_apm_clk);
+ /* set the SSI dividers to divide by 2 */
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ clk_set_parent(&ssi2_clk[0], &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ /*
+ * SSI3 has no clock divide register,
+ * we always set SSI3 parent clock to SSI1 and freq same to SSI1
+ */
+ clk_set_parent(&ssi3_clk[0], &ssi1_clk[0]);
+
+ /* Change the SSI_EXT1_CLK to be sourced from SSI1_CLK_ROOT */
+ clk_set_parent(&ssi_ext1_clk, &ssi1_clk[0]);
+ clk_set_parent(&ssi_ext2_clk, &ssi2_clk[0]);
+
+ /* move usb_phy_clk to 24MHz */
+ clk_set_parent(&usb_phy_clk[0], &osc_clk);
+
+ /* set usboh3_clk to pll2 */
+ clk_set_parent(&usboh3_clk[0], &pll2_sw_clk);
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
+ reg |= 4 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
+ reg |= 1 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ /* Set the current working point. */
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ /* Update the cpu working point table based on the PLL1 freq
+ * at boot time
+ */
+ pll1_rate = clk_get_rate(&pll1_main_clk);
+ if (pll1_rate <= cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate)
+ wp_cnt = 1;
+ else if (pll1_rate <= cpu_wp_tbl[1].cpu_rate &&
+ pll1_rate > cpu_wp_tbl[2].cpu_rate)
+ wp_cnt = cpu_wp_nr - 1;
+ else
+ wp_cnt = cpu_wp_nr;
+
+ cpu_wp_tbl[0].cpu_rate = pll1_rate;
+
+ if (wp_cnt == 1) {
+ cpu_wp_tbl[0] = cpu_wp_tbl[cpu_wp_nr - 1];
+ memset(&cpu_wp_tbl[cpu_wp_nr - 1], 0, sizeof(struct cpu_wp));
+ memset(&cpu_wp_tbl[cpu_wp_nr - 2], 0, sizeof(struct cpu_wp));
+ } else if (wp_cnt < cpu_wp_nr) {
+ for (i = 0; i < wp_cnt; i++)
+ cpu_wp_tbl[i] = cpu_wp_tbl[i+1];
+ memset(&cpu_wp_tbl[i], 0, sizeof(struct cpu_wp));
+ }
+
+ if (wp_cnt < cpu_wp_nr) {
+ set_num_cpu_wp(wp_cnt);
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ }
+
+ pll1_rate = clk_get_rate(&pll1_main_clk);
+ for (j = 0; j < cpu_wp_nr; j++) {
+ if ((ddr_clk.parent == &ddr_hf_clk)) {
+ /* Change the CPU podf divider based on the boot up
+ * pll1 rate.
+ */
+ cpu_wp_tbl[j].cpu_podf =
+ (pll1_rate / cpu_wp_tbl[j].cpu_rate)
+ - 1;
+ if (pll1_rate / (cpu_wp_tbl[j].cpu_podf + 1) >
+ cpu_wp_tbl[j].cpu_rate) {
+ cpu_wp_tbl[j].cpu_podf++;
+ cpu_wp_tbl[j].cpu_rate =
+ pll1_rate /
+ (1000 * (cpu_wp_tbl[j].cpu_podf + 1));
+ cpu_wp_tbl[j].cpu_rate *= 1000;
+ }
+ if (pll1_rate / (cpu_wp_tbl[j].cpu_podf + 1) <
+ cpu_wp_tbl[j].cpu_rate) {
+ cpu_wp_tbl[j].cpu_rate = pll1_rate;
+ }
+ }
+ cpu_wp_tbl[j].pll_rate = pll1_rate;
+ }
+ /* Set the current working point. */
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (clk_get_rate(&cpu_clk) == cpu_wp_tbl[i].cpu_rate) {
+ cpu_curr_wp = i;
+ break;
+ }
+ }
+ if (i > cpu_wp_nr)
+ BUG();
+
+ clk_set_parent(&arm_axi_clk, &axi_a_clk);
+ clk_set_parent(&ipu_clk[0], &axi_b_clk);
+
+ if (uart_at_24) {
+ /* Move UART to run from lp_apm */
+ clk_set_parent(&uart_main_clk, &lp_apm_clk);
+
+ /* Set the UART dividers to divide, so the UART_CLK is 24MHz. */
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CSCDR1_UART_CLK_PRED_MASK;
+ reg |= (0 << MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) |
+ (0 << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+ } else {
+ clk_set_parent(&uart_main_clk, &pll2_sw_clk);
+
+ /* Set the UART dividers to divide, so the UART_CLK is 66.5MHz. */
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_UART_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CSCDR1_UART_CLK_PRED_MASK;
+ reg |= (4 << MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) |
+ (1 << MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+ }
+
+ clk_set_parent(&emi_slow_clk, &ahb_clk);
+ clk_set_rate(&emi_slow_clk, clk_round_rate(&emi_slow_clk, 130000000));
+
+ /* Change the NFC clock rate to be 1:4 ratio with emi clock. */
+ clk_set_rate(&emi_enfc_clk, clk_round_rate(&emi_enfc_clk,
+ (clk_get_rate(&emi_slow_clk))/4));
+
+ base = ioremap(GPT1_BASE_ADDR, SZ_4K);
+ mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
+ return 0;
+}
+
+int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2)
+{
+ __iomem void *base;
+ struct clk *tclk;
+ int i = 0, j = 0, reg;
+ u32 pll1_rate;
+
+ pll1_base = ioremap(MX53_BASE_ADDR(PLL1_BASE_ADDR), SZ_4K);
+ pll2_base = ioremap(MX53_BASE_ADDR(PLL2_BASE_ADDR), SZ_4K);
+ pll3_base = ioremap(MX53_BASE_ADDR(PLL3_BASE_ADDR), SZ_4K);
+ pll4_base = ioremap(MX53_BASE_ADDR(PLL4_BASE_ADDR), SZ_4K);
+
+ /* Turn off all possible clocks */
+ if (mxc_jtag_enabled) {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG3_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG4_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG14_OFFSET, MXC_CCM_CCGR0);
+ } else {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG3_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG14_OFFSET, MXC_CCM_CCGR0);
+ }
+
+ __raw_writel(0, MXC_CCM_CCGR1);
+ __raw_writel(0, MXC_CCM_CCGR2);
+ __raw_writel(0, MXC_CCM_CCGR3);
+ __raw_writel(1 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR4);
+
+ __raw_writel(1 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG6_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG7_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR5);
+
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG4_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG13_OFFSET , MXC_CCM_CCGR6);
+
+ __raw_writel(0, MXC_CCM_CCGR7);
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ ckih2_reference = ckih2;
+ oscillator_reference = osc;
+
+ usb_phy_clk[0].enable_reg = MXC_CCM_CCGR4;
+ usb_phy_clk[0].enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+ ipumux1_clk.enable_reg = MXC_CCM_CCGR5;
+ ipumux1_clk.enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+ ipumux2_clk.enable_reg = MXC_CCM_CCGR6;
+ ipumux2_clk.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+
+ esdhc3_clk[0].get_rate = _clk_esdhc3_get_rate;
+ esdhc3_clk[0].set_rate = _clk_sdhc3_set_rate;
+
+#if defined(CONFIG_USB_STATIC_IRAM) \
+ || defined(CONFIG_USB_STATIC_IRAM_PPH)
+ usboh3_clk[1].secondary = &emi_intr_clk[1];
+#endif
+#ifdef CONFIG_SND_MXC_SOC_IRAM
+ ssi2_clk[2].secondary = &emi_intr_clk[1];
+ ssi1_clk[2].secondary = &emi_intr_clk[1];
+#endif
+#ifdef CONFIG_SDMA_IRAM
+ sdma_clk[1].secondary = &emi_intr_clk[1];
+#endif
+
+ clk_tree_init();
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+ clkdev_add(&lookups[i]);
+ mx53_clks[i].reg_clk = lookups[i].clk;
+ if (lookups[i].con_id != NULL)
+ strcpy(mx53_clks[i].name, lookups[i].con_id);
+ else
+ strcpy(mx53_clks[i].name, lookups[i].dev_id);
+ clk_register(&mx53_clks[i]);
+ }
+
+ j = ARRAY_SIZE(lookups);
+ for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++) {
+ clkdev_add(&mx53_lookups[i]);
+ mx53_clks[i+j].reg_clk = mx53_lookups[i].clk;
+ if (mx53_lookups[i].con_id != NULL)
+ strcpy(mx53_clks[i+j].name, mx53_lookups[i].con_id);
+ else
+ strcpy(mx53_clks[i+j].name, mx53_lookups[i].dev_id);
+ clk_register(&mx53_clks[i+j]);
+ }
+
+ clk_set_parent(&esai_clk[0], &ckih_clk);
+
+ ldb_di_clk[0].parent = ldb_di_clk[1].parent =
+ tve_clk.parent = &pll4_sw_clk;
+
+ max_axi_a_clk = MAX_AXI_A_CLK_MX53;
+ max_axi_b_clk = MAX_AXI_B_CLK_MX53;
+ max_ahb_clk = MAX_AHB_CLK_MX53;
+ max_emi_slow_clk = MAX_AHB_CLK_MX53;
+
+
+ /* set DDR clock parent */
+ reg = __raw_readl(MXC_CCM_CBCMR) &
+ MXC_CCM_CBCMR_DDR_CLK_SEL_MASK;
+ reg >>= MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET;
+ if (reg == 0) {
+ tclk = &axi_a_clk;
+ } else if (reg == 1) {
+ tclk = &axi_b_clk;
+ } else if (reg == 2) {
+ tclk = &emi_slow_clk;
+ } else {
+ tclk = &ahb_clk;
+ }
+ clk_set_parent(&ddr_clk, tclk);
+
+ clk_set_parent(&esdhc1_clk[2], &tmax2_clk);
+ clk_set_parent(&esdhc2_clk[0], &esdhc1_clk[0]);
+ clk_set_parent(&esdhc3_clk[0], &pll2_sw_clk);
+
+ clk_set_parent(&ipu_di_clk[0], &pll4_sw_clk);
+
+#if 0
+ /*Setup the LPM bypass bits */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS
+ | MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS
+ | MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS
+ | MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+#endif
+
+ clk_enable(&cpu_clk);
+
+ clk_enable(&main_bus_clk);
+
+ /* Set AXI_B_CLK to be 200MHz */
+ clk_set_rate(&axi_b_clk, 200000000);
+
+ /* Initialise the parents to be axi_b, parents are set to
+ * axi_a when the clocks are enabled.
+ */
+
+ clk_set_parent(&vpu_clk[0], &axi_b_clk);
+ clk_set_parent(&vpu_clk[1], &axi_b_clk);
+
+ /* move cspi to 24MHz */
+ clk_set_parent(&cspi_main_clk, &lp_apm_clk);
+ clk_set_rate(&cspi_main_clk, 12000000);
+ /*move the spdif0 to spdif_xtal_ckl */
+ clk_set_parent(&spdif0_clk[0], &spdif_xtal_clk);
+ /*set the SPDIF dividers to 1 */
+ reg = __raw_readl(MXC_CCM_CDCDR);
+ reg &= ~MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK;
+ __raw_writel(reg, MXC_CCM_CDCDR);
+
+ /* Move SSI clocks to SSI_LP_APM clock */
+ clk_set_parent(&ssi_lp_apm_clk, &lp_apm_clk);
+
+ clk_set_parent(&ssi1_clk[0], &ssi_lp_apm_clk);
+ /* set the SSI dividers to divide by 2 */
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ clk_set_parent(&ssi2_clk[0], &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ /* Change the SSI_EXT1_CLK to be sourced from PLL2 for camera */
+ clk_disable(&ssi_ext1_clk);
+ clk_set_parent(&ssi_ext1_clk, &pll2_sw_clk);
+ clk_set_rate(&ssi_ext1_clk, 24000000);
+ clk_enable(&ssi_ext1_clk);
+ clk_set_parent(&ssi_ext2_clk, &ssi2_clk[0]);
+
+ /* move usb_phy_clk to 24MHz */
+ clk_set_parent(&usb_phy_clk[0], &osc_clk);
+ clk_set_parent(&usb_phy_clk[1], &osc_clk);
+
+ /* set usboh3_clk to pll2 */
+ clk_set_parent(&usboh3_clk[0], &pll2_sw_clk);
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
+ reg |= 4 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
+ reg |= 1 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ /* set SDHC root clock as 200MHZ*/
+ clk_set_rate(&esdhc1_clk[0], 200000000);
+ clk_set_rate(&esdhc3_clk[0], 200000000);
+
+ /* Set the 1588 RTC input clocks as 108MHZ */
+ clk_set_parent(&ieee_rtc_clk, &pll3_sw_clk);
+ clk_set_rate(&ieee_rtc_clk, 108000000);
+
+ /* The CPU working point should be set according to part number
+ * information. But part number information is not clear now.
+ * So update the cpu working point table based on the PLL1 freq
+ * at boot time
+ */
+ pll1_rate = clk_get_rate(&pll1_main_clk);
+
+ if (pll1_rate > 1000000000)
+ mx53_set_cpu_part_number(IMX53_CEC_1_2G);
+ else if (pll1_rate > 800000000)
+ mx53_set_cpu_part_number(IMX53_CEC);
+ else
+ mx53_set_cpu_part_number(IMX53_AEC);
+
+ /* Set the current working point. */
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (clk_get_rate(&cpu_clk) == cpu_wp_tbl[i].cpu_rate) {
+ cpu_curr_wp = i;
+ break;
+ }
+ }
+ if (i > cpu_wp_nr)
+ BUG();
+
+ clk_set_parent(&arm_axi_clk, &axi_b_clk);
+ clk_set_parent(&ipu_clk[0], &axi_b_clk);
+ clk_set_parent(&uart_main_clk, &pll3_sw_clk);
+ clk_set_parent(&gpu3d_clk, &axi_b_clk);
+ clk_set_parent(&gpu2d_clk, &axi_b_clk);
+
+ clk_set_parent(&emi_slow_clk, &ahb_clk);
+ clk_set_rate(&emi_slow_clk, clk_round_rate(&emi_slow_clk, 133333333));
+
+ clk_set_rate(&emi_enfc_clk, clk_round_rate(&emi_enfc_clk,
+ MAX_NFC_CLK));
+
+ /* set the freq of asrc_serial_clk */
+ clk_set_rate(&asrc_clk[0], clk_round_rate(&asrc_clk[0],
+ 1190000));
+ base = ioremap(MX53_BASE_ADDR(GPT1_BASE_ADDR), SZ_4K);
+ mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
+ return 0;
+}
+
+/*!
+ * Setup cpu clock based on working point.
+ * @param wp cpu freq working point
+ * @return 0 on success or error code on failure.
+ */
+static int cpu_clk_set_wp(int wp)
+{
+ struct cpu_wp *p;
+ u32 reg, pll_hfsm;
+ u32 stat;
+
+ if (wp == cpu_curr_wp)
+ return 0;
+
+ p = &cpu_wp_tbl[wp];
+
+ /*
+ * If DDR clock is sourced from PLL1, we cannot drop PLL1 freq.
+ * Use the ARM_PODF to change the freq of the core, leave the PLL1
+ * freq unchanged. Meanwhile, if pll_rate is same, use the ARM_PODF
+ * to change the freq of core
+ */
+ if ((ddr_clk.parent == &ddr_hf_clk) ||
+ (p->pll_rate == cpu_wp_tbl[cpu_curr_wp].pll_rate)) {
+ reg = __raw_readl(MXC_CCM_CACRR);
+ reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
+ reg |= cpu_wp_tbl[wp].cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CACRR);
+ cpu_curr_wp = wp;
+ } else {
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+ /* Change the ARM clock to requested frequency */
+ /* First move the ARM clock to step clock which is running
+ * at 24MHz.
+ */
+
+ /* Change the source of pll1_sw_clk to be the step_clk */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ /* Stop the PLL */
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
+ reg &= ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
+
+ reg = __raw_readl(MXC_CCM_CACRR);
+ reg = (reg & ~MXC_CCM_CACRR_ARM_PODF_MASK)
+ | p->cpu_podf;
+ __raw_writel(reg, MXC_CCM_CACRR);
+
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
+ pll_hfsm = reg & MXC_PLL_DP_CTL_HFSM;
+ /* PDF and MFI */
+ reg = p->pdf | p->mfi << MXC_PLL_DP_OP_MFI_OFFSET;
+ if (pll_hfsm == 0) {
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_OP);
+ __raw_writel(p->mfd, pll1_base + MXC_PLL_DP_MFD);
+ __raw_writel(p->mfn, pll1_base + MXC_PLL_DP_MFN);
+ } else {
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_HFS_OP);
+ __raw_writel(p->mfd, pll1_base + MXC_PLL_DP_HFS_MFD);
+ __raw_writel(p->mfn, pll1_base + MXC_PLL_DP_HFS_MFN);
+ }
+
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
+ reg |= MXC_PLL_DP_CTL_UPEN;
+ /* Set the UPEN bits */
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
+ /* Forcefully restart the PLL */
+ reg |= MXC_PLL_DP_CTL_RST;
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
+
+ /* Wait for the PLL to lock */
+ getnstimeofday(&nstimeofday);
+ do {
+ getnstimeofday(&curtime);
+ if ((curtime.tv_nsec - nstimeofday.tv_nsec) > SPIN_DELAY)
+ panic("pll1 relock failed\n");
+ stat = __raw_readl(pll1_base + MXC_PLL_DP_CTL) &
+ MXC_PLL_DP_CTL_LRF;
+ } while (!stat);
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+ /* Move the PLL1 back to the pll1_main_clk */
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ cpu_curr_wp = wp;
+ }
+
+#if defined(CONFIG_CPU_FREQ)
+ cpufreq_trig_needed = 1;
+#endif
+ return 0;
+}
diff --git a/arch/arm/mach-mx5/clock_mx50.c b/arch/arm/mach-mx5/clock_mx50.c
new file mode 100644
index 000000000000..87eee08fdbb5
--- /dev/null
+++ b/arch/arm/mach-mx5/clock_mx50.c
@@ -0,0 +1,3523 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/clkdev.h>
+#include <asm/div64.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/sdram_autogating.h>
+
+#include "crm_regs.h"
+#include "serial.h"
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+
+static struct clk pll1_main_clk;
+static struct clk pll1_sw_clk;
+static struct clk pll2_sw_clk;
+static struct clk pll3_sw_clk;
+static struct clk apbh_dma_clk;
+static struct clk apll_clk;
+static struct clk pfd0_clk;
+static struct clk pfd1_clk;
+static struct clk pfd2_clk;
+static struct clk pfd3_clk;
+static struct clk pfd4_clk;
+static struct clk pfd5_clk;
+static struct clk pfd6_clk;
+static struct clk pfd7_clk;
+static struct clk lp_apm_clk;
+static struct clk weim_clk[];
+static struct clk ddr_clk;
+static struct clk axi_a_clk;
+static struct clk axi_b_clk;
+static struct clk gpu2d_clk;
+static int cpu_curr_wp;
+static struct cpu_wp *cpu_wp_tbl;
+
+static void __iomem *pll1_base;
+static void __iomem *pll2_base;
+static void __iomem *pll3_base;
+void __iomem *apll_base;
+
+extern int cpu_wp_nr;
+extern int lp_high_freq;
+extern int lp_med_freq;
+
+void __iomem *databahn;
+
+#define DDR_SYNC_MODE 0x30000
+#define SPIN_DELAY 1000000 /* in nanoseconds */
+#define WAIT(exp, timeout) \
+({ \
+ struct timespec nstimeofday; \
+ struct timespec curtime; \
+ int result = 1; \
+ getnstimeofday(&nstimeofday); \
+ while (!(exp)) { \
+ getnstimeofday(&curtime); \
+ if ((curtime.tv_nsec - nstimeofday.tv_nsec) > (timeout)) { \
+ result = 0; \
+ break; \
+ } \
+ } \
+ result; \
+})
+
+#define MAX_AXI_A_CLK_MX50 400000000
+#define MAX_AXI_B_CLK_MX50 200000000
+#define MAX_AHB_CLK 133333333
+#define MAX_EMI_SLOW_CLK 133000000
+
+extern int mxc_jtag_enabled;
+extern int uart_at_24;
+extern int cpufreq_trig_needed;
+extern int low_bus_freq_mode;
+extern int med_bus_freq_mode;
+
+static int cpu_clk_set_wp(int wp);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+
+static struct clk esdhc3_clk[];
+
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
+{
+ u32 min_pre, temp_pre, old_err, err;
+
+ if (div >= 512) {
+ *pre = 8;
+ *post = 64;
+ } else if (div >= 8) {
+ min_pre = (div - 1) / 64 + 1;
+ old_err = 8;
+ for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+ err = div % temp_pre;
+ if (err == 0) {
+ *pre = temp_pre;
+ break;
+ }
+ err = temp_pre - err;
+ if (err < old_err) {
+ old_err = err;
+ *pre = temp_pre;
+ }
+ }
+ *post = (div + *pre - 1) / *pre;
+ } else if (div < 8) {
+ *pre = div;
+ *post = 1;
+ }
+}
+
+static int _clk_enable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg |= MXC_CCM_CCGRx_CG_MASK << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq++;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq++;
+
+ return 0;
+}
+
+static int _clk_enable_inrun(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+ return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ __raw_writel(reg, clk->enable_reg);
+
+ if (clk->flags & AHB_HIGH_SET_POINT)
+ lp_high_freq--;
+ else if (clk->flags & AHB_MED_SET_POINT)
+ lp_med_freq--;
+}
+
+static void _clk_disable_inwait(struct clk *clk)
+{
+ u32 reg;
+ reg = __raw_readl(clk->enable_reg);
+ reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+ reg |= 1 << clk->enable_shift;
+ __raw_writel(reg, clk->enable_reg);
+}
+
+static unsigned long _clk_round_rate_div(struct clk *clk,
+ unsigned long rate,
+ u32 max_div,
+ u32 *new_div)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = DIV_ROUND_UP(parent_rate, rate);
+ if (div > max_div)
+ div = max_div;
+ else if (div == 0)
+ div++;
+ if (new_div != NULL)
+ *new_div = div;
+
+ return parent_rate / div;
+}
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+ struct clk *m1, struct clk *m2, struct clk *m3)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else
+ BUG();
+
+ return 0;
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux8(struct clk *parent, struct clk *m0, struct clk *m1,
+ struct clk *m2, struct clk *m3, struct clk *m4,
+ struct clk *m5, struct clk *m6, struct clk *m7)
+{
+ if (parent == m0)
+ return 0;
+ else if (parent == m1)
+ return 1;
+ else if (parent == m2)
+ return 2;
+ else if (parent == m3)
+ return 3;
+ else if (parent == m4)
+ return 4;
+ else if (parent == m5)
+ return 5;
+ else if (parent == m6)
+ return 6;
+ else if (parent == m7)
+ return 7;
+ else
+ BUG();
+
+ return 0;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+ if (pll == &pll1_main_clk)
+ return pll1_base;
+ else if (pll == &pll2_sw_clk)
+ return pll2_base;
+ else if (pll == &pll3_sw_clk)
+ return pll3_base;
+ else
+ BUG();
+
+ return NULL;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+ return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+ return external_low_reference;
+}
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+ return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+ return ckih2_reference;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+ .get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+ .get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+ .get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+ .get_rate = get_low_reference_clock_rate,
+};
+
+static int apll_enable(struct clk *clk)
+{
+ __raw_writel(1, apll_base + MXC_ANADIG_MISC_SET);
+ return 0;
+}
+
+static void apll_disable(struct clk *clk)
+{
+ __raw_writel(1, apll_base + MXC_ANADIG_MISC_CLR);
+}
+
+static unsigned long apll_get_rate(struct clk *clk)
+{
+ return 480000000;
+}
+
+static struct clk apll_clk = {
+ .get_rate = apll_get_rate,
+ .enable = apll_enable,
+ .disable = apll_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long pfd_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 frac;
+ u64 tmp;
+ tmp = (u64)clk_get_rate(clk->parent) * 18;
+ do_div(tmp, rate);
+ frac = tmp;
+ frac = frac < 18 ? 18 : frac;
+ frac = frac > 35 ? 35 : frac;
+ do_div(tmp, frac);
+ return tmp;
+}
+
+static int pfd_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 frac;
+ u64 tmp;
+ tmp = (u64)clk_get_rate(clk->parent) * 18;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+
+ do_div(tmp, rate);
+ frac = tmp;
+ frac = frac < 18 ? 18 : frac;
+ frac = frac > 35 ? 35 : frac;
+ /* clear clk frac bits */
+ __raw_writel(MXC_ANADIG_PFD_FRAC_MASK << clk->enable_shift,
+ apll_base + (int)clk->enable_reg + 8);
+ /* set clk frac bits */
+ __raw_writel(frac << clk->enable_shift,
+ apll_base + (int)clk->enable_reg + 4);
+
+ tmp = (u64)clk_get_rate(clk->parent) * 18;
+ do_div(tmp, frac);
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+ return 0;
+}
+
+static int pfd_enable(struct clk *clk)
+{
+ int index;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+ index = _get_mux8(clk, &pfd0_clk, &pfd1_clk, &pfd2_clk, &pfd3_clk,
+ &pfd4_clk, &pfd5_clk, &pfd6_clk, &pfd7_clk);
+ __raw_writel(1 << (index + MXC_ANADIG_PFD_DIS_OFFSET),
+ apll_base + MXC_ANADIG_PLLCTRL_CLR);
+ /* clear clk gate bit */
+ __raw_writel((1 << (clk->enable_shift + 7)),
+ apll_base + (int)clk->enable_reg + 8);
+
+ /* check lock bit */
+ if (!WAIT(__raw_readl(apll_base + MXC_ANADIG_PLLCTRL)
+ & MXC_ANADIG_APLL_LOCK, 50000)) {
+ __raw_writel(MXC_ANADIG_APLL_FORCE_LOCK,
+ apll_base + MXC_ANADIG_PLLCTRL_CLR);
+ __raw_writel(MXC_ANADIG_APLL_FORCE_LOCK,
+ apll_base + MXC_ANADIG_PLLCTRL_SET);
+ if (!WAIT(__raw_readl(apll_base + MXC_ANADIG_PLLCTRL)
+ & MXC_ANADIG_APLL_LOCK, SPIN_DELAY))
+ panic("pfd_enable failed!\n");
+ }
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+ return 0;
+}
+
+static void pfd_disable(struct clk *clk)
+{
+ int index;
+
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.enable(&apbh_dma_clk);
+ index = _get_mux8(clk, &pfd0_clk, &pfd1_clk, &pfd2_clk, &pfd3_clk,
+ &pfd4_clk, &pfd5_clk, &pfd6_clk, &pfd7_clk);
+ /* set clk gate bit */
+ __raw_writel((1 << (clk->enable_shift + 7)),
+ apll_base + (int)clk->enable_reg + 4);
+ __raw_writel(1 << (index + MXC_ANADIG_PFD_DIS_OFFSET),
+ apll_base + MXC_ANADIG_PLLCTRL_SET);
+ if (apbh_dma_clk.usecount == 0)
+ apbh_dma_clk.disable(&apbh_dma_clk);
+}
+
+static struct clk pfd0_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC0,
+ .enable_shift = MXC_ANADIG_PFD0_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd1_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC0,
+ .enable_shift = MXC_ANADIG_PFD1_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd2_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC0,
+ .enable_shift = MXC_ANADIG_PFD2_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd3_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC0,
+ .enable_shift = MXC_ANADIG_PFD3_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd4_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC1,
+ .enable_shift = MXC_ANADIG_PFD4_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd5_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC1,
+ .enable_shift = MXC_ANADIG_PFD5_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd6_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC1,
+ .enable_shift = MXC_ANADIG_PFD6_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk pfd7_clk = {
+ .parent = &apll_clk,
+ .enable_reg = (void *)MXC_ANADIG_FRAC1,
+ .enable_shift = MXC_ANADIG_PFD7_FRAC_OFFSET,
+ .set_rate = pfd_set_rate,
+ .round_rate = pfd_round_rate,
+ .enable = pfd_enable,
+ .disable = pfd_disable,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long _clk_pll_get_rate(struct clk *clk)
+{
+ long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+ unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+ void __iomem *pllbase;
+ s64 temp;
+
+ pllbase = _get_pll_base(clk);
+
+ dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+ dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+ if (pll_hfsm == 0) {
+ dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+ dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+ dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+ } else {
+ dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+ dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+ dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+ }
+ pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+ mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+ mfi = (mfi <= 5) ? 5 : mfi;
+ mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+ mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+ /* Sign extend to 32-bits */
+ if (mfn >= 0x04000000) {
+ mfn |= 0xFC000000;
+ mfn_abs = -mfn;
+ }
+
+ ref_clk = 2 * clk_get_rate(clk->parent);
+ if (dbl != 0)
+ ref_clk *= 2;
+
+ ref_clk /= (pdf + 1);
+ temp = (u64) ref_clk * mfn_abs;
+ do_div(temp, mfd + 1);
+ if (mfn < 0)
+ temp = -temp;
+ temp = (ref_clk * mfi) + temp;
+
+ return temp;
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, reg1;
+ void __iomem *pllbase;
+
+ long mfi, pdf, mfn, mfd = 999999;
+ s64 temp64;
+ unsigned long quad_parent_rate;
+ unsigned long pll_hfsm, dp_ctl;
+
+ pllbase = _get_pll_base(clk);
+
+ quad_parent_rate = 4 * clk_get_rate(clk->parent);
+ pdf = mfi = -1;
+ while (++pdf < 16 && mfi < 5)
+ mfi = rate * (pdf+1) / quad_parent_rate;
+ if (mfi > 15)
+ return -1;
+ pdf--;
+
+ temp64 = rate*(pdf+1) - quad_parent_rate*mfi;
+ do_div(temp64, quad_parent_rate/1000000);
+ mfn = (long)temp64;
+
+ dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ /* use dpdck0_2 */
+ __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+ pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+ if (pll_hfsm == 0) {
+ reg = mfi<<4 | pdf;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+ __raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+ __raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+ } else {
+ reg = mfi<<4 | pdf;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+ __raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+ __raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+ }
+ /* If auto restart is disabled, restart the PLL and
+ * wait for it to lock.
+ */
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ if (reg & MXC_PLL_DP_CTL_UPEN) {
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CONFIG);
+ if (!(reg & MXC_PLL_DP_CONFIG_AREN)) {
+ reg1 = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+ reg1 |= MXC_PLL_DP_CTL_RST;
+ __raw_writel(reg1, pllbase + MXC_PLL_DP_CTL);
+ }
+ /* Wait for lock */
+ if (!WAIT(__raw_readl(pllbase + MXC_PLL_DP_CTL)
+ & MXC_PLL_DP_CTL_LRF, SPIN_DELAY))
+ panic("pll_set_rate: pll relock failed\n");
+ }
+ return 0;
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+ u32 reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+
+ if (reg & MXC_PLL_DP_CTL_UPEN)
+ return 0;
+
+ reg |= MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+ /* Wait for lock */
+ if (!WAIT(__raw_readl(pllbase + MXC_PLL_DP_CTL) & MXC_PLL_DP_CTL_LRF,
+ SPIN_DELAY))
+ panic("pll relock failed\n");
+ return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+ u32 reg;
+ void __iomem *pllbase;
+
+ pllbase = _get_pll_base(clk);
+ reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static struct clk pll1_main_clk = {
+ .parent = &osc_clk,
+ .get_rate = _clk_pll_get_rate,
+ .set_rate = _clk_pll_set_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll1_main_clk) {
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set the step_clk parent to be lp_apm, to save power. */
+ mux = _get_mux(&lp_apm_clk, &lp_apm_clk, NULL, &pll2_sw_clk,
+ &pll3_sw_clk);
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) |
+ (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ } else {
+ if (parent == &lp_apm_clk) {
+ mux = _get_mux(parent, &lp_apm_clk, NULL, &pll2_sw_clk,
+ &pll3_sw_clk);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) |
+ (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCSR);
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ } else {
+ mux = _get_mux(parent, &lp_apm_clk, NULL, &pll2_sw_clk,
+ &pll3_sw_clk);
+ reg = (reg & ~MXC_CCM_CCSR_STEP_SEL_MASK) |
+ (mux << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CCSR);
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+
+ }
+ }
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ return 0;
+}
+
+static unsigned long _clk_pll1_sw_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+ div = 1;
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (clk->parent == &pll2_sw_clk) {
+ div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+ MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+ } else if (clk->parent == &pll3_sw_clk) {
+ div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+ MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+/* pll1 switch clock */
+static struct clk pll1_sw_clk = {
+ .parent = &pll1_main_clk,
+ .set_parent = _clk_pll1_sw_set_parent,
+ .get_rate = _clk_pll1_sw_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCSR);
+
+ if (parent == &pll2_sw_clk) {
+ reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+ } else {
+ reg = (reg & ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL);
+ reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+ }
+ __raw_writel(reg, MXC_CCM_CCSR);
+ return 0;
+}
+
+/* same as pll2_main_clk. These two clocks should always be the same */
+static struct clk pll2_sw_clk = {
+ .parent = &osc_clk,
+ .get_rate = _clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .set_rate = _clk_pll_set_rate,
+ .set_parent = _clk_pll2_sw_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+/* same as pll3_main_clk. These two clocks should always be the same */
+static struct clk pll3_sw_clk = {
+ .parent = &osc_clk,
+ .set_rate = _clk_pll_set_rate,
+ .get_rate = _clk_pll_get_rate,
+ .enable = _clk_pll_enable,
+ .disable = _clk_pll_disable,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ if (parent == &osc_clk)
+ reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+ else if (parent == &apll_clk)
+ reg = __raw_readl(MXC_CCM_CCSR) | MXC_CCM_CCSR_LP_APM_SEL;
+ else
+ return -EINVAL;
+
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ return 0;
+}
+
+static struct clk lp_apm_clk = {
+ .parent = &osc_clk,
+ .set_parent = _clk_lp_apm_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_arm_get_rate(struct clk *clk)
+{
+ u32 cacrr, div;
+
+ cacrr = __raw_readl(MXC_CCM_CACRR);
+ div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 i;
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (rate == cpu_wp_tbl[i].cpu_rate)
+ break;
+ }
+ if (i >= cpu_wp_nr)
+ return -EINVAL;
+ cpu_clk_set_wp(i);
+
+ return 0;
+}
+
+static unsigned long _clk_cpu_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 i;
+ u32 wp;
+
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (rate == cpu_wp_tbl[i].cpu_rate)
+ break;
+ }
+
+ if (i > cpu_wp_nr)
+ wp = 0;
+
+ return cpu_wp_tbl[wp].cpu_rate;
+}
+
+
+static struct clk cpu_clk = {
+ .parent = &pll1_sw_clk,
+ .get_rate = _clk_arm_get_rate,
+ .set_rate = _clk_cpu_set_rate,
+ .round_rate = _clk_cpu_round_rate,
+};
+
+/* TODO: Need to sync with GPC to determine if DVFS is in place so that
+ * the DVFS_PODF divider can be applied in CDCR register.
+ */
+static unsigned long _clk_main_bus_get_rate(struct clk *clk)
+{
+ u32 div = 0;
+
+ if (med_bus_freq_mode)
+ div = (__raw_readl(MXC_CCM_CDCR) & 0x3);
+ return clk_get_rate(clk->parent) / (div + 1);
+}
+
+static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CBCDR) & ~MX50_CCM_CBCDR_PERIPH_CLK_SEL_MASK;
+ reg |= (mux << MX50_CCM_CBCDR_PERIPH_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ return 0;
+}
+
+static struct clk main_bus_clk = {
+ .parent = &pll2_sw_clk,
+ .set_parent = _clk_main_bus_set_parent,
+ .get_rate = _clk_main_bus_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_axi_a_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AXI_A_PODF_MASK) >>
+ MXC_CCM_CBCDR_AXI_A_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_axi_a_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AXI_A_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_AXI_A_PODF_BUSY), SPIN_DELAY))
+ panic("pll _clk_axi_a_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_axi_a_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+
+ return parent_rate / div;
+}
+
+
+static struct clk axi_a_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = _clk_axi_a_get_rate,
+ .set_rate = _clk_axi_a_set_rate,
+ .round_rate = _clk_axi_a_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_axi_b_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AXI_B_PODF_MASK) >>
+ MXC_CCM_CBCDR_AXI_B_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_axi_b_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AXI_B_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR)
+ & MXC_CCM_CDHIPR_AXI_B_PODF_BUSY), SPIN_DELAY))
+ panic("_clk_axi_b_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_axi_b_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+
+ return parent_rate / div;
+}
+
+
+static struct clk axi_b_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = _clk_axi_b_get_rate,
+ .set_rate = _clk_axi_b_set_rate,
+ .round_rate = _clk_axi_b_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_ahb_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+ MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_AHB_PODF_BUSY),
+ SPIN_DELAY))
+ panic("_clk_ahb_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ /* Make sure rate is not greater than the maximum value for the clock.
+ * Also prevent a div of 0.
+ */
+ if (div == 0)
+ div++;
+ if (parent_rate / div > MAX_AHB_CLK)
+ div++;
+
+ if (div > 8)
+ div = 8;
+
+ return parent_rate / div;
+}
+
+
+static struct clk ahb_clk = {
+ .parent = &main_bus_clk,
+ .get_rate = _clk_ahb_get_rate,
+ .set_rate = _clk_ahb_set_rate,
+ .round_rate = _clk_ahb_round_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static int _clk_max_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+
+ /* Handshake with MAX when LPM is entered. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg &= ~MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+
+static void _clk_max_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_disable_inwait(clk);
+
+ /* No Handshake with MAX when LPM is entered as its disabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+
+static struct clk ahb_max_clk = {
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_max_enable,
+ .disable = _clk_max_disable,
+};
+
+static struct clk ahbmux1_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .disable = _clk_disable_inwait,
+};
+
+static unsigned long _clk_ipg_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+ MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static struct clk ipg_clk = {
+ .parent = &ahb_clk,
+ .get_rate = _clk_ipg_get_rate,
+ .flags = RATE_PROPAGATES,
+};
+
+static unsigned long _clk_ipg_per_get_rate(struct clk *clk)
+{
+ u32 reg, prediv1, prediv2, podf;
+
+ if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+ /* the main_bus_clk is the one before the DVFS engine */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
+ prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
+ MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
+ return clk_get_rate(clk->parent) / (prediv1 * prediv2 * podf);
+ } else if (clk->parent == &ipg_clk) {
+ return clk_get_rate(&ipg_clk);
+ }
+ BUG();
+ return 0;
+}
+
+static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &main_bus_clk, &lp_apm_clk, &ipg_clk, NULL);
+ if (mux == 2) {
+ reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+ } else {
+ reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+ if (mux == 0)
+ reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+ else
+ reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+ }
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk ipg_perclk = {
+ .parent = &lp_apm_clk,
+ .get_rate = _clk_ipg_per_get_rate,
+ .set_parent = _clk_ipg_per_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk ipmux1_clk = {
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static struct clk ipmux2_clk = {
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static int _clk_sys_clk_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CLK_SYS);
+ reg &= ~(MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_MASK |
+ MXC_CCM_CLK_SYS_SYS_PLL_CLKGATE_MASK);
+ if (__raw_readl(MXC_CCM_CLKSEQ_BYPASS) & 0x1)
+ reg |= MXC_CCM_CLK_SYS_SYS_PLL_CLKGATE_MASK;
+ else
+ reg |= MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_CLK_SYS);
+ return 0;
+}
+
+static void _clk_sys_clk_disable(struct clk *clk)
+{
+ u32 reg, reg1;
+
+ reg1 = (__raw_readl(databahn + DATABAHN_CTL_REG55))
+ & DDR_SYNC_MODE;
+ reg = __raw_readl(MXC_CCM_CLK_SYS);
+ reg &= ~(MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_MASK |
+ MXC_CCM_CLK_SYS_SYS_PLL_CLKGATE_MASK);
+ if (__raw_readl(MXC_CCM_CLKSEQ_BYPASS) & 0x1)
+ reg |= 1 << MXC_CCM_CLK_SYS_SYS_PLL_CLKGATE_OFFSET;
+ else {
+ /* If DDR is sourced from SYS_CLK (in Sync mode), we cannot
+ * gate its clock when ARM is in wait if the DDR is not in
+ * self refresh.
+ */
+ if (reg1 == DDR_SYNC_MODE)
+ reg |= 3 << MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_OFFSET;
+ else
+ reg |= 1 << MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_OFFSET;
+ }
+ __raw_writel(reg, MXC_CCM_CLK_SYS);
+}
+
+static struct clk sys_clk = {
+ .enable = _clk_sys_clk_enable,
+ .disable = _clk_sys_clk_disable,
+};
+
+
+static int _clk_weim_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ if (parent == &ahb_clk)
+ reg |= MX50_CCM_CBCDR_WEIM_CLK_SEL;
+ else if (parent == &main_bus_clk)
+ reg &= ~MX50_CCM_CBCDR_WEIM_CLK_SEL;
+ else
+ BUG();
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ return 0;
+}
+
+static int _clk_weim_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || (div > 8))
+ return -EINVAL;
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_EMI_PODF_MASK;
+ reg |= (div - 1) << MXC_CCM_CBCDR_EMI_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CBCDR);
+ if (!WAIT(!(__raw_readl(MXC_CCM_CDHIPR) & MXC_CCM_CDHIPR_EMI_PODF_BUSY),
+ SPIN_DELAY))
+ panic("_clk_emi_slow_set_rate failed\n");
+
+ return 0;
+}
+
+static unsigned long _clk_weim_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div > 8)
+ div = 8;
+ else if (div == 0)
+ div++;
+ return parent_rate / div;
+}
+
+static struct clk weim_clk[] = {
+ {
+ .parent = &main_bus_clk,
+ .set_parent = _clk_weim_set_parent,
+ .set_rate = _clk_weim_set_rate,
+ .round_rate = _clk_weim_round_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .disable = _clk_disable_inwait,
+ .flags = RATE_PROPAGATES,
+ .secondary = &weim_clk[1],
+ },
+ {
+ .parent = &ipg_clk,
+ .secondary = &sys_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .disable = _clk_disable_inwait,
+ }
+};
+
+static int _clk_ocram_enable(struct clk *clk)
+{
+ return 0;
+}
+
+static void _clk_ocram_disable(struct clk *clk)
+{
+}
+
+static struct clk ocram_clk = {
+ .parent = &sys_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .enable = _clk_ocram_enable,
+ .disable = _clk_ocram_disable,
+};
+
+static struct clk aips_tz1_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk aips_tz2_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable_reg = MXC_CCM_CCGR0,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+};
+
+static struct clk gpc_dvfs_clk = {
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static int _clk_sdma_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+
+ /* Handshake with SDMA when LPM is entered. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg &= ~MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+
+ return 0;
+}
+
+static void _clk_sdma_disable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_disable(clk);
+ /* No handshake with SDMA as its not enabled. */
+ reg = __raw_readl(MXC_CCM_CLPCR);
+ reg |= MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS;
+ __raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+
+static struct clk sdma_clk[] = {
+ {
+ .parent = &ahb_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .enable = _clk_sdma_enable,
+ .disable = _clk_sdma_disable,
+ },
+ {
+ .parent = &ipg_clk,
+ .secondary = &ddr_clk,
+ },
+};
+
+static struct clk spba_clk = {
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR5,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_uart_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent)/(prediv * podf) ;
+}
+
+static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk uart_main_clk = {
+ .parent = &pll2_sw_clk,
+ .get_rate = _clk_uart_get_rate,
+ .set_parent = _clk_uart_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk uart1_clk[] = {
+ {
+ .id = 0,
+ .parent = &uart_main_clk,
+ .secondary = &uart1_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART1_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+#if UART1_DMA_ENABLE
+ .secondary = &aips_tz1_clk,
+#endif
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart2_clk[] = {
+ {
+ .id = 1,
+ .parent = &uart_main_clk,
+ .secondary = &uart2_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART2_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+#if UART2_DMA_ENABLE
+ .secondary = &aips_tz1_clk,
+#endif
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart3_clk[] = {
+ {
+ .id = 2,
+ .parent = &uart_main_clk,
+ .secondary = &uart3_clk[1],
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART3_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 2,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart4_clk[] = {
+ {
+ .id = 3,
+ .parent = &uart_main_clk,
+ .secondary = &uart4_clk[1],
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART4_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 3,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk uart5_clk[] = {
+ {
+ .id = 4,
+ .parent = &uart_main_clk,
+ .secondary = &uart5_clk[1],
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+#if UART5_DMA_ENABLE
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+#endif
+ },
+ {
+ .id = 4,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk gpt_clk[] = {
+ {
+ .parent = &ipg_perclk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ckil_clk,
+ },
+};
+
+static struct clk pwm1_clk[] = {
+ {
+ .parent = &ipg_perclk,
+ .id = 0,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &pwm1_clk[1],
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ckil_clk,
+ },
+};
+
+static struct clk pwm2_clk[] = {
+ {
+ .parent = &ipg_perclk,
+ .id = 1,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &pwm2_clk[1],
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ckil_clk,
+ },
+};
+
+static struct clk i2c_clk[] = {
+ {
+ .id = 0,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 2,
+ .parent = &ipg_perclk,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+};
+
+static unsigned long _clk_cspi_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR2);
+ prediv = ((reg & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_cspi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk cspi_main_clk = {
+ .parent = &pll3_sw_clk,
+ .get_rate = _clk_cspi_get_rate,
+ .set_parent = _clk_cspi_set_parent,
+ .flags = RATE_PROPAGATES,
+};
+
+static struct clk cspi1_clk[] = {
+ {
+ .id = 0,
+ .parent = &cspi_main_clk,
+ .secondary = &cspi1_clk[1],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &spba_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk cspi2_clk[] = {
+ {
+ .id = 1,
+ .parent = &cspi_main_clk,
+ .secondary = &cspi2_clk[1],
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &aips_tz2_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable_inrun, /*Active only when ARM is running. */
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk cspi3_clk = {
+ .id = 2,
+ .parent = &ipg_clk,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .secondary = &aips_tz2_clk,
+};
+
+static int _clk_ssi_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &ckih_clk, &lp_apm_clk, &ckih2_clk, NULL);
+ reg = __raw_readl(MXC_CCM_CSCMR1) &
+ ~MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi_lp_apm_clk = {
+ .parent = &ckih_clk,
+ .set_parent = _clk_ssi_lp_apm_set_parent,
+};
+
+static unsigned long _clk_ssi1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+static int _clk_ssi1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+ &pll3_sw_clk, &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi1_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi1_set_parent,
+ .secondary = &ssi1_clk[1],
+ .get_rate = _clk_ssi1_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &ssi1_clk[2],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &aips_tz2_clk,
+ },
+};
+
+static unsigned long _clk_ssi2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ prediv = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK) >>
+ MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK) >>
+ MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_ssi2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+ &pll3_sw_clk, &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK;
+ reg |= mux << MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi2_clk[] = {
+ {
+ .id = 1,
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi2_set_parent,
+ .secondary = &ssi2_clk[1],
+ .get_rate = _clk_ssi2_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &ssi2_clk[2],
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &spba_clk,
+ },
+};
+
+static unsigned long _clk_ssi_ext1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+ u32 div = 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if ((reg & MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL) == 0) {
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ prediv = ((reg & MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK) >>
+ MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK) >>
+ MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET) + 1;
+ div = prediv * podf;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ssi_ext1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div, pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ if (div == 0)
+ div++;
+ if (((parent_rate / div) != rate) || div > 512)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~(MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK |
+ MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ return 0;
+}
+
+static int _clk_ssi_ext1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &ssi1_clk[0]) {
+ reg |= MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL;
+ } else {
+ reg &= ~MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL;
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &ssi_lp_apm_clk);
+ reg = (reg & ~MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET);
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_ssi_ext1_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+ u32 div = parent_rate / rate;
+
+ if (parent_rate % rate)
+ div++;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ return parent_rate / (pre * post);
+}
+
+static struct clk ssi_ext1_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi_ext1_set_parent,
+ .set_rate = _clk_ssi_ext1_set_rate,
+ .round_rate = _clk_ssi_ext1_round_rate,
+ .get_rate = _clk_ssi_ext1_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static unsigned long _clk_ssi_ext2_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+ u32 div = 1;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if ((reg & MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL) == 0) {
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ prediv = ((reg & MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK) >>
+ MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET) + 1;
+ if (prediv == 1)
+ BUG();
+ podf = ((reg & MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK) >>
+ MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET) + 1;
+ div = prediv * podf;
+ }
+ return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_ssi_ext2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &ssi2_clk[0]) {
+ reg |= MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL;
+ } else {
+ reg &= ~MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL;
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &ssi_lp_apm_clk);
+ reg = (reg & ~MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET);
+ }
+
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk ssi_ext2_clk = {
+ .parent = &pll3_sw_clk,
+ .set_parent = _clk_ssi_ext2_set_parent,
+ .get_rate = _clk_ssi_ext2_get_rate,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+};
+
+static struct clk tmax2_clk = {
+ .id = 0,
+ .parent = &ahb_clk,
+ .secondary = &ahb_max_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR1,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk usb_ahb_clk = {
+ .parent = &ipg_clk,
+ .secondary = &ddr_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk usb_phy_clk[] = {
+ {
+ .id = 0,
+ .parent = &osc_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 1,
+ .parent = &osc_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .disable = _clk_disable,
+ }
+};
+
+static struct clk esdhc_dep_clks = {
+ .parent = &spba_clk,
+ .secondary = &ddr_clk,
+};
+
+static unsigned long _clk_esdhc1_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_esdhc1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
+ &lp_apm_clk);
+ reg = reg & ~MX50_CCM_CSCMR1_ESDHC1_CLK_SEL_MASK;
+ reg |= mux << MX50_CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+
+static int _clk_esdhc1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set sdhc1 clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR1) &
+ ~(MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_MASK |
+ MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+static struct clk esdhc1_clk[] = {
+ {
+ .id = 0,
+ .parent = &pll2_sw_clk,
+ .set_parent = _clk_esdhc1_set_parent,
+ .get_rate = _clk_esdhc1_get_rate,
+ .set_rate = _clk_esdhc1_set_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc1_clk[1],
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .id = 0,
+ .parent = &ipg_clk,
+ .secondary = &esdhc1_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &tmax2_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+
+};
+
+static int _clk_esdhc2_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk[0])
+ reg &= ~MX50_CCM_CSCMR1_ESDHC2_CLK_SEL;
+ else if (parent == &esdhc3_clk[0])
+ reg |= MX50_CCM_CSCMR1_ESDHC2_CLK_SEL;
+ else
+ BUG();
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+ return 0;
+}
+
+static struct clk esdhc2_clk[] = {
+ {
+ .id = 1,
+ .parent = &esdhc1_clk[0],
+ .set_parent = _clk_esdhc2_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc2_clk[1],
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .id = 1,
+ .parent = &ipg_clk,
+ .secondary = &esdhc2_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &tmax2_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+};
+
+static int _clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ mux = _get_mux8(parent, &pll1_sw_clk, &pll2_sw_clk,
+ &pll3_sw_clk, &lp_apm_clk, &pfd0_clk,
+ &pfd1_clk, &pfd4_clk, &osc_clk);
+ reg = reg & ~MX50_CCM_CSCMR1_ESDHC3_CLK_SEL_MASK;
+ reg |= mux << MX50_CCM_CSCMR1_ESDHC3_CLK_SEL_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static unsigned long _clk_esdhc3_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ prediv = ((reg & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static int _clk_esdhc3_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg;
+ u32 div;
+ u32 pre, post;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+
+ if ((parent_rate / div) != rate)
+ return -EINVAL;
+
+ __calc_pre_post_dividers(div, &pre, &post);
+
+ /* Set sdhc1 clock divider */
+ reg = __raw_readl(MXC_CCM_CSCDR1) &
+ ~(MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK |
+ MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK);
+ reg |= (post - 1) << MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET;
+ reg |= (pre - 1) << MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CSCDR1);
+
+ return 0;
+}
+
+
+static struct clk esdhc3_clk[] = {
+ {
+ .id = 2,
+ .parent = &pll2_sw_clk,
+ .set_parent = _clk_esdhc3_set_parent,
+ .get_rate = _clk_esdhc3_get_rate,
+ .set_rate = _clk_esdhc3_set_rate,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc3_clk[1],
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .id = 2,
+ .parent = &ipg_clk,
+ .secondary = &esdhc3_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG4_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &ahb_max_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+};
+
+static int _clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CSCMR1);
+ if (parent == &esdhc1_clk[0])
+ reg &= ~MX50_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else if (parent == &esdhc3_clk[0])
+ reg |= MX50_CCM_CSCMR1_ESDHC4_CLK_SEL;
+ else
+ BUG();
+ __raw_writel(reg, MXC_CCM_CSCMR1);
+
+ return 0;
+}
+
+static struct clk esdhc4_clk[] = {
+ {
+ .id = 3,
+ .parent = &esdhc1_clk[0],
+ .set_parent = _clk_esdhc4_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable,
+ .secondary = &esdhc4_clk[1],
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .id = 3,
+ .parent = &ipg_clk,
+ .secondary = &esdhc4_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR3,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .disable = _clk_disable,
+ },
+ {
+ .id = 0,
+ .parent = &tmax2_clk,
+ .secondary = &esdhc_dep_clks,
+ },
+};
+
+static int _clk_ddr_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CLK_DDR);
+ if (parent == &pfd0_clk)
+ reg |= MXC_CCM_CLK_DDR_DDR_PFD_SEL;
+ else if (parent == &pll1_sw_clk)
+ reg &= ~MXC_CCM_CLK_DDR_DDR_PFD_SEL;
+ else
+ return -EINVAL;
+ __raw_writel(reg, MXC_CCM_CLK_DDR);
+ return 0;
+}
+
+static unsigned long _clk_ddr_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CLK_DDR);
+ div = (reg & MXC_CCM_CLK_DDR_DDR_DIV_PLL_MASK) >>
+ MXC_CCM_CLK_DDR_DDR_DIV_PLL_OFFSET;
+ if (div)
+ return clk_get_rate(clk->parent) / div;
+
+ return 0;
+}
+
+static int _clk_ddr_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+ reg = (__raw_readl(databahn + DATABAHN_CTL_REG55)) &
+ DDR_SYNC_MODE;
+ if (reg != DDR_SYNC_MODE) {
+ reg = __raw_readl(MXC_CCM_CLK_DDR);
+ reg |= MXC_CCM_CLK_DDR_DDR_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_CLK_DDR);
+ }
+ return 0;
+}
+
+static void _clk_ddr_disable(struct clk *clk)
+{
+ _clk_disable_inwait(clk);
+}
+
+
+static struct clk ddr_clk = {
+ .parent = &pll1_sw_clk,
+ .secondary = &sys_clk,
+ .set_parent = _clk_ddr_set_parent,
+ .get_rate = _clk_ddr_get_rate,
+ .enable = _clk_ddr_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+ .disable = _clk_ddr_disable,
+};
+
+static unsigned long _clk_pgc_get_rate(struct clk *clk)
+{
+ u32 reg, div;
+
+ reg = __raw_readl(MXC_CCM_CSCDR1);
+ div = (reg & MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK) >>
+ MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET;
+ div = 1 >> div;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static struct clk pgc_clk = {
+ .parent = &ipg_clk,
+ .get_rate = _clk_pgc_get_rate,
+};
+
+static unsigned long _clk_usb_get_rate(struct clk *clk)
+{
+ return 60000000;
+}
+
+/*usb OTG clock */
+static struct clk usb_clk = {
+ .get_rate = _clk_usb_get_rate,
+};
+
+static struct clk rtc_clk = {
+ .parent = &ckil_clk,
+ .secondary = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR4,
+ .enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+ .disable = _clk_disable,
+};
+
+struct clk rng_clk = {
+ .parent = &ipg_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk owire_clk = {
+ .parent = &ipg_perclk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .disable = _clk_disable,
+};
+
+static struct clk fec_clk[] = {
+ {
+ .parent = &ipg_clk,
+ .secondary = &fec_clk[1],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR2,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &aips_tz2_clk,
+ .secondary = &ddr_clk,
+ },
+};
+
+static int gpmi_clk_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_GPMI);
+ reg |= MXC_CCM_GPMI_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_GPMI);
+ _clk_enable(clk);
+ return 0;
+}
+
+static void gpmi_clk_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_GPMI);
+ reg &= ~MXC_CCM_GPMI_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_GPMI);
+ _clk_disable(clk);
+}
+
+static int bch_clk_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_BCH);
+ reg |= MXC_CCM_BCH_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_BCH);
+ _clk_enable(clk);
+ return 0;
+}
+
+static void bch_clk_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_BCH);
+ reg &= ~MXC_CCM_BCH_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_BCH);
+ _clk_disable(clk);
+}
+
+static int gpmi_set_parent(struct clk *clk, struct clk *parent)
+{
+ /* Setting for ONFI nand which need PLL1(800MHZ) */
+ if (parent == &pll1_main_clk) {
+ u32 reg = __raw_readl(MXC_CCM_CLKSEQ_BYPASS);
+
+ reg = (reg & ~MXC_CCM_CLKSEQ_BYPASS_BYPASS_GPMI_CLK_SEL_MASK) |
+ (0x2 << MXC_CCM_CLKSEQ_BYPASS_BYPASS_GPMI_CLK_SEL_OFFSET);
+ reg = (reg & ~MXC_CCM_CLKSEQ_BYPASS_BYPASS_BCH_CLK_SEL_MASK) |
+ (0x2 << MXC_CCM_CLKSEQ_BYPASS_BYPASS_BCH_CLK_SEL_OFFSET);
+
+ __raw_writel(reg, MXC_CCM_CLKSEQ_BYPASS);
+
+ /* change to the new Parent */
+ clk->parent = parent;
+ } else
+ printk(KERN_WARNING "You should not call the %s\n", __func__);
+ return 0;
+}
+
+static int gpmi_set_rate(struct clk *clk, unsigned long rate)
+{
+ /* Setting for ONFI nand which in different mode */
+ if (clk->parent == &pll1_main_clk) {
+ u32 value;
+ u32 reg;
+
+ value = clk_get_rate(clk->parent);
+ value /= rate;
+ value /= 2; /* HW_GPMI_CTRL1's GPMI_CLK_DIV2_EN will be set */
+
+ /* set GPMI clock */
+ reg = __raw_readl(MXC_CCM_GPMI);
+ reg = (reg & ~MXC_CCM_GPMI_CLK_DIV_MASK) | value;
+ __raw_writel(reg, MXC_CCM_GPMI);
+
+ /* set BCH clock */
+ reg = __raw_readl(MXC_CCM_BCH);
+ reg = (reg & ~MXC_CCM_BCH_CLK_DIV_MASK) | value;
+ __raw_writel(reg, MXC_CCM_BCH);
+ } else
+ printk(KERN_WARNING "You should not call the %s\n", __func__);
+ return 0;
+}
+
+static struct clk gpmi_nfc_clk[] = {
+ { /* gpmi_io_clk */
+ .parent = &osc_clk,
+ .secondary = &gpmi_nfc_clk[1],
+ .set_parent = gpmi_set_parent,
+ .set_rate = gpmi_set_rate,
+ .enable = gpmi_clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .disable = gpmi_clk_disable,
+ },
+ { /* gpmi_apb_clk */
+ .parent = &ahb_clk,
+ .secondary = &gpmi_nfc_clk[2],
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .disable = _clk_disable,
+ },
+ { /* bch_clk */
+ .parent = &osc_clk,
+ .secondary = &gpmi_nfc_clk[3],
+ .enable = bch_clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+ .disable = bch_clk_disable,
+ },
+ { /* bch_apb_clk */
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+ .disable = _clk_disable,
+ },
+};
+
+static struct clk ocotp_clk = {
+ .parent = &ahb_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+ .disable = _clk_disable,
+};
+
+static int _clk_gpu2d_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ mux = _get_mux(parent, &axi_a_clk, &axi_b_clk, &weim_clk[0], &ahb_clk);
+ reg = (reg & ~MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCMR);
+
+ return 0;
+}
+
+static struct clk gpu2d_clk = {
+ .parent = &axi_a_clk,
+ .secondary = &ddr_clk,
+ .set_parent = _clk_gpu2d_set_parent,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+ .disable = _clk_disable,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk apbh_dma_clk = {
+ .parent = &ahb_clk,
+ .secondary = &ddr_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable_inwait,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+};
+
+struct clk dcp_clk = {
+ .parent = &ahb_clk,
+ .secondary = &apbh_dma_clk,
+ .enable = _clk_enable,
+ .enable_reg = MXC_CCM_CCGR7,
+ .enable_shift = MXC_CCM_CCGRx_CG11_OFFSET,
+ .disable = _clk_disable,
+};
+
+static int _clk_display_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CLKSEQ_BYPASS);
+ mux = _get_mux(parent, &osc_clk, &pfd2_clk, &pll1_sw_clk, NULL);
+ reg = (reg & ~MXC_CCM_CLKSEQ_BYPASS_BYPASS_DISPLAY_AXI_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CLKSEQ_BYPASS_BYPASS_DISPLAY_AXI_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CLKSEQ_BYPASS);
+
+ return 0;
+}
+
+static unsigned long _clk_display_axi_get_rate(struct clk *clk)
+{
+ u32 div;
+
+ div = __raw_readl(MXC_CCM_DISPLAY_AXI);
+ div &= MXC_CCM_DISPLAY_AXI_DIV_MASK;
+ if (div == 0) { /* gated off */
+ return clk_get_rate(clk->parent);
+ } else {
+ return clk_get_rate(clk->parent) / div;
+ }
+}
+
+static unsigned long _clk_display_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 max_div = (2 << 6) - 1;
+ return _clk_round_rate_div(clk, rate, max_div, NULL);
+}
+
+static int _clk_display_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 new_div, max_div;
+ u32 reg;
+
+ max_div = (2 << 6) - 1;
+ _clk_round_rate_div(clk, rate, max_div, &new_div);
+
+ reg = __raw_readl(MXC_CCM_DISPLAY_AXI);
+ reg &= ~MXC_CCM_DISPLAY_AXI_DIV_MASK;
+ reg |= new_div << MXC_CCM_DISPLAY_AXI_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_DISPLAY_AXI);
+
+ while (__raw_readl(MXC_CCM_CSR2) & MXC_CCM_CSR2_DISPLAY_AXI_BUSY)
+ ;
+ return 0;
+}
+
+static struct clk display_axi_clk = {
+ .parent = &osc_clk,
+ .secondary = &apbh_dma_clk,
+ .set_parent = _clk_display_axi_set_parent,
+ .get_rate = _clk_display_axi_get_rate,
+ .set_rate = _clk_display_axi_set_rate,
+ .round_rate = _clk_display_axi_round_rate,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_DISPLAY_AXI,
+ .enable_shift = MXC_CCM_DISPLAY_AXI_CLKGATE_OFFSET,
+ .flags = RATE_PROPAGATES | AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_pxp_axi_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+
+ /* Set the auto-slow bits */
+ reg = __raw_readl(MXC_CCM_DISPLAY_AXI);
+ reg |= (MXC_CCM_DISPLAY_AXI_PXP_ASM_EN);
+ reg |= (5 << MXC_CCM_DISPLAY_AXI_PXP_ASM_DIV_OFFSET);
+ __raw_writel(reg, MXC_CCM_DISPLAY_AXI);
+
+ return 0;
+}
+
+static void _clk_pxp_axi_disable(struct clk *clk)
+{
+ u32 reg;
+
+ /* clear the auto-slow bits */
+ reg = __raw_readl(MXC_CCM_DISPLAY_AXI);
+ reg &= ~MXC_CCM_DISPLAY_AXI_PXP_ASM_EN;
+ __raw_writel(reg, MXC_CCM_DISPLAY_AXI);
+
+ _clk_disable(clk);
+}
+
+
+/* TODO: check Auto-Slow Mode */
+static struct clk pxp_axi_clk = {
+ .parent = &display_axi_clk,
+ .enable = _clk_pxp_axi_enable,
+ .disable = _clk_pxp_axi_disable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET,
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static struct clk elcdif_axi_clk = {
+ .parent = &display_axi_clk,
+ .enable = _clk_enable,
+ .disable = _clk_disable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG10_OFFSET,
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_elcdif_pix_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CLKSEQ_BYPASS);
+ mux = _get_mux(parent, &osc_clk, &pfd6_clk, &pll1_sw_clk, &ckih_clk);
+ reg = (reg & ~MXC_CCM_CLKSEQ_BYPASS_BYPASS_ELCDIF_PIX_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CLKSEQ_BYPASS_BYPASS_ELCDIF_PIX_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CLKSEQ_BYPASS);
+
+ return 0;
+}
+
+static unsigned long _clk_elcdif_pix_get_rate(struct clk *clk)
+{
+ u32 reg, prediv, podf;
+
+ reg = __raw_readl(MXC_CCM_ELCDIFPIX);
+ prediv = ((reg & MXC_CCM_ELCDIFPIX_CLK_PRED_MASK) >>
+ MXC_CCM_ELCDIFPIX_CLK_PRED_OFFSET) + 1;
+ podf = ((reg & MXC_CCM_ELCDIFPIX_CLK_PODF_MASK) >>
+ MXC_CCM_ELCDIFPIX_CLK_PODF_OFFSET) + 1;
+
+ return clk_get_rate(clk->parent) / (prediv * podf);
+}
+
+static unsigned long _clk_elcdif_pix_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 max_div = (2 << 12) - 1;
+ return _clk_round_rate_div(clk, rate, max_div, NULL);
+}
+
+static int _clk_elcdif_pix_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 new_div, max_div;
+ u32 reg;
+
+ max_div = (2 << 12) - 1;
+ _clk_round_rate_div(clk, rate, max_div, &new_div);
+
+ reg = __raw_readl(MXC_CCM_ELCDIFPIX);
+ /* Pre-divider set to 1 - only use PODF for clk dividing */
+ reg &= ~MXC_CCM_ELCDIFPIX_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_ELCDIFPIX_CLK_PRED_OFFSET;
+ reg &= ~MXC_CCM_ELCDIFPIX_CLK_PODF_MASK;
+ reg |= new_div << MXC_CCM_ELCDIFPIX_CLK_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_ELCDIFPIX);
+
+ return 0;
+}
+
+static int _clk_elcdif_pix_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+ reg = __raw_readl(MXC_CCM_ELCDIFPIX);
+ reg |= 0x3 << MXC_CCM_ELCDIFPIX_CLKGATE_OFFSET;
+ __raw_writel(reg, MXC_CCM_ELCDIFPIX);
+ return 0;
+}
+
+static void _clk_elcdif_pix_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_ELCDIFPIX);
+ reg &= ~MXC_CCM_ELCDIFPIX_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_ELCDIFPIX);
+ _clk_disable(clk);
+}
+
+static struct clk elcdif_pix_clk = {
+ .parent = &osc_clk,
+ .secondary = &ddr_clk,
+ .enable = _clk_elcdif_pix_enable,
+ .disable = _clk_elcdif_pix_disable,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+ .set_parent = _clk_elcdif_pix_set_parent,
+ .get_rate = _clk_elcdif_pix_get_rate,
+ .round_rate = _clk_elcdif_pix_round_rate,
+ .set_rate = _clk_elcdif_pix_set_rate,
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static int _clk_epdc_axi_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CLKSEQ_BYPASS);
+ mux = _get_mux(parent, &osc_clk, &pfd3_clk, &pll1_sw_clk, NULL);
+ reg = (reg & ~MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_AXI_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_AXI_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CLKSEQ_BYPASS);
+
+ return 0;
+}
+
+static unsigned long _clk_epdc_axi_get_rate(struct clk *clk)
+{
+ u32 div;
+
+ div = __raw_readl(MXC_CCM_EPDC_AXI);
+ div &= MXC_CCM_EPDC_AXI_DIV_MASK;
+ if (div == 0) { /* gated off */
+ return clk_get_rate(clk->parent);
+ } else {
+ return clk_get_rate(clk->parent) / div;
+ }
+}
+
+static unsigned long _clk_epdc_axi_round_rate_div(struct clk *clk,
+ unsigned long rate,
+ u32 *new_div)
+{
+ u32 div, max_div;
+
+ max_div = (2 << 6) - 1;
+ div = DIV_ROUND_UP(clk_get_rate(clk->parent), rate);
+ if (div > max_div)
+ div = max_div;
+ else if (div == 0)
+ div++;
+ if (new_div != NULL)
+ *new_div = div;
+ return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_epdc_axi_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ return _clk_epdc_axi_round_rate_div(clk, rate, NULL);
+}
+
+static int _clk_epdc_axi_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 new_div;
+ u32 reg;
+
+ _clk_epdc_axi_round_rate_div(clk, rate, &new_div);
+
+ reg = __raw_readl(MXC_CCM_EPDC_AXI);
+ reg &= ~MXC_CCM_EPDC_AXI_DIV_MASK;
+ reg |= new_div << MXC_CCM_EPDC_AXI_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_EPDC_AXI);
+
+ while (__raw_readl(MXC_CCM_CSR2) & MXC_CCM_CSR2_EPDC_AXI_BUSY)
+ ;
+
+ return 0;
+}
+
+static int _clk_epdc_axi_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+
+ reg = __raw_readl(MXC_CCM_EPDC_AXI);
+ reg |= MXC_CCM_EPDC_AXI_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_EPDC_AXI);
+
+ /* Set the auto-slow bits */
+ reg = __raw_readl(MXC_CCM_EPDC_AXI);
+ reg |= (MXC_CCM_EPDC_AXI_ASM_EN);
+ reg |= (5 << MXC_CCM_EPDC_AXI_ASM_DIV_OFFSET);
+ __raw_writel(reg, MXC_CCM_EPDC_AXI);
+
+ return 0;
+}
+
+static void _clk_epdc_axi_disable(struct clk *clk)
+{
+ u32 reg;
+
+ /* clear the auto-slow bits */
+ reg = __raw_readl(MXC_CCM_EPDC_AXI);
+ reg &= ~MXC_CCM_EPDC_AXI_ASM_EN;
+ __raw_writel(reg, MXC_CCM_EPDC_AXI);
+
+ reg = __raw_readl(MXC_CCM_EPDC_AXI);
+ reg &= ~MXC_CCM_EPDC_AXI_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_EPDC_AXI);
+ _clk_disable(clk);
+}
+
+/* TODO: check Auto-Slow Mode */
+static struct clk epdc_axi_clk = {
+ .parent = &osc_clk,
+ .secondary = &apbh_dma_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+ .set_parent = _clk_epdc_axi_set_parent,
+ .get_rate = _clk_epdc_axi_get_rate,
+ .set_rate = _clk_epdc_axi_set_rate,
+ .round_rate = _clk_epdc_axi_round_rate,
+ .enable = _clk_epdc_axi_enable,
+ .disable = _clk_epdc_axi_disable,
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+
+static int _clk_epdc_pix_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 reg, mux;
+
+ reg = __raw_readl(MXC_CCM_CLKSEQ_BYPASS);
+ mux = _get_mux(parent, &osc_clk, &pfd5_clk, &pll1_sw_clk, &ckih_clk);
+ reg = (reg & ~MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_PIX_CLK_SEL_MASK) |
+ (mux << MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_PIX_CLK_SEL_OFFSET);
+ __raw_writel(reg, MXC_CCM_CLKSEQ_BYPASS);
+
+ return 0;
+}
+
+static unsigned long _clk_epdc_pix_get_rate(struct clk *clk)
+{
+ u32 div;
+
+ div = __raw_readl(MXC_CCM_EPDCPIX);
+ div &= MXC_CCM_EPDC_PIX_CLK_PODF_MASK;
+ if (div == 0) { /* gated off */
+ return clk_get_rate(clk->parent);
+ } else {
+ return clk_get_rate(clk->parent) / div;
+ }
+}
+
+static unsigned long _clk_epdc_pix_round_rate(struct clk *clk,
+ unsigned long rate)
+{
+ u32 max_div = (2 << 12) - 1;
+ return _clk_round_rate_div(clk, rate, max_div, NULL);
+}
+
+static int _clk_epdc_pix_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 new_div, max_div;
+ u32 reg;
+
+ max_div = (2 << 12) - 1;
+ _clk_round_rate_div(clk, rate, max_div, &new_div);
+
+ reg = __raw_readl(MXC_CCM_EPDCPIX);
+ /* Pre-divider set to 1 - only use PODF for clk dividing */
+ reg &= ~MXC_CCM_EPDC_PIX_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_EPDC_PIX_CLK_PRED_OFFSET;
+ reg &= ~MXC_CCM_EPDC_PIX_CLK_PODF_MASK;
+ reg |= new_div << MXC_CCM_EPDC_PIX_CLK_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_EPDCPIX);
+
+ while (__raw_readl(MXC_CCM_CSR2) & MXC_CCM_CSR2_EPDC_PIX_BUSY)
+ ;
+
+ return 0;
+}
+
+static int _clk_epdc_pix_enable(struct clk *clk)
+{
+ u32 reg;
+
+ _clk_enable(clk);
+ reg = __raw_readl(MXC_CCM_EPDCPIX);
+ reg |= MXC_CCM_EPDC_PIX_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_EPDCPIX);
+
+ return 0;
+}
+
+static void _clk_epdc_pix_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_EPDCPIX);
+ reg &= ~MXC_CCM_EPDC_PIX_CLKGATE_MASK;
+ __raw_writel(reg, MXC_CCM_EPDCPIX);
+ _clk_disable(clk);
+}
+
+/* TODO: check Auto-Slow Mode */
+static struct clk epdc_pix_clk = {
+ .parent = &osc_clk,
+ .secondary = &apbh_dma_clk,
+ .enable_reg = MXC_CCM_CCGR6,
+ .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+ .set_parent = _clk_epdc_pix_set_parent,
+ .get_rate = _clk_epdc_pix_get_rate,
+ .set_rate = _clk_epdc_pix_set_rate,
+ .round_rate = _clk_epdc_pix_round_rate,
+ .enable = _clk_epdc_pix_enable,
+ .disable = _clk_epdc_pix_disable,
+ .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+};
+
+static unsigned long cko1_get_rate(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= MX50_CCM_CCOSR_CKO1_DIV_MASK;
+ reg = reg >> MX50_CCM_CCOSR_CKO1_DIV_OFFSET;
+ return clk_get_rate(clk->parent) / (reg + 1);
+}
+
+static int cko1_enable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg |= MX50_CCM_CCOSR_CKO1_EN;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static void cko1_disable(struct clk *clk)
+{
+ u32 reg;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MX50_CCM_CCOSR_CKO1_EN;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+}
+
+static int cko1_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 reg, div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = (parent_rate/rate - 1) & 0x7;
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MX50_CCM_CCOSR_CKO1_DIV_MASK;
+ reg |= div << MX50_CCM_CCOSR_CKO1_DIV_OFFSET;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static unsigned long cko1_round_rate(struct clk *clk, unsigned long rate)
+{
+ u32 div;
+ u32 parent_rate = clk_get_rate(clk->parent);
+
+ div = parent_rate / rate;
+ div = div < 1 ? 1 : div;
+ div = div > 8 ? 8 : div;
+ return parent_rate / div;
+}
+
+static int cko1_set_parent(struct clk *clk, struct clk *parent)
+{
+ u32 sel, reg, fast;
+
+ if (parent == &cpu_clk) {
+ sel = 0;
+ fast = 1;
+ } else if (parent == &pll1_sw_clk) {
+ sel = 1;
+ fast = 1;
+ } else if (parent == &pll2_sw_clk) {
+ sel = 2;
+ fast = 1;
+ } else if (parent == &pll3_sw_clk) {
+ sel = 3;
+ fast = 1;
+ } else if (parent == &apll_clk) {
+ sel = 0;
+ fast = 0;
+ } else if (parent == &pfd0_clk) {
+ sel = 1;
+ fast = 0;
+ } else if (parent == &pfd1_clk) {
+ sel = 2;
+ fast = 0;
+ } else if (parent == &pfd2_clk) {
+ sel = 3;
+ fast = 0;
+ } else if (parent == &pfd3_clk) {
+ sel = 4;
+ fast = 0;
+ } else if (parent == &pfd4_clk) {
+ sel = 5;
+ fast = 0;
+ } else if (parent == &pfd5_clk) {
+ sel = 6;
+ fast = 0;
+ } else if (parent == &pfd6_clk) {
+ sel = 7;
+ fast = 0;
+ } else if (parent == &weim_clk[0]) {
+ sel = 10;
+ fast = 0;
+ } else if (parent == &ahb_clk) {
+ sel = 11;
+ fast = 0;
+ } else if (parent == &ipg_clk) {
+ sel = 12;
+ fast = 0;
+ } else if (parent == &ipg_perclk) {
+ sel = 13;
+ fast = 0;
+ } else if (parent == &pfd7_clk) {
+ sel = 15;
+ fast = 0;
+ } else
+ return -EINVAL;
+
+ reg = __raw_readl(MXC_CCM_CCOSR);
+ reg &= ~MX50_CCM_CCOSR_CKO1_SEL_MASK;
+ reg |= sel << MX50_CCM_CCOSR_CKO1_SEL_OFFSET;
+ if (fast)
+ reg &= ~MX50_CCM_CCOSR_CKO1_SLOW_SEL;
+ else
+ reg |= MX50_CCM_CCOSR_CKO1_SLOW_SEL;
+ __raw_writel(reg, MXC_CCM_CCOSR);
+ return 0;
+}
+
+static struct clk cko1_clk = {
+ .parent = &pll1_sw_clk,
+ .get_rate = cko1_get_rate,
+ .enable = cko1_enable,
+ .disable = cko1_disable,
+ .set_rate = cko1_set_rate,
+ .round_rate = cko1_round_rate,
+ .set_parent = cko1_set_parent,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+ { \
+ .dev_id = d, \
+ .con_id = n, \
+ .clk = &c, \
+ }
+
+static struct clk_lookup lookups[] = {
+ _REGISTER_CLOCK(NULL, "osc", osc_clk),
+ _REGISTER_CLOCK(NULL, "ckih", ckih_clk),
+ _REGISTER_CLOCK(NULL, "ckih2", ckih2_clk),
+ _REGISTER_CLOCK(NULL, "ckil", ckil_clk),
+ _REGISTER_CLOCK(NULL, "pll1_main_clk", pll1_main_clk),
+ _REGISTER_CLOCK(NULL, "pll1_sw_clk", pll1_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll2", pll2_sw_clk),
+ _REGISTER_CLOCK(NULL, "pll3", pll3_sw_clk),
+ _REGISTER_CLOCK(NULL, "apll", apll_clk),
+ _REGISTER_CLOCK(NULL, "pfd0", pfd0_clk),
+ _REGISTER_CLOCK(NULL, "pfd1", pfd1_clk),
+ _REGISTER_CLOCK(NULL, "pfd2", pfd2_clk),
+ _REGISTER_CLOCK(NULL, "pfd3", pfd3_clk),
+ _REGISTER_CLOCK(NULL, "pfd4", pfd4_clk),
+ _REGISTER_CLOCK(NULL, "pfd5", pfd5_clk),
+ _REGISTER_CLOCK(NULL, "pfd6", pfd6_clk),
+ _REGISTER_CLOCK(NULL, "pfd7", pfd7_clk),
+ _REGISTER_CLOCK(NULL, "gpc_dvfs_clk", gpc_dvfs_clk),
+ _REGISTER_CLOCK(NULL, "lp_apm", lp_apm_clk),
+ _REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk),
+ _REGISTER_CLOCK(NULL, "main_bus_clk", main_bus_clk),
+ _REGISTER_CLOCK(NULL, "axi_a_clk", axi_a_clk),
+ _REGISTER_CLOCK(NULL, "axi_b_clk", axi_b_clk),
+ _REGISTER_CLOCK(NULL, "ahb_clk", ahb_clk),
+ _REGISTER_CLOCK(NULL, "ahb_max_clk", ahb_max_clk),
+ _REGISTER_CLOCK("mxc_sdma", "sdma_ahb_clk", sdma_clk[0]),
+ _REGISTER_CLOCK("mxc_sdma", "sdma_ipg_clk", sdma_clk[1]),
+ _REGISTER_CLOCK("mxcintuart.0", NULL, uart1_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.1", NULL, uart2_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.2", NULL, uart3_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.3", NULL, uart4_clk[0]),
+ _REGISTER_CLOCK("mxcintuart.4", NULL, uart5_clk[0]),
+ _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk[0]),
+ _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk[1]),
+ _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2]),
+ _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk[0]),
+ _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk[0]),
+ _REGISTER_CLOCK("mxc_spi.0", NULL, cspi1_clk[0]),
+ _REGISTER_CLOCK("mxc_spi.1", NULL, cspi2_clk[0]),
+ _REGISTER_CLOCK("mxc_spi.2", NULL, cspi3_clk),
+ _REGISTER_CLOCK(NULL, "ssi_lp_apm_clk", ssi_lp_apm_clk),
+ _REGISTER_CLOCK("mxc_ssi.0", NULL, ssi1_clk[0]),
+ _REGISTER_CLOCK("mxc_ssi.1", NULL, ssi2_clk[0]),
+ _REGISTER_CLOCK(NULL, "ssi_ext1_clk", ssi_ext1_clk),
+ _REGISTER_CLOCK(NULL, "ssi_ext2_clk", ssi_ext2_clk),
+ _REGISTER_CLOCK(NULL, "usb_ahb_clk", usb_ahb_clk),
+ _REGISTER_CLOCK(NULL, "usb_phy1_clk", usb_phy_clk[0]),
+ _REGISTER_CLOCK(NULL, "usb_phy2_clk", usb_phy_clk[1]),
+ _REGISTER_CLOCK(NULL, "usb_clk", usb_clk),
+ _REGISTER_CLOCK("mxsdhci.0", NULL, esdhc1_clk[0]),
+ _REGISTER_CLOCK("mxsdhci.1", NULL, esdhc2_clk[0]),
+ _REGISTER_CLOCK("mxsdhci.2", NULL, esdhc3_clk[0]),
+ _REGISTER_CLOCK("mxsdhci.3", NULL, esdhc4_clk[0]),
+ _REGISTER_CLOCK(NULL, "ddr_clk", ddr_clk),
+ _REGISTER_CLOCK("mxc_rtc.0", NULL, rtc_clk),
+ _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk),
+ _REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_clk),
+ _REGISTER_CLOCK(NULL, "cko1", cko1_clk),
+ _REGISTER_CLOCK(NULL, "gpt", gpt_clk[0]),
+ _REGISTER_CLOCK("fec.0", NULL, fec_clk[0]),
+ _REGISTER_CLOCK(NULL, "fec_sec1_clk", fec_clk[1]),
+ _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk),
+ _REGISTER_CLOCK(NULL, "gpmi-nfc", gpmi_nfc_clk[0]),
+ _REGISTER_CLOCK(NULL, "gpmi-apb", gpmi_nfc_clk[1]),
+ _REGISTER_CLOCK(NULL, "bch", gpmi_nfc_clk[2]),
+ _REGISTER_CLOCK(NULL, "bch-apb", gpmi_nfc_clk[3]),
+ _REGISTER_CLOCK(NULL, "rng_clk", rng_clk),
+ _REGISTER_CLOCK(NULL, "dcp_clk", dcp_clk),
+ _REGISTER_CLOCK(NULL, "ocotp_ctrl_apb", ocotp_clk),
+ _REGISTER_CLOCK(NULL, "ocram_clk", ocram_clk),
+ _REGISTER_CLOCK(NULL, "apbh_dma_clk", apbh_dma_clk),
+ _REGISTER_CLOCK(NULL, "sys_clk", sys_clk),
+ _REGISTER_CLOCK(NULL, "elcdif_pix", elcdif_pix_clk),
+ _REGISTER_CLOCK(NULL, "display_axi", display_axi_clk),
+ _REGISTER_CLOCK(NULL, "elcdif_axi", elcdif_axi_clk),
+ _REGISTER_CLOCK(NULL, "pxp_axi", pxp_axi_clk),
+ _REGISTER_CLOCK(NULL, "epdc_axi", epdc_axi_clk),
+ _REGISTER_CLOCK(NULL, "epdc_pix", epdc_pix_clk),
+};
+
+static struct mxc_clk mxc_clks[ARRAY_SIZE(lookups)];
+
+static void clk_tree_init(void)
+{
+ u32 reg;
+
+ ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+
+ /*
+ *Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+ * 8MHz, its derived from lp_apm.
+ */
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+ reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+ reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ /* set pll1_main_clk parent */
+ pll1_main_clk.parent = &osc_clk;
+
+ /* set pll2_sw_clk parent */
+ pll2_sw_clk.parent = &osc_clk;
+
+ /* set pll3_clk parent */
+ pll3_sw_clk.parent = &osc_clk;
+
+ /* set weim_clk parent */
+ weim_clk[0].parent = &main_bus_clk;
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ if ((reg & MX50_CCM_CBCDR_WEIM_CLK_SEL) != 0)
+ weim_clk[0].parent = &ahb_clk;
+
+ /* set ipg_perclk parent */
+ ipg_perclk.parent = &lp_apm_clk;
+ reg = __raw_readl(MXC_CCM_CBCMR);
+ if ((reg & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) != 0) {
+ ipg_perclk.parent = &ipg_clk;
+ } else {
+ if ((reg & MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL) == 0)
+ ipg_perclk.parent = &main_bus_clk;
+ }
+}
+
+int __init mx50_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1)
+{
+ __iomem void *base;
+ int i = 0, j = 0, reg;
+ int wp_cnt = 0;
+ u32 pll1_rate;
+
+ pll1_base = ioremap(MX53_BASE_ADDR(PLL1_BASE_ADDR), SZ_4K);
+ pll2_base = ioremap(MX53_BASE_ADDR(PLL2_BASE_ADDR), SZ_4K);
+ pll3_base = ioremap(MX53_BASE_ADDR(PLL3_BASE_ADDR), SZ_4K);
+ apll_base = ioremap(ANATOP_BASE_ADDR, SZ_4K);
+
+ /* Turn off all possible clocks */
+ if (mxc_jtag_enabled) {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG2_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG3_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG4_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG14_OFFSET, MXC_CCM_CCGR0);
+ } else {
+ __raw_writel(1 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG3_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG12_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG13_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG14_OFFSET, MXC_CCM_CCGR0);
+ }
+
+ __raw_writel(0, MXC_CCM_CCGR1);
+ __raw_writel(0, MXC_CCM_CCGR2);
+ __raw_writel(0, MXC_CCM_CCGR3);
+ __raw_writel(0, MXC_CCM_CCGR4);
+
+ __raw_writel(3 << MXC_CCM_CCGRx_CG6_OFFSET |
+ 1 << MXC_CCM_CCGRx_CG8_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET, MXC_CCM_CCGR5);
+
+ __raw_writel(3 << MXC_CCM_CCGRx_CG0_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG1_OFFSET |
+ 2 << MXC_CCM_CCGRx_CG14_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG15_OFFSET, MXC_CCM_CCGR6);
+
+ __raw_writel(0, MXC_CCM_CCGR7);
+
+ external_low_reference = ckil;
+ external_high_reference = ckih1;
+ oscillator_reference = osc;
+
+ usb_phy_clk[0].enable_reg = MXC_CCM_CCGR4;
+ usb_phy_clk[0].enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+ clk_tree_init();
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+ clkdev_add(&lookups[i]);
+ mxc_clks[i].reg_clk = lookups[i].clk;
+ if (lookups[i].con_id != NULL)
+ strcpy(mxc_clks[i].name, lookups[i].con_id);
+ else
+ strcpy(mxc_clks[i].name, lookups[i].dev_id);
+ clk_register(&mxc_clks[i]);
+ }
+
+ /* set DDR clock parent */
+ reg = __raw_readl(MXC_CCM_CLK_DDR) &
+ MXC_CCM_CLK_DDR_DDR_PFD_SEL;
+ if (reg)
+ clk_set_parent(&ddr_clk, &pfd0_clk);
+ else
+ clk_set_parent(&ddr_clk, &pll1_sw_clk);
+
+ clk_set_parent(&esdhc1_clk[0], &pll2_sw_clk);
+ clk_set_parent(&esdhc1_clk[2], &tmax2_clk);
+ clk_set_parent(&esdhc2_clk[0], &esdhc1_clk[0]);
+ clk_set_parent(&esdhc3_clk[0], &pll2_sw_clk);
+
+ clk_enable(&cpu_clk);
+
+ clk_enable(&main_bus_clk);
+
+ clk_enable(&ocotp_clk);
+
+ databahn = ioremap(MX50_DATABAHN_BASE_ADDR, SZ_16K);
+
+ /* Initialise the parents to be axi_b, parents are set to
+ * axi_a when the clocks are enabled.
+ */
+
+ clk_set_parent(&gpu2d_clk, &axi_a_clk);
+
+ /* move cspi to 24MHz */
+ clk_set_parent(&cspi_main_clk, &lp_apm_clk);
+ clk_set_rate(&cspi_main_clk, 12000000);
+
+ /*
+ * Set DISPLAY_AXI to 200Mhz
+ * For Display AXI, source clocks must be
+ * enabled before dividers can be changed
+ */
+ clk_enable(&display_axi_clk);
+ clk_enable(&elcdif_axi_clk);
+ clk_enable(&pxp_axi_clk);
+ clk_set_parent(&display_axi_clk, &pfd2_clk);
+ clk_set_rate(&display_axi_clk, 200000000);
+ clk_disable(&display_axi_clk);
+ clk_disable(&pxp_axi_clk);
+ clk_disable(&elcdif_axi_clk);
+
+ clk_enable(&elcdif_pix_clk);
+ clk_set_parent(&elcdif_pix_clk, &pll1_sw_clk);
+ clk_disable(&elcdif_pix_clk);
+
+ /*
+ * Enable and set EPDC AXI to 200MHz
+ * For EPDC AXI, source clocks must be
+ * enabled before dividers can be changed
+ */
+ clk_enable(&epdc_axi_clk);
+ clk_set_parent(&epdc_axi_clk, &pfd3_clk);
+ clk_set_rate(&epdc_axi_clk, 200000000);
+ clk_disable(&epdc_axi_clk);
+
+ clk_set_parent(&epdc_pix_clk, &pfd5_clk);
+
+ /* Move SSI clocks to SSI_LP_APM clock */
+ clk_set_parent(&ssi_lp_apm_clk, &lp_apm_clk);
+
+ clk_set_parent(&ssi1_clk[0], &ssi_lp_apm_clk);
+ /* set the SSI dividers to divide by 2 */
+ reg = __raw_readl(MXC_CCM_CS1CDR);
+ reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS1CDR);
+
+ clk_set_parent(&ssi2_clk[0], &ssi_lp_apm_clk);
+ reg = __raw_readl(MXC_CCM_CS2CDR);
+ reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK;
+ reg &= ~MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK;
+ reg |= 1 << MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET;
+ __raw_writel(reg, MXC_CCM_CS2CDR);
+
+ /* Change the SSI_EXT1_CLK to be sourced from SSI1_CLK_ROOT */
+ clk_set_parent(&ssi_ext1_clk, &ssi1_clk[0]);
+ clk_set_parent(&ssi_ext2_clk, &ssi2_clk[0]);
+
+ /* move usb_phy_clk to 24MHz */
+ clk_set_parent(&usb_phy_clk[0], &osc_clk);
+ clk_set_parent(&usb_phy_clk[1], &osc_clk);
+
+ /* move gpmi-nfc to 24MHz */
+ clk_set_parent(&gpmi_nfc_clk[0], &osc_clk);
+
+ /* set SDHC root clock as 200MHZ*/
+ clk_set_rate(&esdhc1_clk[0], 200000000);
+ clk_set_rate(&esdhc3_clk[0], 200000000);
+
+ /* Set the current working point. */
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ /* Update the cpu working point table based on the PLL1 freq
+ * at boot time
+ */
+ pll1_rate = clk_get_rate(&pll1_main_clk);
+ if (pll1_rate <= cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate)
+ wp_cnt = 1;
+ else if (pll1_rate <= cpu_wp_tbl[1].cpu_rate &&
+ pll1_rate > cpu_wp_tbl[2].cpu_rate)
+ wp_cnt = cpu_wp_nr - 1;
+ else
+ wp_cnt = cpu_wp_nr;
+
+ cpu_wp_tbl[0].cpu_rate = pll1_rate;
+
+ if (wp_cnt == 1) {
+ cpu_wp_tbl[0] = cpu_wp_tbl[cpu_wp_nr - 1];
+ memset(&cpu_wp_tbl[cpu_wp_nr - 1], 0, sizeof(struct cpu_wp));
+ memset(&cpu_wp_tbl[cpu_wp_nr - 2], 0, sizeof(struct cpu_wp));
+ } else if (wp_cnt < cpu_wp_nr) {
+ for (i = 0; i < wp_cnt; i++)
+ cpu_wp_tbl[i] = cpu_wp_tbl[i+1];
+ memset(&cpu_wp_tbl[i], 0, sizeof(struct cpu_wp));
+ }
+
+ if (wp_cnt < cpu_wp_nr) {
+ set_num_cpu_wp(wp_cnt);
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+ }
+
+ pll1_rate = clk_get_rate(&pll1_main_clk);
+ for (j = 0; j < cpu_wp_nr; j++) {
+ /* Change the CPU podf divider based on the boot up
+ * pll1 rate.
+ */
+ cpu_wp_tbl[j].cpu_podf = max(
+ (int)((pll1_rate / cpu_wp_tbl[j].cpu_rate)
+ - 1), 0);
+ if (pll1_rate/(cpu_wp_tbl[j].cpu_podf + 1) >
+ cpu_wp_tbl[j].cpu_rate) {
+ cpu_wp_tbl[j].cpu_podf++;
+ cpu_wp_tbl[j].cpu_rate =
+ pll1_rate/
+ (1000 * (cpu_wp_tbl[j].cpu_podf + 1));
+ cpu_wp_tbl[j].cpu_rate *= 1000;
+ }
+ if (pll1_rate/(cpu_wp_tbl[j].cpu_podf + 1) <
+ cpu_wp_tbl[j].cpu_rate) {
+ cpu_wp_tbl[j].cpu_rate = pll1_rate;
+ }
+ cpu_wp_tbl[j].pll_rate = pll1_rate;
+ }
+ /* Set the current working point. */
+ for (i = 0; i < cpu_wp_nr; i++) {
+ if (clk_get_rate(&cpu_clk) == cpu_wp_tbl[i].cpu_rate) {
+ cpu_curr_wp = i;
+ break;
+ }
+ }
+ if (i > cpu_wp_nr)
+ BUG();
+
+ clk_set_parent(&uart_main_clk, &lp_apm_clk);
+ clk_set_parent(&gpu2d_clk, &axi_b_clk);
+
+ clk_set_parent(&weim_clk[0], &ahb_clk);
+ clk_set_rate(&weim_clk[0], clk_round_rate(&weim_clk[0], 130000000));
+
+ /* Do the following just to disable the PLL since its not used */
+ clk_enable(&pll3_sw_clk);
+ clk_disable(&pll3_sw_clk);
+
+ base = ioremap(MX53_BASE_ADDR(GPT1_BASE_ADDR), SZ_4K);
+ mxc_timer_init(&gpt_clk[0], base, MXC_INT_GPT);
+ return 0;
+}
+
+/*!
+ * Setup cpu clock based on working point.
+ * @param wp cpu freq working point
+ * @return 0 on success or error code on failure.
+ */
+static int cpu_clk_set_wp(int wp)
+{
+ struct cpu_wp *p;
+ u32 reg;
+
+ if (wp == cpu_curr_wp)
+ return 0;
+
+ p = &cpu_wp_tbl[wp];
+
+ /*
+ * leave the PLL1 freq unchanged.
+ */
+ reg = __raw_readl(MXC_CCM_CACRR);
+ reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
+ reg |= cpu_wp_tbl[wp].cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
+ __raw_writel(reg, MXC_CCM_CACRR);
+ cpu_curr_wp = wp;
+
+#if defined(CONFIG_CPU_FREQ)
+ cpufreq_trig_needed = 1;
+#endif
+ return 0;
+}
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index 2d37785e3857..abb33781c4c1 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
@@ -11,12 +11,37 @@
* This file contains the CPU initialization code.
*/
+#include <linux/proc_fs.h>
#include <linux/types.h>
+#include <linux/err.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/iram_alloc.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <mach/common.h>
#include <mach/hardware.h>
-#include <asm/io.h>
+#include <asm/mach/map.h>
+
+#define CORTEXA8_PLAT_AMC 0x18
+#define SRPG_NEON_PUPSCR 0x284
+#define SRPG_NEON_PDNSCR 0x288
+#define SRPG_ARM_PUPSCR 0x2A4
+#define SRPG_ARM_PDNSCR 0x2A8
+#define SRPG_EMPGC0_PUPSCR 0x2E4
+#define SRPG_EMPGC0_PDNSCR 0x2E8
+#define SRPG_EMPGC1_PUPSCR 0x304
+#define SRPG_EMPGC1_PDNSCR 0x308
+
+void __iomem *arm_plat_base;
+void __iomem *gpc_base;
+void __iomem *ccm_base;
+void __iomem *databahn_base;
+void *wait_in_iram_base;
+void (*wait_in_iram)(void *ccm_addr, void *databahn_addr);
+
+extern void mx50_wait(u32 ccm_base, u32 databahn_addr);
static int cpu_silicon_rev = -1;
@@ -24,7 +49,7 @@ static int cpu_silicon_rev = -1;
static void query_silicon_parameter(void)
{
- void __iomem *rom = ioremap(MX51_IROM_BASE_ADDR, MX51_IROM_SIZE);
+ void __iomem *rom = ioremap(IROM_BASE_ADDR, IROM_SIZE);
u32 rev;
if (!rom) {
@@ -35,16 +60,16 @@ static void query_silicon_parameter(void)
rev = readl(rom + SI_REV);
switch (rev) {
case 0x1:
- cpu_silicon_rev = MX51_CHIP_REV_1_0;
+ cpu_silicon_rev = CHIP_REV_1_0;
break;
case 0x2:
- cpu_silicon_rev = MX51_CHIP_REV_1_1;
+ cpu_silicon_rev = CHIP_REV_1_1;
break;
case 0x10:
- cpu_silicon_rev = MX51_CHIP_REV_2_0;
+ cpu_silicon_rev = CHIP_REV_2_0;
break;
case 0x20:
- cpu_silicon_rev = MX51_CHIP_REV_3_0;
+ cpu_silicon_rev = CHIP_REV_3_0;
break;
default:
cpu_silicon_rev = 0;
@@ -70,30 +95,186 @@ int mx51_revision(void)
}
EXPORT_SYMBOL(mx51_revision);
+struct cpu_wp *(*get_cpu_wp)(int *wp);
+void (*set_num_cpu_wp)(int num);
+
+static void __init mipi_hsc_disable(void)
+{
+ void __iomem *reg_hsc_mcd = ioremap(MIPI_HSC_BASE_ADDR, SZ_4K);
+ void __iomem *reg_hsc_mxt_conf = reg_hsc_mcd + 0x800;
+ struct clk *clk;
+ uint32_t temp;
+
+ /* Temporarily setup MIPI module to legacy mode */
+ clk = clk_get(NULL, "mipi_hsp_clk");
+ if (!IS_ERR(clk)) {
+ clk_enable(clk);
+
+ /* Temporarily setup MIPI module to legacy mode */
+ __raw_writel(0xF00, reg_hsc_mcd);
+
+ /* CSI mode reserved*/
+ temp = __raw_readl(reg_hsc_mxt_conf);
+ __raw_writel(temp | 0x0FF, reg_hsc_mxt_conf);
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0) {
+ temp = __raw_readl(reg_hsc_mxt_conf);
+ __raw_writel(temp | 0x10000, reg_hsc_mxt_conf);
+ }
+
+ clk_disable(clk);
+ clk_put(clk);
+ }
+ iounmap(reg_hsc_mcd);
+}
+
+/*!
+ * This function resets IPU
+ */
+void mx5_ipu_reset(void)
+{
+ u32 *reg;
+ u32 value;
+ reg = ioremap(MX53_BASE_ADDR(SRC_BASE_ADDR), PAGE_SIZE);
+ value = __raw_readl(reg);
+ value = value | 0x8;
+ __raw_writel(value, reg);
+ iounmap(reg);
+}
+
+void mx5_vpu_reset(void)
+{
+ u32 reg;
+ void __iomem *src_base;
+
+ src_base = ioremap(MX53_BASE_ADDR(SRC_BASE_ADDR), PAGE_SIZE);
+
+ /* mask interrupt due to vpu passed reset */
+ reg = __raw_readl(src_base + 0x18);
+ reg |= 0x02;
+ __raw_writel(reg, src_base + 0x18);
+
+ reg = __raw_readl(src_base);
+ reg |= 0x5; /* warm reset vpu */
+ __raw_writel(reg, src_base);
+ while (__raw_readl(src_base) & 0x04)
+ ;
+
+ iounmap(src_base);
+}
+
static int __init post_cpu_init(void)
{
- unsigned int reg;
void __iomem *base;
+ unsigned int reg;
+ struct clk *gpcclk = clk_get(NULL, "gpc_dvfs_clk");
+ int iram_size = IRAM_SIZE;
- if (!cpu_is_mx51())
+ if (!cpu_is_mx5())
return 0;
- base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
+ if (cpu_is_mx51()) {
+ mipi_hsc_disable();
+
+#if defined(CONFIG_MXC_SECURITY_SCC) || defined(CONFIG_MXC_SECURITY_SCC_MODULE)
+ iram_size -= SCC_RAM_SIZE;
+#endif
+ iram_init(MX51_IRAM_BASE_ADDR, iram_size);
+ } else {
+ iram_init(MX53_IRAM_BASE_ADDR, iram_size);
+ }
+
+ gpc_base = ioremap(MX53_BASE_ADDR(GPC_BASE_ADDR), SZ_4K);
+ ccm_base = ioremap(MX53_BASE_ADDR(CCM_BASE_ADDR), SZ_4K);
+
+ clk_enable(gpcclk);
+
+ /* Setup the number of clock cycles to wait for SRPG
+ * power up and power down requests.
+ */
+ __raw_writel(0x010F0201, gpc_base + SRPG_ARM_PUPSCR);
+ __raw_writel(0x010F0201, gpc_base + SRPG_NEON_PUPSCR);
+ __raw_writel(0x00000008, gpc_base + SRPG_EMPGC0_PUPSCR);
+ __raw_writel(0x00000008, gpc_base + SRPG_EMPGC1_PUPSCR);
+
+ __raw_writel(0x01010101, gpc_base + SRPG_ARM_PDNSCR);
+ __raw_writel(0x01010101, gpc_base + SRPG_NEON_PDNSCR);
+ __raw_writel(0x00000018, gpc_base + SRPG_EMPGC0_PDNSCR);
+ __raw_writel(0x00000018, gpc_base + SRPG_EMPGC1_PDNSCR);
+
+ clk_disable(gpcclk);
+ clk_put(gpcclk);
+
+ /* Set ALP bits to 000. Set ALP_EN bit in Arm Memory Controller reg. */
+ arm_plat_base = ioremap(MX53_BASE_ADDR(ARM_BASE_ADDR), SZ_4K);
+ reg = 0x8;
+ __raw_writel(reg, arm_plat_base + CORTEXA8_PLAT_AMC);
+
+ base = ioremap(MX53_BASE_ADDR(AIPS1_BASE_ADDR), SZ_4K);
__raw_writel(0x0, base + 0x40);
__raw_writel(0x0, base + 0x44);
__raw_writel(0x0, base + 0x48);
__raw_writel(0x0, base + 0x4C);
reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
__raw_writel(reg, base + 0x50);
+ iounmap(base);
- base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
+ base = ioremap(MX53_BASE_ADDR(AIPS2_BASE_ADDR), SZ_4K);
__raw_writel(0x0, base + 0x40);
__raw_writel(0x0, base + 0x44);
__raw_writel(0x0, base + 0x48);
__raw_writel(0x0, base + 0x4C);
reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
__raw_writel(reg, base + 0x50);
+ iounmap(base);
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ /*Allow for automatic gating of the EMI internal clock.
+ * If this is done, emi_intr CCGR bits should be set to 11.
+ */
+ base = ioremap(MX53_BASE_ADDR(M4IF_BASE_ADDR), SZ_4K);
+ reg = __raw_readl(base + 0x8c);
+ reg &= ~0x1;
+ __raw_writel(reg, base + 0x8c);
+ iounmap(base);
+ }
+
+ databahn_base = ioremap(MX50_DATABAHN_BASE_ADDR, SZ_16K);
+
+ if (cpu_is_mx50()) {
+ struct clk *ddr_clk = clk_get(NULL, "ddr_clk");
+ unsigned long iram_paddr;
+ iram_alloc(SZ_4K, &iram_paddr);
+ /* Need to remap the area here since we want the memory region
+ to be executable. */
+ wait_in_iram_base = __arm_ioremap(iram_paddr,
+ SZ_4K, MT_HIGH_VECTORS);
+ memcpy(wait_in_iram_base, mx50_wait, SZ_4K);
+ wait_in_iram = (void *)wait_in_iram_base;
+
+ clk_enable(ddr_clk);
+
+ /* Set the DDR to enter automatic self-refresh. */
+ /* Set the DDR to automatically enter lower power mode 4. */
+ reg = __raw_readl(databahn_base + DATABAHN_CTL_REG22);
+ reg &= ~LOWPOWER_AUTOENABLE_MASK;
+ reg |= 1 << 1;
+ __raw_writel(reg, databahn_base + DATABAHN_CTL_REG22);
+
+ /* set the counter for entering mode 4. */
+ reg = __raw_readl(databahn_base + DATABAHN_CTL_REG21);
+ reg &= ~LOWPOWER_EXTERNAL_CNT_MASK;
+ reg = 128 << LOWPOWER_EXTERNAL_CNT_OFFSET;
+ __raw_writel(reg, databahn_base + DATABAHN_CTL_REG21);
+
+ /* Enable low power mode 4 */
+ reg = __raw_readl(databahn_base + DATABAHN_CTL_REG20);
+ reg &= ~LOWPOWER_CONTROL_MASK;
+ reg |= 1 << 1;
+ __raw_writel(reg, databahn_base + DATABAHN_CTL_REG20);
+ clk_disable(ddr_clk);
+ }
return 0;
}
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
index c776b9af0624..45db5f60d7b1 100644
--- a/arch/arm/mach-mx5/crm_regs.h
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
@@ -11,12 +11,7 @@
#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-#define MX51_CCM_BASE MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
-#define MX51_DPLL1_BASE MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
-#define MX51_DPLL2_BASE MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
-#define MX51_DPLL3_BASE MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
-#define MX51_CORTEXA8_BASE MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
-#define MX51_GPC_BASE MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
+#define MXC_CCM_BASE (IO_ADDRESS(CCM_BASE_ADDR))
/* PLL Register Offsets */
#define MXC_PLL_DP_CTL 0x00
@@ -73,41 +68,108 @@
#define MXC_PLL_DP_DESTAT_TOG_SEL (1 << 31)
#define MXC_PLL_DP_DESTAT_MFN 0x07FFFFFF
+/* Register addresses of apll and pfd*/
+#define MXC_ANADIG_FRAC0 0x10
+#define MXC_ANADIG_FRAC0_SET 0x14
+#define MXC_ANADIG_FRAC0_CLR 0x18
+#define MXC_ANADIG_FRAC1 0x20
+#define MXC_ANADIG_FRAC1_SET 0x24
+#define MXC_ANADIG_FRAC1_CLR 0x28
+#define MXC_ANADIG_MISC 0x60
+#define MXC_ANADIG_MISC_SET 0x64
+#define MXC_ANADIG_MISC_CLR 0x68
+#define MXC_ANADIG_PLLCTRL 0x70
+#define MXC_ANADIG_PLLCTRL_SET 0x74
+#define MXC_ANADIG_PLLCTRL_CLR 0x78
+
+/* apll and pfd Register Bit definitions */
+
+#define MXC_ANADIG_PFD3_CLKGATE (1 << 31)
+#define MXC_ANADIG_PFD3_STABLE (1 << 30)
+#define MXC_ANADIG_PFD3_FRAC_OFFSET 24
+#define MXC_ANADIG_PFD_FRAC_MASK 0x3F
+#define MXC_ANADIG_PFD2_CLKGATE (1 << 23)
+#define MXC_ANADIG_PFD2_STABLE (1 << 22)
+#define MXC_ANADIG_PFD2_FRAC_OFFSET 16
+#define MXC_ANADIG_PFD1_CLKGATE (1 << 15)
+#define MXC_ANADIG_PFD1_STABLE (1 << 14)
+#define MXC_ANADIG_PFD1_FRAC_OFFSET 8
+#define MXC_ANADIG_PFD0_CLKGATE (1 << 7)
+#define MXC_ANADIG_PFD0_STABLE (1 << 6)
+#define MXC_ANADIG_PFD0_FRAC_OFFSET 0
+
+#define MXC_ANADIG_PFD7_CLKGATE (1 << 31)
+#define MXC_ANADIG_PFD7_STABLE (1 << 30)
+#define MXC_ANADIG_PFD7_FRAC_OFFSET 24
+#define MXC_ANADIG_PFD6_CLKGATE (1 << 23)
+#define MXC_ANADIG_PFD6_STABLE (1 << 22)
+#define MXC_ANADIG_PFD6_FRAC_OFFSET 16
+#define MXC_ANADIG_PFD5_CLKGATE (1 << 15)
+#define MXC_ANADIG_PFD5_STABLE (1 << 14)
+#define MXC_ANADIG_PFD5_FRAC_OFFSET 8
+#define MXC_ANADIG_PFD4_CLKGATE (1 << 7)
+#define MXC_ANADIG_PFD4_STABLE (1 << 6)
+#define MXC_ANADIG_PFD4_FRAC_OFFSET 0
+
+#define MXC_ANADIG_APLL_LOCK (1 << 31)
+#define MXC_ANADIG_APLL_FORCE_LOCK (1 << 30)
+#define MXC_ANADIG_PFD_DIS_OFFSET 16
+#define MXC_ANADIG_PFD_DIS_MASK 0xff
+#define MXC_ANADIG_APLL_LOCK_CNT_OFFSET 0
+#define MXC_ANADIG_APLL_LOCK_CNT_MASK 0xffff
+
/* Register addresses of CCM*/
-#define MXC_CCM_CCR (MX51_CCM_BASE + 0x00)
-#define MXC_CCM_CCDR (MX51_CCM_BASE + 0x04)
-#define MXC_CCM_CSR (MX51_CCM_BASE + 0x08)
-#define MXC_CCM_CCSR (MX51_CCM_BASE + 0x0C)
-#define MXC_CCM_CACRR (MX51_CCM_BASE + 0x10)
-#define MXC_CCM_CBCDR (MX51_CCM_BASE + 0x14)
-#define MXC_CCM_CBCMR (MX51_CCM_BASE + 0x18)
-#define MXC_CCM_CSCMR1 (MX51_CCM_BASE + 0x1C)
-#define MXC_CCM_CSCMR2 (MX51_CCM_BASE + 0x20)
-#define MXC_CCM_CSCDR1 (MX51_CCM_BASE + 0x24)
-#define MXC_CCM_CS1CDR (MX51_CCM_BASE + 0x28)
-#define MXC_CCM_CS2CDR (MX51_CCM_BASE + 0x2C)
-#define MXC_CCM_CDCDR (MX51_CCM_BASE + 0x30)
-#define MXC_CCM_CHSCDR (MX51_CCM_BASE + 0x34)
-#define MXC_CCM_CSCDR2 (MX51_CCM_BASE + 0x38)
-#define MXC_CCM_CSCDR3 (MX51_CCM_BASE + 0x3C)
-#define MXC_CCM_CSCDR4 (MX51_CCM_BASE + 0x40)
-#define MXC_CCM_CWDR (MX51_CCM_BASE + 0x44)
-#define MXC_CCM_CDHIPR (MX51_CCM_BASE + 0x48)
-#define MXC_CCM_CDCR (MX51_CCM_BASE + 0x4C)
-#define MXC_CCM_CTOR (MX51_CCM_BASE + 0x50)
-#define MXC_CCM_CLPCR (MX51_CCM_BASE + 0x54)
-#define MXC_CCM_CISR (MX51_CCM_BASE + 0x58)
-#define MXC_CCM_CIMR (MX51_CCM_BASE + 0x5C)
-#define MXC_CCM_CCOSR (MX51_CCM_BASE + 0x60)
-#define MXC_CCM_CGPR (MX51_CCM_BASE + 0x64)
-#define MXC_CCM_CCGR0 (MX51_CCM_BASE + 0x68)
-#define MXC_CCM_CCGR1 (MX51_CCM_BASE + 0x6C)
-#define MXC_CCM_CCGR2 (MX51_CCM_BASE + 0x70)
-#define MXC_CCM_CCGR3 (MX51_CCM_BASE + 0x74)
-#define MXC_CCM_CCGR4 (MX51_CCM_BASE + 0x78)
-#define MXC_CCM_CCGR5 (MX51_CCM_BASE + 0x7C)
-#define MXC_CCM_CCGR6 (MX51_CCM_BASE + 0x80)
-#define MXC_CCM_CMEOR (MX51_CCM_BASE + 0x84)
+#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00)
+#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04)
+#define MXC_CCM_CSR (MXC_CCM_BASE + 0x08)
+#define MXC_CCM_CCSR (MXC_CCM_BASE + 0x0C)
+#define MXC_CCM_CACRR (MXC_CCM_BASE + 0x10)
+#define MXC_CCM_CBCDR (MXC_CCM_BASE + 0x14)
+#define MXC_CCM_CBCMR (MXC_CCM_BASE + 0x18)
+#define MXC_CCM_CSCMR1 (MXC_CCM_BASE + 0x1C)
+#define MXC_CCM_CSCMR2 (MXC_CCM_BASE + 0x20)
+#define MXC_CCM_CSCDR1 (MXC_CCM_BASE + 0x24)
+#define MXC_CCM_CS1CDR (MXC_CCM_BASE + 0x28)
+#define MXC_CCM_CS2CDR (MXC_CCM_BASE + 0x2C)
+#define MXC_CCM_CDCDR (MXC_CCM_BASE + 0x30)
+#define MXC_CCM_CHSCDR (MXC_CCM_BASE + 0x34)
+#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38)
+#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3C)
+#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40)
+#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44)
+#define MXC_CCM_CDHIPR (MXC_CCM_BASE + 0x48)
+#define MXC_CCM_CDCR (MXC_CCM_BASE + 0x4C)
+#define MXC_CCM_CTOR (MXC_CCM_BASE + 0x50)
+#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x54)
+#define MXC_CCM_CISR (MXC_CCM_BASE + 0x58)
+#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x5C)
+#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x60)
+#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x64)
+#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x68)
+#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x6C)
+#define MXC_CCM_CCGR2 (MXC_CCM_BASE + 0x70)
+#define MXC_CCM_CCGR3 (MXC_CCM_BASE + 0x74)
+#define MXC_CCM_CCGR4 (MXC_CCM_BASE + 0x78)
+#define MXC_CCM_CCGR5 (MXC_CCM_BASE + 0x7C)
+#define MXC_CCM_CCGR6 (MXC_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7 (MXC_CCM_BASE + 0x84)
+#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x88)
+#define MXC_CCM_CSR2 (MXC_CCM_BASE + 0x8C)
+#define MXC_CCM_CLKSEQ_BYPASS (MXC_CCM_BASE + 0x90)
+#define MXC_CCM_CLK_SYS (MXC_CCM_BASE + 0x94)
+#define MXC_CCM_CLK_DDR (MXC_CCM_BASE + 0x98)
+#define MXC_CCM_ELCDIFPIX (MXC_CCM_BASE + 0x9C)
+#define MXC_CCM_EPDCPIX (MXC_CCM_BASE + 0xA0)
+#define MXC_CCM_DISPLAY_AXI (MXC_CCM_BASE + 0xA4)
+#define MXC_CCM_EPDC_AXI (MXC_CCM_BASE + 0xA8)
+#define MXC_CCM_GPMI (MXC_CCM_BASE + 0xAC)
+#define MXC_CCM_BCH (MXC_CCM_BASE + 0xB0)
+#define MXC_CCM_MSHC_XMSCKI (MXC_CCM_BASE + 0xB4)
+
+/* CCM Register Offsets. */
+#define MXC_CCM_CDCR_OFFSET 0x4C
+#define MXC_CCM_CACRR_OFFSET 0x10
+#define MXC_CCM_CDHIPR_OFFSET 0x48
/* Define the bits in register CCR */
#define MXC_CCM_CCR_COSC_EN (1 << 12)
@@ -119,82 +181,103 @@
#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
/* Define the bits in register CCDR */
+/* MX51 */
#define MXC_CCM_CCDR_HSC_HS_MASK (0x1 << 18)
#define MXC_CCM_CCDR_IPU_HS_MASK (0x1 << 17)
#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16)
+/* MX53 */
+#define MXC_CCM_CCDR_IPU_HS_MX53_MASK (0x1 << 21)
+#define MXC_CCM_CCDR_EMI_HS_INT2_MASK (0x1 << 20)
+#define MXC_CCM_CCDR_EMI_HS_INT1_MASK (0x1 << 19)
+#define MXC_CCM_CCDR_EMI_HS_SLOW_MASK (0x1 << 18)
+#define MXC_CCM_CCDR_EMI_HS_FAST_MASK (0x1 << 17)
+#define MXC_CCM_CCDR_EMI_HS_MASK (0x1 << 16)
/* Define the bits in register CSR */
#define MXC_CCM_CSR_COSR_READY (1 << 5)
-#define MXC_CCM_CSR_LVS_VALUE (1 << 4)
+#define MXC_CCM_CSR_LVS_VALUE (1 << 4)
#define MXC_CCM_CSR_CAMP2_READY (1 << 3)
#define MXC_CCM_CSR_CAMP1_READY (1 << 2)
#define MXC_CCM_CSR_FPM_READY (1 << 1)
-#define MXC_CCM_CSR_REF_EN_B (1 << 0)
+#define MXC_CCM_CSR_TEMP_MON_ALARM (1 << 1)
+#define MXC_CCM_CSR_REF_EN_B (1 << 0)
/* Define the bits in register CCSR */
-#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 9)
-#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7)
-#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7)
+#define MXC_CCM_CCSR_PLL3_PFD_EN (0x1 << 13)
+#define MXC_CCM_CCSR_PLL2_PFD_EN (0x1 << 12)
+#define MXC_CCM_CCSR_PLL1_PFD_EN (0x1 << 11)
+#define MXC_CCM_CCSR_LP_APM_SEL (0x1 << 10)
+#define MXC_CCM_CCSR_LP_APM_SE_MX51L (0x1 << 9)
+#define MXC_CCM_CCSR_PLL4_SW_CLK_SEL (1 << 9)
+#define MXC_CCM_CCSR_STEP_SEL_OFFSET (7)
+#define MXC_CCM_CCSR_STEP_SEL_MASK (0x3 << 7)
#define MXC_CCM_CCSR_STEP_SEL_LP_APM 0
#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS 1 /* Only when JTAG connected? */
#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
#define MXC_CCM_CCSR_PLL2_PODF_OFFSET (5)
-#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5)
+#define MXC_CCM_CCSR_PLL2_PODF_MASK (0x3 << 5)
#define MXC_CCM_CCSR_PLL3_PODF_OFFSET (3)
-#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3)
+#define MXC_CCM_CCSR_PLL3_PODF_MASK (0x3 << 3)
#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2) /* 0: pll1_main_clk,
1: step_clk */
-#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1)
-#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0)
+#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1)
+#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0)
/* Define the bits in register CACRR */
#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0)
-#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7)
+#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7)
/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
+#define MX50_CCM_CBCDR_WEIM_CLK_SEL (0x1 << 27)
+#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26)
+#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
+#define MX50_CCM_CBCDR_PERIPH_CLK_SEL_OFFSET (25)
+#define MX50_CCM_CBCDR_PERIPH_CLK_SEL_MASK (0x3 << 25)
#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET (30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30)
+#define MXC_CCM_CBCDR_DDR_HF_SEL (0x1 << 30)
#define MXC_CCM_CBCDR_DDR_PODF_OFFSET (27)
#define MXC_CCM_CBCDR_DDR_PODF_MASK (0x7 << 27)
+#define MX50_CCM_CBCDR_WEIM_PODF_OFFSET (22)
+#define MX50_CCM_CBCDR_WEIM_PODF_MASK (0x7 << 22)
#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22)
+#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22)
#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19)
#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19)
#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16)
#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16)
#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13)
+#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13)
#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
+#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6)
+#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6)
#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3)
#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0)
+#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0)
#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7)
/* Define the bits in register CBCMR */
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16)
#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10)
#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10)
#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8)
#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4)
#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0)
+#define MXC_CCM_CBCMR_DBG_APB_CLK_SEL_OFFSET (2)
+#define MXC_CCM_CBCMR_DBG_APB_CLK_SEL_MASK (0x3 << 2)
+#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1)
+#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0)
/* Define the bits in register CSCMR1 */
#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30)
@@ -203,96 +286,128 @@
#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28)
#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26)
#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24)
#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC2_CLK_SEL_OFFSET (20)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC2_CLK_SEL_MASK (0x3 << 20)
+#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL_MX51 (0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC2_CLK_SEL (0x1 << 19)
#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10)
+#define MX50_CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET (21)
+#define MX50_CCM_CSCMR1_ESDHC1_CLK_SEL_MASK (0x3 << 21)
+#define MX50_CCM_CSCMR1_ESDHC2_CLK_SEL (0x1 << 20)
+#define MX50_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 19)
+#define MX50_CCM_CSCMR1_ESDHC3_CLK_SEL_OFFSET (16)
+#define MX50_CCM_CSCMR1_ESDHC3_CLK_SEL_MASK (0x7 << 16)
+#define MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_OFFSET (16)
+#define MXC_CCM_CSCMR1_ESDHC3_MSHC2_CLK_SEL_MASK (0x3 << 16)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11)
+#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10)
#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8)
#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7)
+#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7)
#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2)
+#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1)
+#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1)
/* Define the bits in register CSCMR2 */
#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n) (26+n*3)
#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n) (0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22)
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET (24)
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK (0x3 << 24)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET (22)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK (0x3 << 22)
+/* MX51 */
#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET (20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK (0x3 << 20)
#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET (18)
#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK (0x3 << 18)
#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET (16)
#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK (0x3 << 16)
#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET (14)
#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK (0x3 << 14)
+/* MX53 */
+#define MXC_CCM_CSCMR2_ASRC_CLK_SEL (1<<21)
+#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET (19)
+#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK (0x3 << 19)
+#define MXC_CCM_CSCMR2_ESAI_POST_SEL_OFFSET (16)
+#define MXC_CCM_CSCMR2_ESAI_POST_SEL_MASK (0x7 << 16)
+#define MXC_CCM_CSCMR2_IEEE_CLK_SEL_OFFSET (14)
+#define MXC_CCM_CSCMR2_IEEE_CLK_SEL_MASK (0x3 << 14)
#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET (12)
#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK (0x3 << 12)
+/* MX51 */
#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET (10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK (0x3 << 10)
#define MXC_CCM_CSCMR2_SLIMBUS_COM (0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET (6)
#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK (0x7 << 6)
+/* MX53 */
+#define MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV (0x1 << 11)
+#define MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV (0x1 << 10)
+#define MXC_CCM_CSCMR2_LDB_DI1_CLK_SEL (0x1 << 9)
+#define MXC_CCM_CSCMR2_LDB_DI0_CLK_SEL (0x1 << 8)
+#define MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET (6)
+#define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3 << 6)
#define MXC_CCM_CSCMR2_SPDIF1_COM (1 << 5)
#define MXC_CCM_CSCMR2_SPDIF0_COM (1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET (2)
#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK (0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET (0)
#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3)
/* Define the bits in register CSCDR1 */
#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CSCDR1_ESDHC3_MSHC2_CLK_PODF_MASK (0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_OFFSET (11)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC2_CLK_PODF_MASK (0x7 << 11)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3)
#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7)
/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET (25)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK (0x3F << 25)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET (16)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK (0x3F << 16)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET (9)
+#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK (0x7 << 9)
#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6)
#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0)
#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET (22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK (0x7 << 22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET (16)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK (0x3F << 16)
#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6)
#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0)
@@ -300,50 +415,74 @@
/* Define the bits in register CDCDR */
#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET (28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK (0x7 << 28)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16)
+/* MX51 */
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (16)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
+/* MX53 */
+#define MXC_CCM_CDCDR_DI_PLL4_PODF_OFFSET (16)
+#define MXC_CCM_CDCDR_DI_PLL4_PODF_MASK (0x7 << 16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CDCDR_DI1_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CDCDR_DI1_CLK_PRED_MASK (0x7 << 6)
#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET (3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK (0x7 << 3)
#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET (0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK (0x7)
/* Define the bits in register CHSCCDR */
+/* MX51 */
#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET (12)
#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK (0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET (6)
#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK (0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET (3)
#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK (0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET (0)
#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK (0x7)
+/* MX53 */
+#define MXC_CCM_CHSCCDR_ESAI_HCKT_SEL_OFFSET (6)
+#define MXC_CCM_CHSCCDR_ESAI_HCKT_SEL_MASK (0x3 << 6)
+#define MXC_CCM_CHSCCDR_ESAI_HCKR_SEL_OFFSET (4)
+#define MXC_CCM_CHSCCDR_ESAI_HCKR_SEL_MASK (0x3 << 4)
+#define MXC_CCM_CHSCCDR_SSI2_MLB_SPDIF_SRC_OFFSET (2)
+#define MXC_CCM_CHSCCDR_SSI2_MLB_SPDIF_SRC_MASK (0x3 << 2)
+#define MXC_CCM_CHSCCDR_SSI1_MLB_SPDIF_SRC_OFFSET (0)
+#define MXC_CCM_CHSCCDR_SSI1_MLB_SPDIF_SRC_MASK (0x3)
/* Define the bits in register CSCDR2 */
+#define MXC_CCM_CSCDR2_ASRC_CLK_PRED_OFFSET (28)
+#define MXC_CCM_CSCDR2_ASRC_CLK_PRED_MASK (0x7 << 28)
#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25)
#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25)
#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19)
#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19)
+/* MX51 */
#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16)
#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16)
#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9)
#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6)
#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6)
#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0)
#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F)
+/* MX53 */
+#define MXC_CCM_CSCDR2_ASRC_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CSCDR2_ASRC_CLK_PODF_MASK (0x3F << 9)
+#define MXC_CCM_CSCDR2_IEEE_CLK_PRED_OFFSET (6)
+#define MXC_CCM_CSCDR2_IEEE_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CSCDR2_IEEE_CLK_PODF_OFFSET (0)
+#define MXC_CCM_CSCDR2_IEEE_CLK_PODF_MASK (0x3F)
/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET (16)
#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK (0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET (9)
#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK (0x3F << 9)
#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET (6)
#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK (0x7 << 6)
@@ -352,13 +491,13 @@
/* Define the bits in register CSCDR4 */
#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET (16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK (0x7 << 16)
#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET (9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK (0x3F << 9)
#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET (6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK (0x7 << 6)
#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET (0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK (0x3F)
/* Define the bits in register CDHIPR */
#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
@@ -373,58 +512,92 @@
#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY (1 << 0)
/* Define the bits in register CDCR */
-#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0)
+#define MX50_CCM_CDCR_SW_PERIPH_CLK_DIV_REQ_STATUS (0x1 << 7)
+#define MX50_CCM_CDCR_SW_PERIPH_CLK_DIV_REQ (0x1 << 6)
+#define MX50_CCM_CDCR_SW_DVFS_EN (0x1 << 5)
+#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER (0x1 << 2)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET (0)
#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK (0x3)
/* Define the bits in register CLPCR */
+/* MX51 */
#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS (0x1 << 23)
-#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS (0x1 << 22)
-#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 21)
-#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 20)
+#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS_MX51 (0x1 << 22)
+#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS_MX51 (0x1 << 21)
+#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS_MX51 (0x1 << 20)
+/* MX53 */
+#define MXC_CCM_CLPCR_BYPASS_CAN2_LPM_HS (0x1 << 27)
+#define MXC_CCM_CLPCR_BYPASS_CAN1_LPM_HS (0x1 << 27)
+#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS_MX53 (0x1 << 26)
+#define MXC_CCM_CLPCR_BYPASS_MAX_LPM_HS (0x1 << 25)
+#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS (0x1 << 24)
+#define MXC_CCM_CLPCR_BYPASS_EMI_INT2_LPM_HS (0x1 << 23)
+#define MX50_CCM_CLPCR_BYPASS_RNGB_LPM_HS (0x1 << 23)
+#define MXC_CCM_CLPCR_BYPASS_EMI_INT1_LPM_HS (0x1 << 22)
+#define MXC_CCM_CLPCR_BYPASS_EMI_SLOW_LPM_HS (0x1 << 21)
+#define MXC_CCM_CLPCR_BYPASS_EMI_FAST_LPM_HS (0x1 << 20)
#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS (0x1 << 19)
#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS (0x1 << 18)
-#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17)
-#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16)
-#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11)
+#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS (0x1 << 17)
+#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS (0x1 << 16)
+#define MXC_CCM_CLPCR_COSC_PWRDOWN (0x1 << 11)
#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9)
#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
-#define MXC_CCM_CLPCR_VSTBY (0x1 << 8)
-#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7)
-#define MXC_CCM_CLPCR_SBYOS (0x1 << 6)
-#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
+#define MXC_CCM_CLPCR_VSTBY (0x1 << 8)
+#define MXC_CCM_CLPCR_DIS_REF_OSC (0x1 << 7)
+#define MXC_CCM_CLPCR_SBYOS (0x1 << 6)
+#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
-#define MXC_CCM_CLPCR_LPM_OFFSET (0)
+#define MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY (0x1 << 2)
+#define MXC_CCM_CLPCR_LPM_OFFSET (0)
#define MXC_CCM_CLPCR_LPM_MASK (0x3)
/* Define the bits in register CISR */
-#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 25)
-#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
+#define MXC_CCM_CISR_ARM_PODF_LOADED_MX51 (0x1 << 25)
+#define MXC_CCM_CISR_ARM_PODF_LOADED (0x1 << 26)
+#define MXC_CCM_CISR_TEMP_MON_ALARM (0x1 << 25)
+#define MXC_CCM_CISR_EMI_CLK_SEL_LOADED (0x1 << 23)
+#define MXC_CCM_CISR_PER_CLK_SEL_LOADED (0x1 << 22)
+#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
#define MXC_CCM_CISR_AHB_PODF_LOADED (0x1 << 20)
-#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19)
+#define MXC_CCM_CISR_EMI_PODF_LOADED (0x1 << 19)
#define MXC_CCM_CISR_AXI_B_PODF_LOADED (0x1 << 18)
#define MXC_CCM_CISR_AXI_A_PODF_LOADED (0x1 << 17)
-#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16)
+#define MXC_CCM_CISR_DIVIDER_LOADED (0x1 << 16)
#define MXC_CCM_CISR_COSC_READY (0x1 << 6)
-#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5)
+#define MXC_CCM_CISR_CKIH2_READY (0x1 << 5)
#define MXC_CCM_CISR_CKIH_READY (0x1 << 4)
+#define MX50_CCM_CISR_CAMP1_READY (0x1 << 4)
#define MXC_CCM_CISR_FPM_READY (0x1 << 3)
-#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2)
-#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1)
-#define MXC_CCM_CISR_LRF_PLL1 (0x1)
+#define MXC_CCM_CISR_LRF_PLL3 (0x1 << 2)
+#define MXC_CCM_CISR_LRF_PLL2 (0x1 << 1)
+#define MXC_CCM_CISR_LRF_PLL1 (0x1)
/* Define the bits in register CIMR */
-#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 25)
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED_MX51 (0x1 << 25)
+#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED_MX51 (0x1 << 20)
+#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED_MX51 (0x1 << 19)
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (0x1 << 26)
+#define MXC_CCM_CIMR_MASK_TEMP_MON_ALARM (0x1 << 25)
+#define MXC_CCM_CIMR_MASK_EMI_CLK_SEL_LOADED (0x1 << 23)
+#define MXC_CCM_CIMR_MASK_PER_CLK_SEL_LOADED (0x1 << 22)
#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED (0x1 << 21)
-#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED (0x1 << 20)
-#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED (0x1 << 19)
+#define MXC_CCM_CIMR_MASK_AHB_PODF_LOADED_MX53 (0x1 << 20)
+#define MXC_CCM_CIMR_MASK_EMI_SLOW_PODF_LOADED_MX53 (0x1 << 19)
+#define MX50_CCM_CIMR_MASK_WEIM_PODF_LOADED (0x1 << 19)
#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED (0x1 << 18)
#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED (0x1 << 17)
#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED (0x1 << 16)
-#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 5)
+/* MX51 */
+#define MXC_CCM_CIMR_MASK_COSC_READY_MX51 (0x1 << 5)
#define MXC_CCM_CIMR_MASK_CKIH_READY (0x1 << 4)
#define MXC_CCM_CIMR_MASK_FPM_READY (0x1 << 3)
+/* MX53/MX50 */
+#define MXC_CCM_CIMR_MASK_COSC_READY (0x1 << 6)
+#define MXC_CCM_CIMR_MASK_CAMP2_READY (0x1 << 5)
+#define MXC_CCM_CIMR_MASK_CAMP1_READY (0x1 << 4)
+#define MXC_CCM_CIMR_MASK_LRF_PLL4 (0x1 << 3)
#define MXC_CCM_CIMR_MASK_LRF_PLL3 (0x1 << 2)
#define MXC_CCM_CIMR_MASK_LRF_PLL2 (0x1 << 1)
#define MXC_CCM_CIMR_MASK_LRF_PLL1 (0x1)
@@ -442,11 +615,20 @@
#define MXC_CCM_CCOSR_CKOL_SEL_MASK (0xF)
/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_ARM_CLK_INPUT_SEL (0x1 << 24)
+#define MXC_CCM_CGPR_ARM_ASYNC_REF_EN (0x1 << 23)
#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (0x1 << 4)
#define MXC_CCM_CGPR_FPM_SEL (0x1 << 3)
#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET (0)
#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK (0x7)
+#define MX50_CCM_CCOSR_CKO1_SLOW_SEL (0x1 << 8)
+#define MX50_CCM_CCOSR_CKO1_EN (0x1 << 7)
+#define MX50_CCM_CCOSR_CKO1_DIV_OFFSET (4)
+#define MX50_CCM_CCOSR_CKO1_DIV_MASK (0x7 << 4)
+#define MX50_CCM_CCOSR_CKO1_SEL_OFFSET (0)
+#define MX50_CCM_CCOSR_CKO1_SEL_MASK (0xF)
+
/* Define the bits in registers CCGRx */
#define MXC_CCM_CCGRx_CG_MASK 0x3
#define MXC_CCM_CCGRx_MOD_OFF 0x0
@@ -485,30 +667,120 @@
#define MXC_CCM_CCGRx_CG1_OFFSET 2
#define MXC_CCM_CCGRx_CG0_OFFSET 0
-#define MXC_DPTC_LP_BASE (MX51_GPC_BASE + 0x80)
-#define MXC_DPTC_GP_BASE (MX51_GPC_BASE + 0x100)
-#define MXC_DVFS_CORE_BASE (MX51_GPC_BASE + 0x180)
-#define MXC_DPTC_PER_BASE (MX51_GPC_BASE + 0x1C0)
-#define MXC_PGC_IPU_BASE (MX51_GPC_BASE + 0x220)
-#define MXC_PGC_VPU_BASE (MX51_GPC_BASE + 0x240)
-#define MXC_PGC_GPU_BASE (MX51_GPC_BASE + 0x260)
-#define MXC_SRPG_NEON_BASE (MX51_GPC_BASE + 0x280)
-#define MXC_SRPG_ARM_BASE (MX51_GPC_BASE + 0x2A0)
-#define MXC_SRPG_EMPGC0_BASE (MX51_GPC_BASE + 0x2C0)
-#define MXC_SRPG_EMPGC1_BASE (MX51_GPC_BASE + 0x2D0)
-#define MXC_SRPG_MEGAMIX_BASE (MX51_GPC_BASE + 0x2E0)
-#define MXC_SRPG_EMI_BASE (MX51_GPC_BASE + 0x300)
+#define MXC_CCM_CCGR5_CG6_1_OFFSET 12
+#define MXC_CCM_CCGR5_CG6_2_OFFSET 13
+
+/* Define the bits in registers CSR2 */
+#define MXC_CCM_CSR2_ELCDIF_PIX_BUSY (0x1 << 9)
+#define MXC_CCM_CSR2_EPDC_PIX_BUSY (0x1 << 8)
+#define MXC_CCM_CSR2_EPDC_AXI_BUSY (0x1 << 4)
+#define MXC_CCM_CSR2_DISPLAY_AXI_BUSY (0x1 << 3)
+
+/* Define the bits in registers CLKSEQ_BYPASS */
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_ELCDIF_PIX_CLK_SEL_OFFSET 14
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_ELCDIF_PIX_CLK_SEL_MASK (0x3 << 14)
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_PIX_CLK_SEL_OFFSET 12
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_PIX_CLK_SEL_MASK (0x3 << 12)
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_GPMI_CLK_SEL_OFFSET 6
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_GPMI_CLK_SEL_MASK (0x3 << 6)
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_BCH_CLK_SEL_OFFSET 8
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_BCH_CLK_SEL_MASK (0x3 << 8)
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_AXI_CLK_SEL_OFFSET 4
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_EPDC_AXI_CLK_SEL_MASK (0x3 << 4)
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_DISPLAY_AXI_CLK_SEL_OFFSET 2
+#define MXC_CCM_CLKSEQ_BYPASS_BYPASS_DISPLAY_AXI_CLK_SEL_MASK (0x3 << 2)
+
+/* Define the bits in registers CLK_SYS */
+#define MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_OFFSET (30)
+#define MXC_CCM_CLK_SYS_SYS_XTAL_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_CLK_SYS_SYS_PLL_CLKGATE_OFFSET (28)
+#define MXC_CCM_CLK_SYS_SYS_PLL_CLKGATE_MASK (0x3 << 28)
+#define MXC_CCM_CLK_SYS_DIV_XTAL_OFFSET (6)
+#define MXC_CCM_CLK_SYS_DIV_XTAL_MASK (0xF << 6)
+#define MXC_CCM_CLK_SYS_DIV_PLL_OFFSET (0)
+#define MXC_CCM_CLK_SYS_DIV_PLL_MASK (0x3F)
+
+/* Define the bits in registers CLK_DDR */
+#define MXC_CCM_CLK_DDR_DDR_CLKGATE_OFFSET (30)
+#define MXC_CCM_CLK_DDR_DDR_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_CLK_DDR_DDR_PFD_SEL (1 << 6)
+#define MXC_CCM_CLK_DDR_DDR_DIV_PLL_OFFSET (0)
+#define MXC_CCM_CLK_DDR_DDR_DIV_PLL_MASK (0x3F)
+
+/* Define the bits in register DISPLAY_AXI */
+#define MXC_CCM_DISPLAY_AXI_CLKGATE_OFFSET (30)
+#define MXC_CCM_DISPLAY_AXI_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_DISPLAY_AXI_PXP_ASM_EN (1 << 13)
+#define MXC_CCM_DISPLAY_AXI_PXP_ASM_DIV_MASK (0x7 << 10)
+#define MXC_CCM_DISPLAY_AXI_PXP_ASM_DIV_OFFSET 10
+#define MXC_CCM_DISPLAY_AXI_DIV_OFFSET (0)
+#define MXC_CCM_DISPLAY_AXI_DIV_MASK (0x3F)
+
+/* Define the bits in register EPDC_AXI */
+#define MXC_CCM_EPDC_AXI_CLKGATE_OFFSET (30)
+#define MXC_CCM_EPDC_AXI_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_EPDC_AXI_ASM_EN (1 << 9)
+#define MXC_CCM_EPDC_AXI_ASM_DIV_OFFSET (6)
+#define MXC_CCM_EPDC_AXI_ASM_DIV_MASK (0x7 << 6)
+#define MXC_CCM_EPDC_AXI_DIV_OFFSET (0)
+#define MXC_CCM_EPDC_AXI_DIV_MASK (0x3F)
+
+/* Define the bits in register EPDCPIX */
+#define MXC_CCM_EPDC_PIX_CLKGATE_OFFSET (30)
+#define MXC_CCM_EPDC_PIX_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_EPDC_PIX_CLK_PRED_OFFSET (12)
+#define MXC_CCM_EPDC_PIX_CLK_PRED_MASK (0x3 << 12)
+#define MXC_CCM_EPDC_PIX_CLK_PODF_OFFSET (0)
+#define MXC_CCM_EPDC_PIX_CLK_PODF_MASK (0xFFF)
+
+/* Define the bits in register ELCDIFPIX */
+#define MXC_CCM_ELCDIFPIX_CLKGATE_OFFSET (30)
+#define MXC_CCM_ELCDIFPIX_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_ELCDIFPIX_CLK_PRED_OFFSET (12)
+#define MXC_CCM_ELCDIFPIX_CLK_PRED_MASK (0x3 << 12)
+#define MXC_CCM_ELCDIFPIX_CLK_PODF_OFFSET (0)
+#define MXC_CCM_ELCDIFPIX_CLK_PODF_MASK (0xFFF)
+
+
+/* Define the bits in register GPMI */
+#define MXC_CCM_GPMI_CLKGATE_OFFSET (30)
+#define MXC_CCM_GPMI_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_GPMI_CLK_DIV_OFFSET (0)
+#define MXC_CCM_GPMI_CLK_DIV_MASK (0x3F)
+
+/* Define the bits in register BCH */
+#define MXC_CCM_BCH_CLKGATE_OFFSET (30)
+#define MXC_CCM_BCH_CLKGATE_MASK (0x3 << 30)
+#define MXC_CCM_BCH_CLK_DIV_OFFSET (0)
+#define MXC_CCM_BCH_CLK_DIV_MASK (0x3F)
+
+#define MXC_GPC_BASE (IO_ADDRESS(GPC_BASE_ADDR))
+#define MXC_DPTC_LP_BASE (MXC_GPC_BASE + 0x80)
+#define MXC_DPTC_GP_BASE (MXC_GPC_BASE + 0x100)
+#define MXC_DVFS_CORE_BASE (MXC_GPC_BASE + 0x180)
+#define MXC_DVFS_PER_BASE (MXC_GPC_BASE + 0x1C4)
+#define MXC_PGC_IPU_BASE (MXC_GPC_BASE + 0x220)
+#define MXC_PGC_VPU_BASE (MXC_GPC_BASE + 0x240)
+#define MXC_PGC_GPU_BASE (MXC_GPC_BASE + 0x260)
+#define MXC_SRPG_NEON_BASE (MXC_GPC_BASE + 0x280)
+#define MXC_SRPG_ARM_BASE (MXC_GPC_BASE + 0x2A0)
+#define MXC_SRPG_EMPGC0_BASE (MXC_GPC_BASE + 0x2C0)
+#define MXC_SRPG_EMPGC1_BASE (MXC_GPC_BASE + 0x2D0)
+#define MXC_SRPG_MEGAMIX_BASE (MXC_GPC_BASE + 0x2E0)
+#define MXC_SRPG_EMI_BASE (MXC_GPC_BASE + 0x300)
/* CORTEXA8 platform */
-#define MXC_CORTEXA8_PLAT_PVID (MX51_CORTEXA8_BASE + 0x0)
-#define MXC_CORTEXA8_PLAT_GPC (MX51_CORTEXA8_BASE + 0x4)
-#define MXC_CORTEXA8_PLAT_PIC (MX51_CORTEXA8_BASE + 0x8)
-#define MXC_CORTEXA8_PLAT_LPC (MX51_CORTEXA8_BASE + 0xC)
-#define MXC_CORTEXA8_PLAT_NEON_LPC (MX51_CORTEXA8_BASE + 0x10)
-#define MXC_CORTEXA8_PLAT_ICGC (MX51_CORTEXA8_BASE + 0x14)
-#define MXC_CORTEXA8_PLAT_AMC (MX51_CORTEXA8_BASE + 0x18)
-#define MXC_CORTEXA8_PLAT_NMC (MX51_CORTEXA8_BASE + 0x20)
-#define MXC_CORTEXA8_PLAT_NMS (MX51_CORTEXA8_BASE + 0x24)
+extern void __iomem *arm_plat_base;
+#define MXC_CORTEXA8_BASE (arm_plat_base)
+#define MXC_CORTEXA8_PLAT_PVID (arm_plat_base + 0x0)
+#define MXC_CORTEXA8_PLAT_GPC (arm_plat_base + 0x4)
+#define MXC_CORTEXA8_PLAT_PIC (arm_plat_base + 0x8)
+#define MXC_CORTEXA8_PLAT_LPC (arm_plat_base + 0xC)
+#define MXC_CORTEXA8_PLAT_NEON_LPC (arm_plat_base + 0x10)
+#define MXC_CORTEXA8_PLAT_ICGC (arm_plat_base + 0x14)
+#define MXC_CORTEXA8_PLAT_AMC (arm_plat_base + 0x18)
+#define MXC_CORTEXA8_PLAT_NMC (arm_plat_base + 0x20)
+#define MXC_CORTEXA8_PLAT_NMS (arm_plat_base + 0x24)
/* DVFS CORE */
#define MXC_DVFSTHRS (MXC_DVFS_CORE_BASE + 0x00)
@@ -529,14 +801,23 @@
#define MXC_DVFSPT2 (MXC_DVFS_CORE_BASE + 0x3C)
#define MXC_DVFSPT3 (MXC_DVFS_CORE_BASE + 0x40)
+/* DVFS PER */
+#define MXC_DVFSPER_LTR0 (MXC_DVFS_PER_BASE)
+#define MXC_DVFSPER_LTR1 (MXC_DVFS_PER_BASE + 0x04)
+#define MXC_DVFSPER_LTR2 (MXC_DVFS_PER_BASE + 0x08)
+#define MXC_DVFSPER_LTR3 (MXC_DVFS_PER_BASE + 0x0C)
+#define MXC_DVFSPER_LTBR0 (MXC_DVFS_PER_BASE + 0x10)
+#define MXC_DVFSPER_LTBR1 (MXC_DVFS_PER_BASE + 0x14)
+#define MXC_DVFSPER_PMCR0 (MXC_DVFS_PER_BASE + 0x18)
+#define MXC_DVFSPER_PMCR1 (MXC_DVFS_PER_BASE + 0x1C)
+
/* GPC */
-#define MXC_GPC_CNTR (MX51_GPC_BASE + 0x0)
-#define MXC_GPC_PGR (MX51_GPC_BASE + 0x4)
-#define MXC_GPC_VCR (MX51_GPC_BASE + 0x8)
-#define MXC_GPC_ALL_PU (MX51_GPC_BASE + 0xC)
-#define MXC_GPC_NEON (MX51_GPC_BASE + 0x10)
-#define MXC_GPC_PGR_ARMPG_OFFSET 8
-#define MXC_GPC_PGR_ARMPG_MASK (3 << 8)
+#define MXC_GPC_CNTR (MXC_GPC_BASE + 0x0)
+#define MXC_GPC_PGR (MXC_GPC_BASE + 0x4)
+#define MXC_GPC_VCR (MXC_GPC_BASE + 0x8)
+#define MXC_GPC_CNTR_OFFSET 0x0
+#define MXC_GPC_PGR_OFFSET 0x4
+#define MXC_GPC_VCR_OFFSET 0x8
/* PGC */
#define MXC_PGC_IPU_PGCR (MXC_PGC_IPU_BASE + 0x0)
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
new file mode 100644
index 000000000000..8235b8c6729b
--- /dev/null
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * 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.
+ */
+#include <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst;
+#define imx51_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst;
+#define imx51_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
+#define imx51_add_cspi(pdata) \
+ imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
+#define imx51_add_ecspi(id, pdata) \
+ imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 7130449aacdc..68c021c28064 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -1,7 +1,8 @@
/*
- * Copyright 2009 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
@@ -10,79 +11,541 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/ipu.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/uio_driver.h>
+#include <linux/mxc_scc2_driver.h>
+#include <linux/iram_alloc.h>
+#include <linux/gpmi-nfc.h>
+#include <linux/fsl_devices.h>
+#include <mach/common.h>
#include <mach/hardware.h>
-#include <mach/imx-uart.h>
-#include <mach/irqs.h>
+#include <mach/gpio.h>
+#include <mach/sdma.h>
+#include "dma-apbh.h"
-static struct resource uart0[] = {
+/* Flag used to indicate when IRAM has been initialized */
+int iram_ready;
+/* Flag used to indicate if dvfs_core is active. */
+int dvfs_core_is_active;
+
+static struct resource sdma_resources[] = {
{
- .start = MX51_UART1_BASE_ADDR,
- .end = MX51_UART1_BASE_ADDR + 0xfff,
+ .start = SDMA_BASE_ADDR,
+ .end = SDMA_BASE_ADDR + SZ_4K - 1,
.flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_UART1,
- .end = MX51_MXC_INT_UART1,
+ },
+ {
+ .start = MXC_INT_SDMA,
.flags = IORESOURCE_IRQ,
},
};
-struct platform_device mxc_uart_device0 = {
- .name = "imx-uart",
+struct platform_device mxc_dma_device = {
+ .name = "mxc_sdma",
+ .id = -1,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(sdma_resources),
+ .resource = sdma_resources,
+};
+
+static struct resource mxc_w1_master_resources[] = {
+ {
+ .start = OWIRE_BASE_ADDR,
+ .end = OWIRE_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_OWIRE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_w1_master_device = {
+ .name = "mxc_w1",
.id = 0,
- .resource = uart0,
- .num_resources = ARRAY_SIZE(uart0),
+ .num_resources = ARRAY_SIZE(mxc_w1_master_resources),
+ .resource = mxc_w1_master_resources,
};
-static struct resource uart1[] = {
+static struct resource mxc_kpp_resources[] = {
{
- .start = MX51_UART2_BASE_ADDR,
- .end = MX51_UART2_BASE_ADDR + 0xfff,
+ .start = KPP_BASE_ADDR,
+ .end = KPP_BASE_ADDR + SZ_4K - 1,
.flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_UART2,
- .end = MX51_MXC_INT_UART2,
+ },
+ {
+ .start = MXC_INT_KPP,
+ .end = MXC_INT_KPP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_keypad_device = {
+ .name = "mxc_keypad",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_kpp_resources),
+ .resource = mxc_kpp_resources,
+};
+
+struct platform_device mxc_powerkey_device = {
+ .name = "mxcpwrkey",
+ .id = 0,
+};
+static struct resource rtc_resources[] = {
+ {
+ .start = SRTC_BASE_ADDR,
+ .end = SRTC_BASE_ADDR + 0x40,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SRTC_NTZ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_rtc_device = {
+ .name = "mxc_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static struct resource mxc_nand_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .name = "NFC_AXI_BASE",
+ .start = MX51_NFC_BASE_ADDR_AXI,
+ .end = MX51_NFC_BASE_ADDR_AXI + SZ_8K - 1,
+ },
+ {
+ .flags = IORESOURCE_MEM,
+ .name = "NFC_IP_BASE",
+ .start = NFC_BASE_ADDR + 0x00,
+ .end = NFC_BASE_ADDR + 0x34 - 1,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_NFC,
+ .end = MXC_INT_NFC,
+ },
+};
+
+struct platform_device mxc_nandv2_mtd_device = {
+ .name = "mxc_nandv2_flash",
+ .id = 0,
+ .resource = mxc_nand_resources,
+ .num_resources = ARRAY_SIZE(mxc_nand_resources),
+};
+
+static struct resource gpmi_nfc_resources[] = {
+ {
+ .name = GPMI_NFC_GPMI_REGS_ADDR_RES_NAME,
+ .flags = IORESOURCE_MEM,
+ .start = GPMI_BASE_ADDR,
+ .end = GPMI_BASE_ADDR + SZ_8K - 1,
+ },
+ {
+ .name = GPMI_NFC_GPMI_INTERRUPT_RES_NAME,
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_RAWNAND_GPMI,
+ .end = MXC_INT_RAWNAND_GPMI,
+ },
+ {
+ .name = GPMI_NFC_BCH_REGS_ADDR_RES_NAME,
+ .flags = IORESOURCE_MEM,
+ .start = BCH_BASE_ADDR,
+ .end = BCH_BASE_ADDR + SZ_8K - 1,
+ },
+ {
+ .name = GPMI_NFC_BCH_INTERRUPT_RES_NAME,
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_RAWNAND_BCH,
+ .end = MXC_INT_RAWNAND_BCH,
+ },
+ {
+ .name = GPMI_NFC_DMA_CHANNELS_RES_NAME,
+ .flags = IORESOURCE_DMA,
+ .start = MXS_DMA_CHANNEL_AHB_APBH_GPMI0,
+ .end = MXS_DMA_CHANNEL_AHB_APBH_GPMI7,
+ },
+ {
+ .name = GPMI_NFC_DMA_INTERRUPT_RES_NAME,
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_APBHDMA_CHAN0,
+ .end = MXC_INT_APBHDMA_CHAN7,
+ },
+};
+
+struct platform_device gpmi_nfc_device = {
+ .name = GPMI_NFC_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = gpmi_nfc_resources,
+ .num_resources = ARRAY_SIZE(gpmi_nfc_resources),
+};
+
+static struct resource imx_nfc_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = MX51_NFC_BASE_ADDR_AXI,
+ .end = MX51_NFC_BASE_ADDR_AXI + 0x1200 - 1,
+ .name = IMX_NFC_BUFFERS_ADDR_RES_NAME,
+ },
+ {
+ .flags = IORESOURCE_MEM,
+ .start = MX51_NFC_BASE_ADDR_AXI + 0x1E00,
+ .end = MX51_NFC_BASE_ADDR_AXI + 0x1E44 - 1,
+ .name = IMX_NFC_PRIMARY_REGS_ADDR_RES_NAME,
+ },
+ {
+ .flags = IORESOURCE_MEM,
+ .start = NFC_BASE_ADDR + 0x00,
+ .end = NFC_BASE_ADDR + 0x34 - 1,
+ .name = IMX_NFC_SECONDARY_REGS_ADDR_RES_NAME,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_NFC,
+ .end = MXC_INT_NFC,
+ .name = IMX_NFC_INTERRUPT_RES_NAME,
+ },
+};
+
+struct platform_device imx_nfc_device = {
+ .name = IMX_NFC_DRIVER_NAME,
+ .id = 0,
+ .resource = imx_nfc_resources,
+ .num_resources = ARRAY_SIZE(imx_nfc_resources),
+};
+
+static struct resource wdt_resources[] = {
+ {
+ .start = WDOG1_BASE_ADDR,
+ .end = WDOG1_BASE_ADDR + 0x30,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device mxc_wdt_device = {
+ .name = "mxc_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(wdt_resources),
+ .resource = wdt_resources,
+};
+
+static struct resource pwm1_resources[] = {
+ {
+ .start = PWM1_BASE_ADDR,
+ .end = PWM1_BASE_ADDR + 0x14,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_PWM1,
+ .end = MXC_INT_PWM1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_pwm1_device = {
+ .name = "mxc_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(pwm1_resources),
+ .resource = pwm1_resources,
+};
+
+static struct resource pwm2_resources[] = {
+ {
+ .start = PWM2_BASE_ADDR,
+ .end = PWM2_BASE_ADDR + 0x14,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_PWM2,
+ .end = MXC_INT_PWM2,
.flags = IORESOURCE_IRQ,
},
};
-struct platform_device mxc_uart_device1 = {
- .name = "imx-uart",
+struct platform_device mxc_pwm2_device = {
+ .name = "mxc_pwm",
.id = 1,
- .resource = uart1,
- .num_resources = ARRAY_SIZE(uart1),
+ .num_resources = ARRAY_SIZE(pwm2_resources),
+ .resource = pwm2_resources,
};
-static struct resource uart2[] = {
+struct platform_device mxc_pwm1_backlight_device = {
+ .name = "pwm-backlight",
+ .id = 0,
+};
+
+struct platform_device mxc_pwm2_backlight_device = {
+ .name = "pwm-backlight",
+ .id = 1,
+};
+
+static struct resource flexcan0_resources[] = {
{
- .start = MX51_UART3_BASE_ADDR,
- .end = MX51_UART3_BASE_ADDR + 0xfff,
+ .start = CAN1_BASE_ADDR,
+ .end = CAN1_BASE_ADDR + 0x3FFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_CAN1,
+ .end = MXC_INT_CAN1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_flexcan0_device = {
+ .name = "FlexCAN",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(flexcan0_resources),
+ .resource = flexcan0_resources,
+};
+
+static struct resource flexcan1_resources[] = {
+ {
+ .start = CAN2_BASE_ADDR,
+ .end = CAN2_BASE_ADDR + 0x3FFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_CAN2,
+ .end = MXC_INT_CAN2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_flexcan1_device = {
+ .name = "FlexCAN",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(flexcan1_resources),
+ .resource = flexcan1_resources,
+};
+
+static struct resource ipu_resources[] = {
+ {
+ .start = MX51_IPU_CTRL_BASE_ADDR,
+ .end = MX51_IPU_CTRL_BASE_ADDR + SZ_512M,
.flags = IORESOURCE_MEM,
- }, {
- .start = MX51_MXC_INT_UART3,
- .end = MX51_MXC_INT_UART3,
+ },
+ {
+ .start = MXC_INT_IPU_SYN,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MXC_INT_IPU_ERR,
.flags = IORESOURCE_IRQ,
},
};
-struct platform_device mxc_uart_device2 = {
- .name = "imx-uart",
- .id = 2,
- .resource = uart2,
- .num_resources = ARRAY_SIZE(uart2),
+struct platform_device mxc_ipu_device = {
+ .name = "mxc_ipu",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ipu_resources),
+ .resource = ipu_resources,
};
-static struct resource mxc_fec_resources[] = {
+static struct resource epdc_resources[] = {
+ {
+ .start = EPDC_BASE_ADDR,
+ .end = EPDC_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_EPDC,
+ .end = MXC_INT_EPDC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device epdc_device = {
+ .name = "mxc_epdc_fb",
+ .id = -1,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(epdc_resources),
+ .resource = epdc_resources,
+};
+
+static struct resource elcdif_resources[] = {
+ {
+ .start = ELCDIF_BASE_ADDR,
+ .end = ELCDIF_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_ELCDIF,
+ .end = MXC_INT_ELCDIF,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device elcdif_device = {
+ .name = "mxc_elcdif_fb",
+ .id = -1,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(elcdif_resources),
+ .resource = elcdif_resources,
+};
+
+struct platform_device mxc_fb_devices[] = {
+ {
+ .name = "mxc_sdc_fb",
+ .id = 0,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ {
+ .name = "mxc_sdc_fb",
+ .id = 1,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ {
+ .name = "mxc_sdc_fb",
+ .id = 2,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+};
+
+static struct resource ldb_resources[] = {
+ {
+ .start = IOMUXC_BASE_ADDR,
+ .end = IOMUXC_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device mxc_ldb_device = {
+ .name = "mxc_ldb",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ldb_resources),
+ .resource = ldb_resources,
+};
+
+static struct resource vpu_resources[] = {
+ {
+ .start = VPU_BASE_ADDR,
+ .end = VPU_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
{
- .start = MX51_MXC_FEC_BASE_ADDR,
- .end = MX51_MXC_FEC_BASE_ADDR + 0xfff,
+ .start = MXC_INT_VPU,
+ .end = MXC_INT_VPU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxcvpu_device = {
+ .name = "mxc_vpu",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(vpu_resources),
+ .resource = vpu_resources,
+};
+
+struct platform_device fixed_volt_reg_device = {
+ .name = "reg-fixed-voltage",
+ .id = -1,
+};
+
+static struct resource scc_resources[] = {
+ {
+ .start = SCC_BASE_ADDR,
+ .end = SCC_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MX51_SCC_RAM_BASE_ADDR,
+ .end = MX51_SCC_RAM_BASE_ADDR + SZ_16K - 1,
.flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device mxcscc_device = {
+ .name = "mxc_scc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(scc_resources),
+ .resource = scc_resources,
+};
+
+static struct resource dcp_resources[] = {
+
+ {
+ .flags = IORESOURCE_MEM,
+ .start = DCP_BASE_ADDR,
+ .end = DCP_BASE_ADDR + 0x2000 - 1,
}, {
- .start = MX51_MXC_INT_FEC,
- .end = MX51_MXC_INT_FEC,
- .flags = IORESOURCE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_DCP_CHAN0,
+ .end = MXC_INT_DCP_CHAN0,
+ }, {
+ .flags = IORESOURCE_IRQ,
+ .start = MXC_INT_DCP_CHAN1_3,
+ .end = MXC_INT_DCP_CHAN1_3,
+ },
+};
+
+struct platform_device dcp_device = {
+ .name = "dcp",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(dcp_resources),
+ .resource = dcp_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+
+static struct resource rngb_resources[] = {
+ {
+ .start = RNGB_BASE_ADDR,
+ .end = RNGB_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_RNGB_BLOCK,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* the RNGC driver applies for MX50's RNGB hw */
+struct platform_device mxc_rngb_device = {
+ .name = "fsl_rngc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(rngb_resources),
+ .resource = rngb_resources,
+};
+
+static struct resource mxc_fec_resources[] = {
+ {
+ .start = FEC_BASE_ADDR,
+ .end = FEC_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .start = MXC_INT_FEC,
+ .end = MXC_INT_FEC,
+ .flags = IORESOURCE_IRQ
},
};
@@ -93,57 +556,734 @@ struct platform_device mxc_fec_device = {
.resource = mxc_fec_resources,
};
+static struct resource mxc_ptp_resources[] = {
+ {
+ .start = PTP_BASE_ADDR,
+ .end = PTP_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .start = RTC_BASE_ADDR,
+ .end = RTC_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM
+ },
+ {
+ .start = MXC_INT_PTP,
+ .end = MXC_INT_PTP,
+ .flags = IORESOURCE_IRQ
+ },
+ {
+ .start = MXC_INT_RTC,
+ .end = MXC_INT_RTC,
+ .flags = IORESOURCE_IRQ
+ },
+};
+
+struct platform_device mxc_ptp_device = {
+ .name = "ptp",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_ptp_resources),
+ .resource = mxc_ptp_resources,
+};
+
+static struct resource mxcspi1_resources[] = {
+ {
+ .start = CSPI1_BASE_ADDR,
+ .end = CSPI1_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_CSPI1,
+ .end = MXC_INT_CSPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxcspi1_device = {
+ .name = "mxc_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxcspi1_resources),
+ .resource = mxcspi1_resources,
+};
+
+static struct resource mxcspi2_resources[] = {
+ {
+ .start = CSPI2_BASE_ADDR,
+ .end = CSPI2_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_CSPI2,
+ .end = MXC_INT_CSPI2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxcspi2_device = {
+ .name = "mxc_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mxcspi2_resources),
+ .resource = mxcspi2_resources,
+};
+
+static struct resource mxcspi3_resources[] = {
+ {
+ .start = CSPI3_BASE_ADDR,
+ .end = CSPI3_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_CSPI,
+ .end = MXC_INT_CSPI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxcspi3_device = {
+ .name = "mxc_spi",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mxcspi3_resources),
+ .resource = mxcspi3_resources,
+};
+
+static struct resource mxci2c1_resources[] = {
+ {
+ .start = I2C1_BASE_ADDR,
+ .end = I2C1_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_I2C1,
+ .end = MXC_INT_I2C1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource mxci2c2_resources[] = {
+ {
+ .start = I2C2_BASE_ADDR,
+ .end = I2C2_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_I2C2,
+ .end = MXC_INT_I2C2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource mxci2c3_resources[] = {
+ {
+ .start = I2C3_BASE_ADDR,
+ .end = I2C3_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_I2C3,
+ .end = MXC_INT_I2C3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxci2c_devices[] = {
+ {
+ .name = "imx-i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxci2c1_resources),
+ .resource = mxci2c1_resources,
+ },
+ {
+ .name = "imx-i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mxci2c2_resources),
+ .resource = mxci2c2_resources,
+ },
+ {
+ .name = "imx-i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mxci2c3_resources),
+ .resource = mxci2c3_resources,
+ },
+};
+
+static struct resource mxci2c_hs_resources[] = {
+ {
+ .start = HSI2C_DMA_BASE_ADDR,
+ .end = HSI2C_DMA_BASE_ADDR + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_HS_I2C,
+ .end = MXC_INT_HS_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxci2c_hs_device = {
+ .name = "mxc_i2c_hs",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(mxci2c_hs_resources),
+ .resource = mxci2c_hs_resources
+};
+
+static struct resource ssi1_resources[] = {
+ {
+ .start = SSI1_BASE_ADDR,
+ .end = SSI1_BASE_ADDR + 0x5C,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SSI1,
+ .end = MXC_INT_SSI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_ssi1_device = {
+ .name = "mxc_ssi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ssi1_resources),
+ .resource = ssi1_resources,
+};
+
+static struct resource ssi2_resources[] = {
+ {
+ .start = SSI2_BASE_ADDR,
+ .end = SSI2_BASE_ADDR + 0x5C,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SSI2,
+ .end = MXC_INT_SSI2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_ssi2_device = {
+ .name = "mxc_ssi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(ssi2_resources),
+ .resource = ssi2_resources,
+};
+
+static struct resource ssi3_resources[] = {
+ {
+ .start = SSI3_BASE_ADDR,
+ .end = SSI3_BASE_ADDR + 0x5C,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SSI3,
+ .end = MXC_INT_SSI3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_ssi3_device = {
+ .name = "mxc_ssi",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(ssi3_resources),
+ .resource = ssi3_resources,
+};
+
+static struct resource esai_resources[] = {
+ {
+ .start = ESAI_BASE_ADDR,
+ .end = ESAI_BASE_ADDR + 0x100,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_ESAI,
+ .end = MXC_INT_ESAI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_esai_device = {
+ .name = "mxc_esai",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(esai_resources),
+ .resource = esai_resources,
+};
+
+static struct resource tve_resources[] = {
+ {
+ .start = TVE_BASE_ADDR,
+ .end = TVE_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_TVE,
+ .end = MXC_INT_TVE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_tve_device = {
+ .name = "tve",
+ .num_resources = ARRAY_SIZE(tve_resources),
+ .resource = tve_resources,
+};
+
+static struct resource dvfs_core_resources[] = {
+ {
+ .start = DVFSCORE_BASE_ADDR,
+ .end = DVFSCORE_BASE_ADDR + 4 * SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_GPC1,
+ .end = MXC_INT_GPC1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_dvfs_core_device = {
+ .name = "mxc_dvfs_core",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(dvfs_core_resources),
+ .resource = dvfs_core_resources,
+};
+
+static struct resource dvfs_per_resources[] = {
+ {
+ .start = DVFSPER_BASE_ADDR,
+ .end = DVFSPER_BASE_ADDR + 2 * SZ_16 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_GPC1,
+ .end = MXC_INT_GPC1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_dvfs_per_device = {
+ .name = "mxc_dvfsper",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(dvfs_per_resources),
+ .resource = dvfs_per_resources,
+};
+
+static struct resource asrc_resources[] = {
+ {
+ .start = ASRC_BASE_ADDR,
+ .end = ASRC_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_ASRC,
+ .end = MXC_INT_ASRC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_asrc_device = {
+ .name = "mxc_asrc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(asrc_resources),
+ .resource = asrc_resources,
+};
+
+struct mxc_gpio_port mxc_gpio_ports[] = {
+ {
+ .chip.label = "gpio-0",
+ .base = IO_ADDRESS(GPIO1_BASE_ADDR),
+ .irq = MXC_INT_GPIO1_LOW,
+ .irq_high = MXC_INT_GPIO1_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START
+ },
+ {
+ .chip.label = "gpio-1",
+ .base = IO_ADDRESS(GPIO2_BASE_ADDR),
+ .irq = MXC_INT_GPIO2_LOW,
+ .irq_high = MXC_INT_GPIO2_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
+ },
+ {
+ .chip.label = "gpio-2",
+ .base = IO_ADDRESS(GPIO3_BASE_ADDR),
+ .irq = MXC_INT_GPIO3_LOW,
+ .irq_high = MXC_INT_GPIO3_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
+ },
+ {
+ .chip.label = "gpio-3",
+ .base = IO_ADDRESS(GPIO4_BASE_ADDR),
+ .irq = MXC_INT_GPIO4_LOW,
+ .irq_high = MXC_INT_GPIO4_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
+ },
+ {
+ .chip.label = "gpio-4",
+ .base = IO_ADDRESS(GPIO5_BASE_ADDR),
+ .irq = MXC_INT_GPIO5_LOW,
+ .irq_high = MXC_INT_GPIO5_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
+ },
+ {
+ .chip.label = "gpio-5",
+ .base = IO_ADDRESS(GPIO6_BASE_ADDR),
+ .irq = MXC_INT_GPIO6_LOW,
+ .irq_high = MXC_INT_GPIO6_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
+ },
+ {
+ .chip.label = "gpio-6",
+ .base = IO_ADDRESS(GPIO7_BASE_ADDR),
+ .irq = MXC_INT_GPIO7_LOW,
+ .irq_high = MXC_INT_GPIO7_HIGH,
+ .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
+ },
+};
+
+int __init mxc_register_gpios(void)
+{
+ if (cpu_is_mx51())
+ return mxc_gpio_init(mxc_gpio_ports, 4);
+ else if (cpu_is_mx50())
+ return mxc_gpio_init(mxc_gpio_ports, 6);
+ return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
+}
+
+static struct resource spdif_resources[] = {
+ {
+ .start = SPDIF_BASE_ADDR,
+ .end = SPDIF_BASE_ADDR + 0x50,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SPDIF_MX51,
+ .end = MXC_INT_SPDIF_MX51,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_alsa_spdif_device = {
+ .name = "mxc_alsa_spdif",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(spdif_resources),
+ .resource = spdif_resources,
+};
+
+struct platform_device mx51_lpmode_device = {
+ .name = "mx51_lpmode",
+ .id = 0,
+};
+
+struct platform_device busfreq_device = {
+ .name = "busfreq",
+ .id = 0,
+};
+
+struct platform_device pm_device = {
+ .name = "mx5_pm",
+ .id = 0,
+};
+
+static struct resource mxc_m4if_resources[] = {
+ {
+ .start = M4IF_BASE_ADDR,
+ .end = M4IF_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device sdram_autogating_device = {
+ .name = "sdram_autogating",
+ .id = 0,
+ .resource = mxc_m4if_resources,
+ .num_resources = ARRAY_SIZE(mxc_m4if_resources),
+};
+
+static struct resource mxc_iim_resources[] = {
+ {
+ .start = IIM_BASE_ADDR,
+ .end = IIM_BASE_ADDR + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_IIM,
+ .end = MXC_INT_IIM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_iim_device = {
+ .name = "mxc_iim",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_iim_resources),
+ .resource = mxc_iim_resources
+};
+
+static struct resource mxc_sim_resources[] = {
+ {
+ .start = SIM_BASE_ADDR,
+ .end = SIM_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SIM_IPB,
+ .end = MXC_INT_SIM_IPB,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MXC_INT_SIM_DAT,
+ .end = MXC_INT_SIM_DAT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_sim_device = {
+ .name = "mxc_sim",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_sim_resources),
+ .resource = mxc_sim_resources,
+};
+
+static struct resource mxcsdhc1_resources[] = {
+ {
+ .start = MMC_SDHC1_BASE_ADDR,
+ .end = MMC_SDHC1_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_MMC_SDHC1,
+ .end = MXC_INT_MMC_SDHC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource mxcsdhc2_resources[] = {
+ {
+ .start = MMC_SDHC2_BASE_ADDR,
+ .end = MMC_SDHC2_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_MMC_SDHC2,
+ .end = MXC_INT_MMC_SDHC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource mxcsdhc3_resources[] = {
+ {
+ .start = MMC_SDHC3_BASE_ADDR,
+ .end = MMC_SDHC3_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_MMC_SDHC3,
+ .end = MXC_INT_MMC_SDHC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxcsdhc1_device = {
+ .name = "mxsdhci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxcsdhc1_resources),
+ .resource = mxcsdhc1_resources,
+};
+
+struct platform_device mxcsdhc2_device = {
+ .name = "mxsdhci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mxcsdhc2_resources),
+ .resource = mxcsdhc2_resources,
+};
+
+struct platform_device mxcsdhc3_device = {
+ .name = "mxsdhci",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mxcsdhc3_resources),
+ .resource = mxcsdhc3_resources,
+};
+
+static struct resource pata_fsl_resources[] = {
+ {
+ .start = ATA_BASE_ADDR,
+ .end = ATA_BASE_ADDR + 0x000000C8,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_ATA,
+ .end = MXC_INT_ATA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device pata_fsl_device = {
+ .name = "pata_fsl",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pata_fsl_resources),
+ .resource = pata_fsl_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/* On-Chip OTP device and resource */
+static struct resource otp_resource = {
+ .start = OCOTP_CTRL_BASE_ADDR,
+ .end = OCOTP_CTRL_BASE_ADDR + SZ_8K - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+struct platform_device fsl_otp_device = {
+ .name = "ocotp",
+ .id = -1,
+ .resource = &otp_resource,
+ .num_resources = 1,
+};
+
+static struct resource ahci_fsl_resources[] = {
+ {
+ .start = MX53_SATA_BASE_ADDR,
+ .end = MX53_SATA_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_SATA,
+ .end = MXC_INT_SATA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device ahci_fsl_device = {
+ .name = "ahci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ahci_fsl_resources),
+ .resource = ahci_fsl_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
static u64 usb_dma_mask = DMA_BIT_MASK(32);
-static struct resource usbotg_resources[] = {
+static struct resource usbotg_host_resources[] = {
+ {
+ .start = OTG_BASE_ADDR,
+ .end = OTG_BASE_ADDR + 0x1ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_USB_OTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource usbotg_udc_resources[] = {
+ {
+ .start = OTG_BASE_ADDR,
+ .end = OTG_BASE_ADDR + 0x1ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_USB_OTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource usbotg_xcvr_resources[] = {
{
- .start = MX51_OTG_BASE_ADDR,
- .end = MX51_OTG_BASE_ADDR + 0x1ff,
+ .start = OTG_BASE_ADDR,
+ .end = OTG_BASE_ADDR + 0x1ff,
.flags = IORESOURCE_MEM,
},
{
- .start = MX51_MXC_INT_USB_OTG,
+ .start = MXC_INT_USB_OTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource usbotg_wakeup_resources[] = {
+ {
+ .start = MXC_INT_USB_OTG,/* wakeup irq */
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MXC_INT_USB_OTG,/* usb core irq , may be equel to wakeup irq for some imx chips */
.flags = IORESOURCE_IRQ,
},
};
-/* OTG gadget device */
struct platform_device mxc_usbdr_udc_device = {
.name = "fsl-usb2-udc",
.id = -1,
- .num_resources = ARRAY_SIZE(usbotg_resources),
- .resource = usbotg_resources,
+ .dev = {
+ .dma_mask = &usb_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = usbotg_udc_resources,
+ .num_resources = ARRAY_SIZE(usbotg_udc_resources),
+};
+
+struct platform_device mxc_usbdr_otg_device = {
+ .name = "fsl-usb2-otg",
+ .id = -1,
.dev = {
.dma_mask = &usb_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
+ .resource = usbotg_xcvr_resources,
+ .num_resources = ARRAY_SIZE(usbotg_xcvr_resources),
};
struct platform_device mxc_usbdr_host_device = {
- .name = "mxc-ehci",
+ .name = "fsl-ehci",
.id = 0,
- .num_resources = ARRAY_SIZE(usbotg_resources),
- .resource = usbotg_resources,
+ .num_resources = ARRAY_SIZE(usbotg_host_resources),
+ .resource = usbotg_host_resources,
.dev = {
.dma_mask = &usb_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
+struct platform_device mxc_usbdr_wakeup_device = {
+ .name = "usb_wakeup",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(usbotg_wakeup_resources),
+ .resource = usbotg_wakeup_resources,
+};
+
static struct resource usbh1_resources[] = {
{
- .start = MX51_OTG_BASE_ADDR + 0x200,
- .end = MX51_OTG_BASE_ADDR + 0x200 + 0x1ff,
+ .start = OTG_BASE_ADDR + 0x200,
+ .end = OTG_BASE_ADDR + 0x200 + 0x1ff,
.flags = IORESOURCE_MEM,
},
{
- .start = MX51_MXC_INT_USB_H1,
+ .start = MXC_INT_USB_H1,
.flags = IORESOURCE_IRQ,
},
};
+static struct resource usbh1_wakeup_resources[] = {
+ {
+ .start = MXC_INT_USB_H1, /*wakeup irq*/
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MXC_INT_USB_H1,
+ .flags = IORESOURCE_IRQ,/* usb core irq */
+ },
+};
+
struct platform_device mxc_usbh1_device = {
- .name = "mxc-ehci",
+ .name = "fsl-ehci",
.id = 1,
.num_resources = ARRAY_SIZE(usbh1_resources),
.resource = usbh1_resources,
@@ -153,49 +1293,607 @@ struct platform_device mxc_usbh1_device = {
},
};
-static struct resource mxc_wdt_resources[] = {
+struct platform_device mxc_usbh1_wakeup_device = {
+ .name = "usb_wakeup",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(usbh1_wakeup_resources),
+ .resource = usbh1_wakeup_resources,
+};
+
+static struct resource usbh2_resources[] = {
{
- .start = MX51_WDOG_BASE_ADDR,
- .end = MX51_WDOG_BASE_ADDR + SZ_16K - 1,
+ .start = OTG_BASE_ADDR + 0x400,
+ .end = OTG_BASE_ADDR + 0x400 + 0x1ff,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = MXC_INT_USB_H2,
+ .flags = IORESOURCE_IRQ,
+ },
};
-struct platform_device mxc_wdt = {
- .name = "imx2-wdt",
+static struct resource usbh2_wakeup_resources[] = {
+ {
+ .start = MXC_INT_USB_H2,
+ .flags = IORESOURCE_IRQ,/* wakeup irq */
+ },
+ {
+ .start = MXC_INT_USB_H2,
+ .flags = IORESOURCE_IRQ,/* usb core irq */
+ },
+};
+struct platform_device mxc_usbh2_device = {
+ .name = "fsl-ehci",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(usbh2_resources),
+ .resource = usbh2_resources,
+ .dev = {
+ .dma_mask = &usb_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+struct platform_device mxc_usbh2_wakeup_device = {
+ .name = "usb_wakeup",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(usbh2_wakeup_resources),
+ .resource = usbh2_wakeup_resources,
+};
+
+static struct resource mxc_gpu_resources[] = {
+ {
+ .start = MXC_INT_GPU2_IRQ,
+ .end = MXC_INT_GPU2_IRQ,
+ .name = "gpu_2d_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MXC_INT_GPU,
+ .end = MXC_INT_GPU,
+ .name = "gpu_3d_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MX51_GPU2D_BASE_ADDR,
+ .end = MX51_GPU2D_BASE_ADDR + SZ_4K - 1,
+ .name = "gpu_2d_registers",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = GPU_BASE_ADDR,
+ .end = GPU_BASE_ADDR + SZ_128K - 1,
+ .name = "gpu_3d_registers",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MX51_GPU_GMEM_BASE_ADDR,
+ .end = MX51_GPU_GMEM_BASE_ADDR + SZ_128K - 1,
+ .name = "gpu_graphics_mem",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0,
+ .end = 0,
+ .name = "gpu_reserved_mem",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device gpu_device = {
+ .name = "mxc_gpu",
.id = 0,
- .num_resources = ARRAY_SIZE(mxc_wdt_resources),
- .resource = mxc_wdt_resources,
+ .num_resources = ARRAY_SIZE(mxc_gpu_resources),
+ .resource = mxc_gpu_resources,
};
-static struct mxc_gpio_port mxc_gpio_ports[] = {
+int z160_revision;
+
+static struct resource mxc_gpu2d_resources[] = {
{
- .chip.label = "gpio-0",
- .base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO1_LOW,
- .virtual_irq_start = MXC_GPIO_IRQ_START
+ .start = MX51_GPU2D_BASE_ADDR,
+ .end = MX51_GPU2D_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
},
{
- .chip.label = "gpio-1",
- .base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO2_LOW,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
+ .flags = IORESOURCE_MEM,
},
{
- .chip.label = "gpio-2",
- .base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO3_LOW,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
+ .flags = IORESOURCE_MEM,
},
+};
+
+static struct resource mlb_resources[] = {
+ [0] = {
+ .start = MLB_BASE_ADDR,
+ .end = MLB_BASE_ADDR + 0x300,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MXC_INT_MLB,
+ .end = MXC_INT_MLB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_mlb_device = {
+ .name = "mxc_mlb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mlb_resources),
+ .resource = mlb_resources,
+};
+
+static struct resource pxp_resources[] = {
{
- .chip.label = "gpio-3",
- .base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO4_LOW,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
+ .start = EPXP_BASE_ADDR,
+ .end = EPXP_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_EPXP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mxc_pxp_device = {
+ .name = "mxc-pxp",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pxp_resources),
+ .resource = pxp_resources,
+};
+
+struct platform_device mxc_pxp_client_device = {
+ .name = "pxp-device",
+ .id = -1,
+};
+
+static u64 pxp_dma_mask = DMA_BIT_MASK(32);
+struct platform_device mxc_pxp_v4l2 = {
+ .name = "pxp-v4l2",
+ .id = -1,
+ .dev = {
+ .dma_mask = &pxp_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
},
};
-int __init mxc_register_gpios(void)
+struct platform_device mxc_v4l2_device = {
+ .name = "mxc_v4l2_capture",
+ .id = 0,
+};
+
+struct platform_device mxc_v4l2out_device = {
+ .name = "mxc_v4l2_output",
+ .id = 0,
+};
+
+struct resource viim_resources[] = {
+ [0] = {
+ .start = (GPT1_BASE_ADDR - 0x20000000),
+ .end = (GPT1_BASE_ADDR - 0x20000000) + PAGE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OCOTP_CTRL_BASE_ADDR,
+ .end = OCOTP_CTRL_BASE_ADDR + PAGE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+struct platform_device mxs_viim = {
+ .name = "mxs_viim",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(viim_resources),
+ .resource = viim_resources,
+};
+
+static struct resource mx5_perfmon_res[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .start = PERFMON_BASE_ADDR,
+ .end = PERFMON_BASE_ADDR + 0x1000 - 1,
+ },
+};
+
+struct platform_device mxc_perfmon = {
+ .name = "mxs-perfmon",
+ .resource = mx5_perfmon_res,
+ .num_resources = ARRAY_SIZE(mx5_perfmon_res),
+ .id = 0
+};
+
+static struct mxs_perfmon_bit_config
+mx50_perfmon_bit_config[] = {
+ {.field = (1 << 0), .name = "MID0-CORE" },
+ {.field = (1 << 1), .name = "MID1-DCP" },
+ {.field = (1 << 2), .name = "MID2-PXP" },
+ {.field = (1 << 3), .name = "MID3-USB" },
+ {.field = (1 << 4), .name = "MID4-GPU2D" },
+ {.field = (1 << 5), .name = "MID5-BCH" },
+ {.field = (1 << 6), .name = "MID6-AHB" },
+ {.field = (1 << 7), .name = "MID7-EPDC" },
+ {.field = (1 << 8), .name = "MID8-LCDIF" },
+ {.field = (1 << 9), .name = "MID9-SDMA" },
+ {.field = (1 << 10), .name = "MID10-FEC" },
+ {.field = (1 << 11), .name = "MID11-MSHC" }
+};
+
+struct mxs_platform_perfmon_data mxc_perfmon_data = {
+ .bit_config_tab = mx50_perfmon_bit_config,
+ .bit_config_cnt = ARRAY_SIZE(mx50_perfmon_bit_config),
+};
+
+static struct resource dma_apbh_resources[] = {
+ {
+ .start = APBHDMA_BASE_ADDR,
+ .end = APBHDMA_BASE_ADDR + 0x2000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device mxs_dma_apbh_device = {
+ .name = "mxs-dma-apbh",
+ .num_resources = ARRAY_SIZE(dma_apbh_resources),
+ .resource = dma_apbh_resources,
+};
+
+struct platform_device mxc_zq_calib_device = {
+ .name = "mxc_zq_calib",
+ .id = -1,
+};
+
+void __init mx5_init_irq(void)
{
- return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
+ unsigned long tzic_addr;
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0)
+ tzic_addr = MX51_TZIC_BASE_ADDR_T01;
+ else if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0)
+ tzic_addr = MX51_TZIC_BASE_ADDR;
+ else /* mx53 and mx50 */
+ tzic_addr = MX53_TZIC_BASE_ADDR;
+
+ mxc_tzic_init_irq(tzic_addr);
}
+
+#define SCM_RD_DELAY 1000000 /* in nanoseconds */
+#define SEC_TO_NANOSEC 1000000000 /*Second to nanoseconds */
+static __init void mxc_init_scc_iram(void)
+{
+ uint32_t reg_value;
+ uint32_t reg_mask = 0;
+ uint8_t *UMID_base;
+ uint32_t *MAP_base;
+ uint8_t i;
+ uint32_t partition_no;
+ uint32_t scc_partno;
+ void *scm_ram_base;
+ void *scc_base;
+ uint32_t ram_partitions, ram_partition_size, ram_size;
+ uint32_t scm_version_register;
+ struct timespec stime;
+ struct timespec curtime;
+ long scm_rd_timeout = 0;
+ long cur_ns = 0;
+ long start_ns = 0;
+
+ scc_base = ioremap((uint32_t) scc_resources[0].start, 0x140);
+ if (scc_base == NULL) {
+ printk(KERN_ERR "FAILED TO MAP SCC REGS\n");
+ return;
+ }
+
+ scm_version_register = __raw_readl(scc_base + SCM_VERSION_REG);
+ ram_partitions = 1 + ((scm_version_register & SCM_VER_NP_MASK)
+ >> SCM_VER_NP_SHIFT);
+ ram_partition_size = (uint32_t) (1 <<
+ ((scm_version_register & SCM_VER_BPP_MASK)
+ >> SCM_VER_BPP_SHIFT));
+
+ ram_size = (uint32_t)(ram_partitions * ram_partition_size);
+
+ scm_ram_base = ioremap((uint32_t) scc_resources[1].start, ram_size);
+
+ if (scm_ram_base == NULL) {
+ printk(KERN_ERR "FAILED TO MAP SCC RAM\n");
+ return;
+ }
+
+ /* Wait for any running SCC operations to finish or fail */
+ getnstimeofday(&stime);
+ do {
+ reg_value = __raw_readl(scc_base + SCM_STATUS_REG);
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec > stime.tv_nsec)
+ scm_rd_timeout = curtime.tv_nsec - stime.tv_nsec;
+ else{
+ /*Converted second to nanosecond and add to
+ nsec when current nanosec is less than
+ start time nanosec.*/
+ cur_ns = (curtime.tv_sec * SEC_TO_NANOSEC) +
+ curtime.tv_nsec;
+ start_ns = (stime.tv_sec * SEC_TO_NANOSEC) +
+ stime.tv_nsec;
+ scm_rd_timeout = cur_ns - start_ns;
+ }
+ } while (((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY)
+ && ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_FAIL));
+
+ /* Check for failures */
+ if ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY) {
+ /* Special message for bad secret key fuses */
+ if (reg_value & SCM_STATUS_KST_BAD_KEY)
+ printk(KERN_ERR "INVALID SCC KEY FUSE PATTERN\n");
+ else
+ printk(KERN_ERR "SECURE RAM FAILURE\n");
+
+ iounmap(scm_ram_base);
+ iounmap(scc_base);
+ return;
+ }
+
+ scm_rd_timeout = 0;
+
+ /* Release all partitions for SCC2 driver on MX53*/
+ if (cpu_is_mx53())
+ scc_partno = 0;
+ /* Release final two partitions for SCC2 driver on MX51 */
+ else
+ scc_partno = ram_partitions -
+ (SCC_RAM_SIZE / ram_partition_size);
+
+ for (partition_no = scc_partno; partition_no < ram_partitions;
+ partition_no++) {
+ reg_value = (((partition_no << SCM_ZCMD_PART_SHIFT) &
+ SCM_ZCMD_PART_MASK) | ((0x03 << SCM_ZCMD_CCMD_SHIFT) &
+ SCM_ZCMD_CCMD_MASK));
+ __raw_writel(reg_value, scc_base + SCM_ZCMD_REG);
+ udelay(1);
+ /* Wait for zeroization to complete */
+ getnstimeofday(&stime);
+ do {
+ reg_value = __raw_readl(scc_base + SCM_STATUS_REG);
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec > stime.tv_nsec)
+ scm_rd_timeout = curtime.tv_nsec -
+ stime.tv_nsec;
+ else {
+ /*Converted second to nanosecond and add to
+ nsec when current nanosec is less than
+ start time nanosec.*/
+ cur_ns = (curtime.tv_sec * SEC_TO_NANOSEC) +
+ curtime.tv_nsec;
+ start_ns = (stime.tv_sec * SEC_TO_NANOSEC) +
+ stime.tv_nsec;
+ scm_rd_timeout = cur_ns - start_ns;
+ }
+ } while (((reg_value & SCM_STATUS_SRS_MASK) !=
+ SCM_STATUS_SRS_READY) && ((reg_value & SCM_STATUS_SRS_MASK) !=
+ SCM_STATUS_SRS_FAIL) && (scm_rd_timeout <= SCM_RD_DELAY));
+
+ if (scm_rd_timeout > SCM_RD_DELAY)
+ printk(KERN_ERR "SCM Status Register Read timeout"
+ "for Partition No:%d", partition_no);
+
+ if ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY)
+ break;
+ }
+
+ /* 4 partitions on MX53 */
+ if (cpu_is_mx53())
+ reg_mask = 0xFF;
+
+ /*Check all expected partitions released */
+ reg_value = __raw_readl(scc_base + SCM_PART_OWNERS_REG);
+ if ((reg_value & reg_mask) != 0) {
+ printk(KERN_ERR "FAILED TO RELEASE IRAM PARTITION\n");
+ iounmap(scm_ram_base);
+ iounmap(scc_base);
+ return;
+ }
+
+ /* we are done if this is MX53, since no sharing of IRAM and SCC_RAM */
+ if (cpu_is_mx53())
+ goto exit;
+
+ reg_mask = 0;
+ scm_rd_timeout = 0;
+ /* Allocate remaining partitions for general use */
+ for (partition_no = 0; partition_no < scc_partno; partition_no++) {
+ /* Supervisor mode claims a partition for it's own use
+ by writing zero to SMID register.*/
+ __raw_writel(0, scc_base + (SCM_SMID0_REG + 8 * partition_no));
+
+ /* Wait for any zeroization to complete */
+ getnstimeofday(&stime);
+ do {
+ reg_value = __raw_readl(scc_base + SCM_STATUS_REG);
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec > stime.tv_nsec)
+ scm_rd_timeout = curtime.tv_nsec -
+ stime.tv_nsec;
+ else{
+ /*Converted second to nanosecond and add to
+ nsec when current nanosec is less than
+ start time nanosec.*/
+ cur_ns = (curtime.tv_sec * SEC_TO_NANOSEC) +
+ curtime.tv_nsec;
+ start_ns = (stime.tv_sec * SEC_TO_NANOSEC) +
+ stime.tv_nsec;
+ scm_rd_timeout = cur_ns - start_ns;
+ }
+ } while (((reg_value & SCM_STATUS_SRS_MASK) !=
+ SCM_STATUS_SRS_READY) && ((reg_value & SCM_STATUS_SRS_MASK) !=
+ SCM_STATUS_SRS_FAIL) && (scm_rd_timeout <= SCM_RD_DELAY));
+
+ if (scm_rd_timeout > SCM_RD_DELAY)
+ printk(KERN_ERR "SCM Status Register Read timeout"
+ "for Partition No:%d", partition_no);
+
+ if ((reg_value & SCM_STATUS_SRS_MASK) != SCM_STATUS_SRS_READY)
+ break;
+ /* Set UMID=0 and permissions for universal data
+ read/write access */
+ MAP_base = scm_ram_base +
+ (uint32_t) (partition_no * ram_partition_size);
+ UMID_base = (uint8_t *) MAP_base + 0x10;
+ for (i = 0; i < 16; i++)
+ UMID_base[i] = 0;
+
+ MAP_base[0] = (SCM_PERM_NO_ZEROIZE | SCM_PERM_HD_SUP_DISABLE |
+ SCM_PERM_HD_READ | SCM_PERM_HD_WRITE |
+ SCM_PERM_HD_EXECUTE | SCM_PERM_TH_READ |
+ SCM_PERM_TH_WRITE);
+ reg_mask |= (3 << (2 * (partition_no)));
+ }
+
+ /* Check all expected partitions allocated */
+ reg_value = __raw_readl(scc_base + SCM_PART_OWNERS_REG);
+ if ((reg_value & reg_mask) != reg_mask) {
+ printk(KERN_ERR "FAILED TO ACQUIRE IRAM PARTITION\n");
+ iounmap(scm_ram_base);
+ iounmap(scc_base);
+ return;
+ }
+
+exit:
+ iounmap(scm_ram_base);
+ iounmap(scc_base);
+ printk(KERN_INFO "IRAM READY\n");
+ iram_ready = 1;
+}
+
+#define MX53_OFFSET 0x20000000
+
+int __init mxc_init_devices(void)
+{
+ if (cpu_is_mx53() || cpu_is_mx50()) {
+ sdma_resources[0].start -= MX53_OFFSET;
+ sdma_resources[0].end -= MX53_OFFSET;
+ mxc_w1_master_resources[0].start -= MX53_OFFSET;
+ mxc_w1_master_resources[0].end -= MX53_OFFSET;
+ mxc_kpp_resources[0].start -= MX53_OFFSET;
+ mxc_kpp_resources[0].end -= MX53_OFFSET;
+ rtc_resources[0].start -= MX53_OFFSET;
+ rtc_resources[0].end -= MX53_OFFSET;
+
+ wdt_resources[0].start -= MX53_OFFSET;
+ wdt_resources[0].end -= MX53_OFFSET;
+ pwm1_resources[0].start -= MX53_OFFSET;
+ pwm1_resources[0].end -= MX53_OFFSET;
+ pwm2_resources[0].start -= MX53_OFFSET;
+ pwm2_resources[0].end -= MX53_OFFSET;
+ flexcan0_resources[0].start -= MX53_OFFSET;
+ flexcan0_resources[0].end -= MX53_OFFSET;
+ flexcan1_resources[0].start -= MX53_OFFSET;
+ flexcan1_resources[0].end -= MX53_OFFSET;
+ mxc_fec_resources[0].start -= MX53_OFFSET;
+ mxc_fec_resources[0].end -= MX53_OFFSET;
+ mxc_ptp_resources[0].start -= MX53_OFFSET;
+ mxc_ptp_resources[0].end -= MX53_OFFSET;
+ mxc_ptp_resources[1].start -= MX53_OFFSET;
+ mxc_ptp_resources[1].end -= MX53_OFFSET;
+ vpu_resources[0].start -= MX53_OFFSET;
+ vpu_resources[0].end -= MX53_OFFSET;
+ scc_resources[0].start -= MX53_OFFSET;
+ scc_resources[0].end -= MX53_OFFSET;
+ scc_resources[1].start = MX53_SCC_RAM_BASE_ADDR;
+ scc_resources[1].end = MX53_SCC_RAM_BASE_ADDR + SZ_16K - 1;
+ rngb_resources[0].start -= MX53_OFFSET;
+ rngb_resources[0].end -= MX53_OFFSET;
+ mxcspi1_resources[0].start -= MX53_OFFSET;
+ mxcspi1_resources[0].end -= MX53_OFFSET;
+ mxcspi2_resources[0].start -= MX53_OFFSET;
+ mxcspi2_resources[0].end -= MX53_OFFSET;
+ mxcspi3_resources[0].start -= MX53_OFFSET;
+ mxcspi3_resources[0].end -= MX53_OFFSET;
+ mxci2c1_resources[0].start -= MX53_OFFSET;
+ mxci2c1_resources[0].end -= MX53_OFFSET;
+ mxci2c2_resources[0].start -= MX53_OFFSET;
+ mxci2c2_resources[0].end -= MX53_OFFSET;
+ mxci2c3_resources[0].start -= MX53_OFFSET;
+ mxci2c3_resources[0].end -= MX53_OFFSET;
+ ssi1_resources[0].start -= MX53_OFFSET;
+ ssi1_resources[0].end -= MX53_OFFSET;
+ ssi2_resources[0].start -= MX53_OFFSET;
+ ssi2_resources[0].end -= MX53_OFFSET;
+ esai_resources[0].start -= MX53_OFFSET;
+ esai_resources[0].end -= MX53_OFFSET;
+ tve_resources[0].start -= MX53_OFFSET;
+ tve_resources[0].end -= MX53_OFFSET;
+ dvfs_core_resources[0].start -= MX53_OFFSET;
+ dvfs_core_resources[0].end -= MX53_OFFSET;
+ dvfs_per_resources[0].start -= MX53_OFFSET;
+ dvfs_per_resources[0].end -= MX53_OFFSET;
+ spdif_resources[0].start -= MX53_OFFSET;
+ spdif_resources[0].end -= MX53_OFFSET;
+ spdif_resources[1].start = MXC_INT_SPDIF_MX53;
+ spdif_resources[1].end = MXC_INT_SPDIF_MX53;
+ asrc_resources[0].start -= MX53_OFFSET;
+ asrc_resources[0].end -= MX53_OFFSET;
+ mxc_m4if_resources[0].start -= MX53_OFFSET;
+ mxc_m4if_resources[0].end -= MX53_OFFSET;
+ mxc_iim_resources[0].start -= MX53_OFFSET;
+ mxc_iim_resources[0].end -= MX53_OFFSET;
+ mxc_sim_resources[0].start -= MX53_OFFSET;
+ mxc_sim_resources[0].end -= MX53_OFFSET;
+ mxcsdhc1_resources[0].start -= MX53_OFFSET;
+ mxcsdhc1_resources[0].end -= MX53_OFFSET;
+ mxcsdhc2_resources[0].start -= MX53_OFFSET;
+ mxcsdhc2_resources[0].end -= MX53_OFFSET;
+ mxcsdhc3_resources[0].start -= MX53_OFFSET;
+ mxcsdhc3_resources[0].end -= MX53_OFFSET;
+ usbotg_host_resources[0].start -= MX53_OFFSET;
+ usbotg_host_resources[0].end -= MX53_OFFSET;
+ usbotg_udc_resources[0].start -= MX53_OFFSET;
+ usbotg_udc_resources[0].end -= MX53_OFFSET;
+ usbotg_xcvr_resources[0].start -= MX53_OFFSET;
+ usbotg_xcvr_resources[0].end -= MX53_OFFSET;
+ usbh1_resources[0].start -= MX53_OFFSET;
+ usbh1_resources[0].end -= MX53_OFFSET;
+ usbh2_resources[0].start -= MX53_OFFSET;
+ usbh2_resources[0].end -= MX53_OFFSET;
+ mxc_gpu_resources[2].start = MX53_GPU2D_BASE_ADDR;
+ mxc_gpu_resources[2].end = MX53_GPU2D_BASE_ADDR + SZ_4K - 1;
+ mxc_gpu2d_resources[0].start = MX53_GPU2D_BASE_ADDR;
+ mxc_gpu2d_resources[0].end = MX53_GPU2D_BASE_ADDR + SZ_4K - 1;
+ if (cpu_is_mx53()) {
+ mxc_gpu_resources[4].start = MX53_GPU_GMEM_BASE_ADDR;
+ mxc_gpu_resources[4].end = MX53_GPU_GMEM_BASE_ADDR
+ + SZ_256K - 1;
+ if (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1) {
+ z160_revision = 1;
+ } else {
+ z160_revision = 0;
+ }
+ } else {
+ mxc_gpu_resources[1].start = 0;
+ mxc_gpu_resources[1].end = 0;
+ mxc_gpu_resources[3].start = 0;
+ mxc_gpu_resources[3].end = 0;
+ mxc_gpu_resources[4].start = 0;
+ mxc_gpu_resources[4].end = 0;
+ z160_revision = 1;
+ }
+ ipu_resources[0].start = MX53_IPU_CTRL_BASE_ADDR;
+ ipu_resources[0].end = MX53_IPU_CTRL_BASE_ADDR + SZ_128M - 1;
+ mlb_resources[0].start -= MX53_OFFSET;
+ mlb_resources[0].end -= MX53_OFFSET;
+ mxc_nandv2_mtd_device.resource[0].start =
+ MX53_NFC_BASE_ADDR_AXI;
+ mxc_nandv2_mtd_device.resource[0].end =
+ MX53_NFC_BASE_ADDR_AXI + SZ_8K - 1;
+ mxc_nandv2_mtd_device.resource[1].start -= MX53_OFFSET;
+ mxc_nandv2_mtd_device.resource[1].end -= MX53_OFFSET;
+ ldb_resources[0].start -= MX53_OFFSET;
+ ldb_resources[0].end -= MX53_OFFSET;
+ } else if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) {
+ scc_resources[1].start += 0x8000;
+ scc_resources[1].end += 0x8000;
+ }
+
+
+ if (cpu_is_mx51() || cpu_is_mx53())
+ mxc_init_scc_iram();
+ return 0;
+}
+postcore_initcall(mxc_init_devices);
+
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index c879ae71cd5b..2671b5dc6f83 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -1,8 +1,95 @@
-extern struct platform_device mxc_uart_device0;
-extern struct platform_device mxc_uart_device1;
-extern struct platform_device mxc_uart_device2;
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
extern struct platform_device mxc_fec_device;
+extern struct platform_device mxc_ptp_device;
+extern struct platform_device mxc_dma_device;
+extern struct platform_device mxc_w1_master_device;
+extern struct platform_device mxc_keypad_device;
+extern struct platform_device mxc_powerkey_device;
+extern struct platform_device mxc_rtc_device;
+extern struct platform_device mxc_nandv2_mtd_device;
+extern struct platform_device imx_nfc_device;
+extern struct platform_device mxc_wdt_device;
+extern struct platform_device mxc_pwm1_device;
+extern struct platform_device mxc_pwm2_device;
+extern struct platform_device mxc_pwm1_backlight_device;
+extern struct platform_device mxc_pwm2_backlight_device;
+extern struct platform_device mxc_flexcan0_device;
+extern struct platform_device mxc_flexcan1_device;
+extern struct platform_device mxc_ipu_device;
+extern struct platform_device mxc_fb_devices[];
+extern struct platform_device mxc_ldb_device;
+extern struct platform_device mxcvpu_device;
+extern struct platform_device mxcscc_device;
+extern struct platform_device mxcspi1_device;
+extern struct platform_device mxcspi2_device;
+extern struct platform_device mxcspi3_device;
+extern struct platform_device mxci2c_devices[];
+extern struct platform_device mxci2c_hs_device;
+extern struct platform_device mxc_tve_device;
+extern struct platform_device mxc_dvfs_core_device;
+extern struct platform_device mxc_dvfs_per_device;
+extern struct platform_device mxc_ssi1_device;
+extern struct platform_device mxc_ssi2_device;
+extern struct platform_device mxc_ssi3_device;
+extern struct platform_device mxc_esai_device;
+extern struct platform_device mxc_alsa_spdif_device;
+extern struct platform_device mx51_lpmode_device;
+extern struct platform_device mx53_lpmode_device;
+extern struct platform_device busfreq_device;
+extern struct platform_device sdram_autogating_device;
+extern struct platform_device mxc_iim_device;
+extern struct platform_device mxc_sim_device;
+extern struct platform_device mxcsdhc1_device;
+extern struct platform_device mxcsdhc2_device;
+extern struct platform_device mxcsdhc3_device;
+extern struct platform_device ahci_fsl_device;
+extern struct ahci_platform_data sata_data;
+extern struct platform_device pata_fsl_device;
+extern struct platform_device fsl_otp_device;
+extern struct platform_device gpu_device;
+extern struct platform_device mxc_usbdr_udc_device;
+extern struct platform_device mxc_usbdr_otg_device;
extern struct platform_device mxc_usbdr_host_device;
+extern struct platform_device mxc_usbdr_wakeup_device;
extern struct platform_device mxc_usbh1_device;
-extern struct platform_device mxc_usbdr_udc_device;
-extern struct platform_device mxc_wdt;
+extern struct platform_device mxc_usbh1_wakeup_device;
+extern struct platform_device mxc_usbh2_device;
+extern struct platform_device mxc_usbh2_wakeup_device;
+extern struct platform_device mxc_mlb_device;
+extern struct platform_device mxc_nandv2_mtd_device;
+extern struct platform_device mxc_pxp_device;
+extern struct platform_device mxc_pxp_client_device;
+extern struct platform_device mxc_pxp_v4l2;
+extern struct platform_device epdc_device;
+extern struct platform_device elcdif_device;
+extern struct platform_device mxc_v4l2_device;
+extern struct platform_device mxc_v4l2out_device;
+extern struct platform_device mxs_viim;
+extern struct platform_device mxs_dma_apbh_device;
+extern struct platform_device gpmi_nfc_device;
+extern struct platform_device mxc_rngb_device;
+extern struct platform_device dcp_device;
+extern struct platform_device pm_device;
+extern struct platform_device fixed_volt_reg_device;
+extern struct platform_device mxc_zq_calib_device;
+extern struct platform_device mxc_asrc_device;
+extern struct platform_device mxc_perfmon;
+extern struct mxs_platform_perfmon_data mxc_perfmon_data;
+extern int z160_revision;
diff --git a/arch/arm/mach-mx5/dma-apbh.c b/arch/arm/mach-mx5/dma-apbh.c
new file mode 100644
index 000000000000..9e1b10d7c35c
--- /dev/null
+++ b/arch/arm/mach-mx5/dma-apbh.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dmapool.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc.h>
+#include <mach/dmaengine.h>
+
+#include "regs-apbh.h"
+
+#ifndef BM_APBH_CTRL0_APB_BURST_EN
+#define BM_APBH_CTRL0_APB_BURST_EN BM_APBH_CTRL0_APB_BURST4_EN
+#endif
+
+static int mxs_dma_apbh_enable(struct mxs_dma_chan *pchan, unsigned int chan)
+{
+ unsigned int sem;
+ struct mxs_dma_device *pdev = pchan->dma;
+ struct mxs_dma_desc *pdesc;
+
+ pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node);
+ if (pdesc == NULL)
+ return -EFAULT;
+
+ sem = __raw_readl(pdev->base + HW_APBH_CHn_SEMA(chan));
+ sem = (sem & BM_APBH_CHn_SEMA_PHORE) >> BP_APBH_CHn_SEMA_PHORE;
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY) {
+
+ if (pdesc->cmd.cmd.bits.chain == 0)
+ return 0;
+ if (sem < 2) {
+ if (!sem)
+ return 0;
+ pdesc = list_entry(pdesc->node.next,
+ struct mxs_dma_desc, node);
+ __raw_writel(mxs_dma_cmd_address(pdesc),
+ pdev->base + HW_APBH_CHn_NXTCMDAR(chan));
+ }
+ sem = pchan->pending_num;
+ pchan->pending_num = 0;
+ __raw_writel(BF_APBH_CHn_SEMA_INCREMENT_SEMA(sem),
+ pdev->base + HW_APBH_CHn_SEMA(chan));
+ pchan->active_num += sem;
+ return 0;
+ }
+
+ pchan->active_num += pchan->pending_num;
+ pchan->pending_num = 0;
+ __raw_writel(mxs_dma_cmd_address(pdesc),
+ pdev->base + HW_APBH_CHn_NXTCMDAR(chan));
+ __raw_writel(pchan->active_num, pdev->base + HW_APBH_CHn_SEMA(chan));
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CTRL0_CLR);
+ return 0;
+}
+
+static void mxs_dma_apbh_disable(struct mxs_dma_chan *pchan, unsigned int chan)
+{
+ struct mxs_dma_device *pdev = pchan->dma;
+ __raw_writel(1 << (chan + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+ pdev->base + HW_APBH_CTRL0_SET);
+}
+
+static void mxs_dma_apbh_reset(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << (chan + BP_APBH_CHANNEL_CTRL_RESET_CHANNEL),
+ pdev->base + HW_APBH_CHANNEL_CTRL_SET);
+}
+
+static void mxs_dma_apbh_freeze(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CHANNEL_CTRL_SET);
+}
+
+static void
+mxs_dma_apbh_unfreeze(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CHANNEL_CTRL_CLR);
+}
+
+static void mxs_dma_apbh_info(struct mxs_dma_device *pdev,
+ unsigned int chan, struct mxs_dma_info *info)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBH_CTRL2);
+ info->status = reg >> chan;
+ info->buf_addr = __raw_readl(pdev->base + HW_APBH_CHn_BAR(chan));
+}
+
+static int
+mxs_dma_apbh_read_semaphore(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBH_CHn_SEMA(chan));
+ return (reg & BM_APBH_CHn_SEMA_PHORE) >> BP_APBH_CHn_SEMA_PHORE;
+}
+
+static void
+mxs_dma_apbh_enable_irq(struct mxs_dma_device *pdev,
+ unsigned int chan, int enable)
+{
+ if (enable)
+ __raw_writel(1 << (chan + 16), pdev->base + HW_APBH_CTRL1_SET);
+ else
+ __raw_writel(1 << (chan + 16), pdev->base + HW_APBH_CTRL1_CLR);
+
+}
+
+static int
+mxs_dma_apbh_irq_is_pending(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ unsigned int reg;
+ reg = __raw_readl(pdev->base + HW_APBH_CTRL1);
+ reg |= __raw_readl(pdev->base + HW_APBH_CTRL2);
+ return reg & (1 << chan);
+}
+
+static void mxs_dma_apbh_ack_irq(struct mxs_dma_device *pdev, unsigned int chan)
+{
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CTRL1_CLR);
+ __raw_writel(1 << chan, pdev->base + HW_APBH_CTRL2_CLR);
+}
+
+static struct mxs_dma_device mxs_dma_apbh = {
+ .name = "mxs-dma-apbh",
+ .enable = mxs_dma_apbh_enable,
+ .disable = mxs_dma_apbh_disable,
+ .reset = mxs_dma_apbh_reset,
+ .freeze = mxs_dma_apbh_freeze,
+ .unfreeze = mxs_dma_apbh_unfreeze,
+ .info = mxs_dma_apbh_info,
+ .read_semaphore = mxs_dma_apbh_read_semaphore,
+ .enable_irq = mxs_dma_apbh_enable_irq,
+ .irq_is_pending = mxs_dma_apbh_irq_is_pending,
+ .ack_irq = mxs_dma_apbh_ack_irq,
+};
+
+static int __devinit dma_apbh_probe(struct platform_device *pdev)
+{
+ int i;
+ struct resource *res;
+ struct mxs_dma_plat_data *plat;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENOMEM;
+ mxs_dma_apbh.base = ioremap(res->start, resource_size(res));
+ __raw_writel(BM_APBH_CTRL0_SFTRST,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+ for (i = 0; i < 10000; i++) {
+ if (!(__raw_readl(mxs_dma_apbh.base + HW_APBH_CTRL0_CLR) &
+ BM_APBH_CTRL0_SFTRST))
+ break;
+ udelay(2);
+ }
+ if (i >= 10000)
+ return -ETIME;
+ __raw_writel(BM_APBH_CTRL0_CLKGATE,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+
+ plat = (struct mxs_dma_plat_data *)pdev->dev.platform_data;
+ if (!plat)
+ return -ENODEV;
+ if (plat->burst8)
+ __raw_writel(BM_APBH_CTRL0_AHB_BURST8_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_SET);
+ else
+ __raw_writel(BM_APBH_CTRL0_AHB_BURST8_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+
+ if (plat->burst)
+ __raw_writel(BM_APBH_CTRL0_APB_BURST_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_SET);
+ else
+ __raw_writel(BM_APBH_CTRL0_APB_BURST_EN,
+ mxs_dma_apbh.base + HW_APBH_CTRL0_CLR);
+
+ mxs_dma_apbh.pdev = pdev;
+ mxs_dma_apbh.chan_base = plat->chan_base;
+ mxs_dma_apbh.chan_num = plat->chan_num;
+ platform_set_drvdata(pdev, &mxs_dma_apbh);
+ return mxs_dma_device_register(&mxs_dma_apbh);
+}
+
+static int __devexit dma_apbh_remove(struct platform_device *pdev)
+{
+ iounmap(mxs_dma_apbh.base);
+ return 0;
+}
+
+static struct platform_driver dma_apbh_driver = {
+ .probe = dma_apbh_probe,
+ .remove = __devexit_p(dma_apbh_remove),
+ .driver = {
+ .name = "mxs-dma-apbh"},
+};
+
+static int __init mxs_dma_apbh_init(void)
+{
+ return platform_driver_register(&dma_apbh_driver);
+}
+
+fs_initcall(mxs_dma_apbh_init);
diff --git a/arch/arm/mach-mx5/dma-apbh.h b/arch/arm/mach-mx5/dma-apbh.h
new file mode 100644
index 000000000000..9d8d1de53ecf
--- /dev/null
+++ b/arch/arm/mach-mx5/dma-apbh.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ASM_ARCH_MACH_DMA_H__
+#define __ASM_ARCH_MACH_DMA_H__
+
+enum {
+ MXS_DMA_CHANNEL_AHB_APBH = 0,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI0 = MXS_DMA_CHANNEL_AHB_APBH,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI2,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI3,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI4,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI5,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI6,
+ MXS_DMA_CHANNEL_AHB_APBH_GPMI7,
+ MXS_DMA_CHANNEL_AHB_APBH_SSP,
+ MXS_MAX_DMA_CHANNELS,
+};
+#endif
diff --git a/arch/arm/mach-mx5/dma.c b/arch/arm/mach-mx5/dma.c
new file mode 100644
index 000000000000..aec79d5a96bb
--- /dev/null
+++ b/arch/arm/mach-mx5/dma.c
@@ -0,0 +1,1724 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/init.h>
+#include <linux/device.h>
+#include <asm/dma.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+#include <mach/mxc_uart.h>
+
+#include "serial.h"
+#include "sdma_script_code_mx51.h"
+#include "sdma_script_code_mx53.h"
+#include "sdma_script_code_mx50.h"
+
+#define MXC_MMC_BUFFER_ACCESS 0x20
+#define MXC_SDHC_MMC_WML 64
+#define MXC_SDHC_SD_WML 256
+#define MXC_SSI_TX0_REG 0x0
+#define MXC_SSI_TX1_REG 0x4
+#define MXC_SSI_RX0_REG 0x8
+#define MXC_SSI_RX1_REG 0xC
+#ifdef CONFIG_MXC_SSI_DUAL_FIFO
+#define MXC_SSI_TXFIFO_WML 0x8
+#define MXC_SSI_RXFIFO_WML 0xC
+#else
+#define MXC_SSI_TXFIFO_WML 0x4
+#define MXC_SSI_RXFIFO_WML 0x6
+#endif
+#define MXC_SPDIF_TXFIFO_WML 0x8
+#define MXC_SPDIF_RXFIFO_WML 0x8
+#define MXC_SPDIF_TX_REG 0x2C
+#define MXC_SPDIF_RX_REG 0x14
+#define MXC_ASRC_FIFO_WML 0x40
+#define MXC_ASRCA_RX_REG 0x60
+#define MXC_ASRCA_TX_REG 0x64
+#define MXC_ASRCB_RX_REG 0x68
+#define MXC_ASRCB_TX_REG 0x6C
+#define MXC_ASRCC_RX_REG 0x70
+#define MXC_ASRCC_TX_REG 0x74
+#define MXC_ESAI_TX_REG 0x00
+#define MXC_ESAI_RX_REG 0x04
+#define MXC_ESAI_FIFO_WML 0x40
+
+typedef struct mxc_sdma_info_entry_s {
+ mxc_dma_device_t device;
+ void *chnl_info;
+} mxc_sdma_info_entry_t;
+
+static mxc_sdma_channel_params_t mxc_sdma_uart1_rx_params = {
+ .chnl_params = {
+ .watermark_level = UART1_UFCR_RXTL,
+ .per_address = UART1_BASE_ADDR,
+ .peripheral_type = UART,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_UART1_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART1_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart1_tx_params = {
+ .chnl_params = {
+ .watermark_level = UART1_UFCR_TXTL,
+ .per_address = UART1_BASE_ADDR + MXC_UARTUTXD,
+ .peripheral_type = UART,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_UART1_TX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART1_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart2_rx_params = {
+ .chnl_params = {
+ .watermark_level = UART2_UFCR_RXTL,
+ .per_address = UART2_BASE_ADDR,
+ .peripheral_type = UART,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_UART2_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART2_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart2_tx_params = {
+ .chnl_params = {
+ .watermark_level = UART2_UFCR_TXTL,
+ .per_address = UART2_BASE_ADDR + MXC_UARTUTXD,
+ .peripheral_type = UART,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_UART2_TX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART2_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart3_rx_params = {
+ .chnl_params = {
+ .watermark_level = UART3_UFCR_RXTL,
+ .per_address = UART3_BASE_ADDR,
+ .peripheral_type = UART_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_UART3_RX_MX51,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART3_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart3_tx_params = {
+ .chnl_params = {
+ .watermark_level = UART3_UFCR_TXTL,
+ .per_address = UART3_BASE_ADDR + MXC_UARTUTXD,
+ .peripheral_type = UART_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_UART3_TX_MX51,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART3_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart4_rx_params = {
+ .chnl_params = {
+ .watermark_level = UART4_UFCR_RXTL,
+ .per_address = UART4_BASE_ADDR,
+ .peripheral_type = UART,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ATA_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART4_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart4_tx_params = {
+ .chnl_params = {
+ .watermark_level = UART4_UFCR_TXTL,
+ .per_address = UART4_BASE_ADDR + MXC_UARTUTXD,
+ .peripheral_type = UART,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_ATA_TX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART4_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart5_rx_params = {
+ .chnl_params = {
+ .watermark_level = UART5_UFCR_RXTL,
+ .per_address = UART5_BASE_ADDR,
+ .peripheral_type = UART,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_UART5_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART5_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_uart5_tx_params = {
+ .chnl_params = {
+ .watermark_level = UART5_UFCR_TXTL,
+ .per_address = UART5_BASE_ADDR + MXC_UARTUTXD,
+ .peripheral_type = UART,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_UART5_TX,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_UART5_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_mmc1_width1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SDHC_MMC_WML,
+ .per_address =
+ MMC_SDHC1_BASE_ADDR + MXC_MMC_BUFFER_ACCESS,
+ .peripheral_type = MMC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SDHC1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_MMC1,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_mmc1_width4_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SDHC_SD_WML,
+ .per_address =
+ MMC_SDHC1_BASE_ADDR + MXC_MMC_BUFFER_ACCESS,
+ .peripheral_type = MMC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SDHC1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_MMC1,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_mmc2_width1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SDHC_MMC_WML,
+ .per_address =
+ MMC_SDHC2_BASE_ADDR + MXC_MMC_BUFFER_ACCESS,
+ .peripheral_type = MMC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SDHC2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_MMC2,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_mmc2_width4_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SDHC_SD_WML,
+ .per_address =
+ MMC_SDHC2_BASE_ADDR + MXC_MMC_BUFFER_ACCESS,
+ .peripheral_type = MMC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SDHC2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_MMC2,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML,
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI1_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML,
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI1_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI1_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI1_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI1_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI1_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML,
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI1_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML,
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI1_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI1_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI1_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI1_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI1_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML,
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI2_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML,
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI2_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI2_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI2_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI2_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI2_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML,
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI2_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML,
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI2_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI2_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI2_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI2_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI_SP,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI2_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_8bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML,
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI3_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_8bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML,
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI3_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_16bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI3_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_16bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI3_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_24bit_rx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_RX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI3_RX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_24bit_tx0_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI3_TX1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_8bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML,
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI3_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_8bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML,
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI3_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_8BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_16bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI3_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_16bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u16)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI3_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_24bit_rx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_RXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_RX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SSI3_RX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_RX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ssi3_24bit_tx1_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SSI_TXFIFO_WML * (sizeof(u32)),
+ .per_address = SSI3_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = SSI,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SSI3_TX2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SSI3_TX,
+ .chnl_priority = 2,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_memory_params = {
+ .chnl_params = {
+ .peripheral_type = MEMORY,
+ .transfer_type = emi_2_emi,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_MEMORY,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ata_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_IDE_DMA_WATERMARK,
+ .per_address = ATA_DMA_BASE_ADDR,
+ .peripheral_type = ATA,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ATA_TX_END,
+ .event_id2 = DMA_REQ_ATA_RX,
+ .bd_number = MXC_IDE_DMA_BD_NR,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ATA_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_ata_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_IDE_DMA_WATERMARK,
+ .per_address = ATA_DMA_BASE_ADDR + 0x18,
+ .peripheral_type = ATA,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_ATA_TX_END,
+ .event_id2 = DMA_REQ_ATA_TX,
+ .bd_number = MXC_IDE_DMA_BD_NR,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ATA_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_spdif_16bit_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SPDIF_TXFIFO_WML,
+ .per_address = SPDIF_BASE_ADDR + MXC_SPDIF_TX_REG,
+ .peripheral_type = SPDIF,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SPDIF_MX51,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SPDIF_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_spdif_32bit_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SPDIF_TXFIFO_WML,
+ .per_address = SPDIF_BASE_ADDR + MXC_SPDIF_TX_REG,
+ .peripheral_type = SPDIF,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_SPDIF_MX51,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SPDIF_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_spdif_32bit_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_SPDIF_RXFIFO_WML,
+ .per_address = SPDIF_BASE_ADDR + MXC_SPDIF_RX_REG,
+ .peripheral_type = SPDIF,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_SPDIF_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_SPDIF_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_asrca_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ASRC_FIFO_WML,
+ .per_address = ASRC_BASE_ADDR + MXC_ASRCA_RX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_ASRC_DMA1,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_asrca_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ASRC_FIFO_WML,
+ .per_address = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ASRC_DMA4,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_asrcb_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ASRC_FIFO_WML,
+ .per_address = ASRC_BASE_ADDR + MXC_ASRCB_RX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_ASRC_DMA2,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_asrcb_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ASRC_FIFO_WML,
+ .per_address = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ASRC_DMA5,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_asrcc_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ASRC_FIFO_WML * 3,
+ .per_address = ASRC_BASE_ADDR + MXC_ASRCC_RX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = emi_2_per,
+ .event_id = DMA_REQ_ASRC_DMA3,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCC_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_asrcc_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ASRC_FIFO_WML * 3,
+ .per_address = ASRC_BASE_ADDR + MXC_ASRCC_TX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ASRC_DMA6,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCC_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi1_tx0_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI1_TX1,
+ .event_id2 = DMA_REQ_ASRC_DMA4,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI1_TX0,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi1_tx1_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI1_TX2,
+ .event_id2 = DMA_REQ_ASRC_DMA4,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI1_TX1,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi2_tx0_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI2_TX1,
+ .event_id2 = DMA_REQ_ASRC_DMA4,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI2_TX0,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_ssi2_tx1_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI2_TX2,
+ .event_id2 = DMA_REQ_ASRC_DMA4,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_SSI2_TX1,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi1_tx0_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI1_TX1,
+ .event_id2 = DMA_REQ_ASRC_DMA5,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI1_TX0,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi1_tx1_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI1_TX2,
+ .event_id2 = DMA_REQ_ASRC_DMA5,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI1_TX1,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi2_tx0_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI2_TX1,
+ .event_id2 = DMA_REQ_ASRC_DMA5,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI2_TX0,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_ssi2_tx1_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_SSI2_TX2,
+ .event_id2 = DMA_REQ_ASRC_DMA5,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_SSI_TXFIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_SSI2_TX1,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrca_esai_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_ESAI_TX,
+ .event_id2 = DMA_REQ_ASRC_DMA4,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_ESAI_FIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCA_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCA_ESAI,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrcb_esai_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_ESAI_TX,
+ .event_id2 = DMA_REQ_ASRC_DMA5,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_ESAI_FIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCB_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCB_ESAI,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_ext_params_t mxc_sdma_asrcc_esai_params = {
+ .chnl_ext_params = {
+ .common = {
+ .watermark_level =
+ MXC_ASRC_FIFO_WML >> 1,
+ .per_address =
+ ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
+ .peripheral_type = ASRC,
+ .transfer_type = per_2_per,
+ .event_id = DMA_REQ_ESAI_TX,
+ .event_id2 = DMA_REQ_ASRC_DMA6,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ .ext = 1,
+ },
+ .p2p_dir = 0,
+ .info_bits =
+ SDMA_ASRC_P2P_INFO_CONT | SDMA_ASRC_P2P_INFO_SP |
+ SDMA_ASRC_P2P_INFO_DP,
+ .watermark_level2 = MXC_ASRC_FIFO_WML,
+ .per_address2 = ASRC_BASE_ADDR + MXC_ASRCC_TX_REG,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ASRCC_ESAI,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_esai_16bit_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ESAI_FIFO_WML,
+ .per_address = ESAI_BASE_ADDR + MXC_ESAI_RX_REG,
+ .peripheral_type = ESAI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ESAI_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ESAI_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_esai_16bit_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ESAI_FIFO_WML,
+ .per_address = ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
+ .peripheral_type = ESAI,
+ .transfer_type = int_2_per,
+ .event_id = DMA_REQ_ESAI_TX,
+ .bd_number = 32,
+ .word_size = TRANSFER_16BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ESAI_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_esai_24bit_rx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ESAI_FIFO_WML,
+ .per_address = ESAI_BASE_ADDR + MXC_ESAI_RX_REG,
+ .peripheral_type = ESAI,
+ .transfer_type = per_2_emi,
+ .event_id = DMA_REQ_ESAI_RX,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ESAI_RX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_channel_params_t mxc_sdma_esai_24bit_tx_params = {
+ .chnl_params = {
+ .watermark_level = MXC_ESAI_FIFO_WML,
+ .per_address = ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
+ .peripheral_type = ESAI,
+ .transfer_type = int_2_per,
+ .event_id = DMA_REQ_ESAI_TX,
+ .bd_number = 32,
+ .word_size = TRANSFER_32BIT,
+ },
+ .channel_num = MXC_DMA_CHANNEL_ESAI_TX,
+ .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
+};
+
+static mxc_sdma_info_entry_t mxc_sdma_active_dma_info[] = {
+ {MXC_DMA_UART1_RX, &mxc_sdma_uart1_rx_params},
+ {MXC_DMA_UART1_TX, &mxc_sdma_uart1_tx_params},
+ {MXC_DMA_UART2_RX, &mxc_sdma_uart2_rx_params},
+ {MXC_DMA_UART2_TX, &mxc_sdma_uart2_tx_params},
+ {MXC_DMA_UART3_RX, &mxc_sdma_uart3_rx_params},
+ {MXC_DMA_UART3_TX, &mxc_sdma_uart3_tx_params},
+ {MXC_DMA_UART4_RX, &mxc_sdma_uart4_rx_params},
+ {MXC_DMA_UART4_TX, &mxc_sdma_uart4_tx_params},
+ {MXC_DMA_UART5_RX, &mxc_sdma_uart5_rx_params},
+ {MXC_DMA_UART5_TX, &mxc_sdma_uart5_tx_params},
+ {MXC_DMA_MMC1_WIDTH_1, &mxc_sdma_mmc1_width1_params},
+ {MXC_DMA_MMC1_WIDTH_4, &mxc_sdma_mmc1_width4_params},
+ {MXC_DMA_MMC2_WIDTH_1, &mxc_sdma_mmc2_width1_params},
+ {MXC_DMA_MMC2_WIDTH_4, &mxc_sdma_mmc2_width4_params},
+ {MXC_DMA_SSI1_8BIT_RX0, &mxc_sdma_ssi1_8bit_rx0_params},
+ {MXC_DMA_SSI1_8BIT_TX0, &mxc_sdma_ssi1_8bit_tx0_params},
+ {MXC_DMA_SSI1_16BIT_RX0, &mxc_sdma_ssi1_16bit_rx0_params},
+ {MXC_DMA_SSI1_16BIT_TX0, &mxc_sdma_ssi1_16bit_tx0_params},
+ {MXC_DMA_SSI1_24BIT_RX0, &mxc_sdma_ssi1_24bit_rx0_params},
+ {MXC_DMA_SSI1_24BIT_TX0, &mxc_sdma_ssi1_24bit_tx0_params},
+ {MXC_DMA_SSI1_8BIT_RX1, &mxc_sdma_ssi1_8bit_rx1_params},
+ {MXC_DMA_SSI1_8BIT_TX1, &mxc_sdma_ssi1_8bit_tx1_params},
+ {MXC_DMA_SSI1_16BIT_RX1, &mxc_sdma_ssi1_16bit_rx1_params},
+ {MXC_DMA_SSI1_16BIT_TX1, &mxc_sdma_ssi1_16bit_tx1_params},
+ {MXC_DMA_SSI1_24BIT_RX1, &mxc_sdma_ssi1_24bit_rx1_params},
+ {MXC_DMA_SSI1_24BIT_TX1, &mxc_sdma_ssi1_24bit_tx1_params},
+ {MXC_DMA_SSI2_8BIT_RX0, &mxc_sdma_ssi2_8bit_rx0_params},
+ {MXC_DMA_SSI2_8BIT_TX0, &mxc_sdma_ssi2_8bit_tx0_params},
+ {MXC_DMA_SSI2_16BIT_RX0, &mxc_sdma_ssi2_16bit_rx0_params},
+ {MXC_DMA_SSI2_16BIT_TX0, &mxc_sdma_ssi2_16bit_tx0_params},
+ {MXC_DMA_SSI2_24BIT_RX0, &mxc_sdma_ssi2_24bit_rx0_params},
+ {MXC_DMA_SSI2_24BIT_TX0, &mxc_sdma_ssi2_24bit_tx0_params},
+ {MXC_DMA_SSI2_8BIT_RX1, &mxc_sdma_ssi2_8bit_rx1_params},
+ {MXC_DMA_SSI2_8BIT_TX1, &mxc_sdma_ssi2_8bit_tx1_params},
+ {MXC_DMA_SSI2_16BIT_RX1, &mxc_sdma_ssi2_16bit_rx1_params},
+ {MXC_DMA_SSI2_16BIT_TX1, &mxc_sdma_ssi2_16bit_tx1_params},
+ {MXC_DMA_SSI2_24BIT_RX1, &mxc_sdma_ssi2_24bit_rx1_params},
+ {MXC_DMA_SSI2_24BIT_TX1, &mxc_sdma_ssi2_24bit_tx1_params},
+ {MXC_DMA_SSI3_8BIT_RX0, &mxc_sdma_ssi3_8bit_rx0_params},
+ {MXC_DMA_SSI3_8BIT_TX0, &mxc_sdma_ssi3_8bit_tx0_params},
+ {MXC_DMA_SSI3_16BIT_RX0, &mxc_sdma_ssi3_16bit_rx0_params},
+ {MXC_DMA_SSI3_16BIT_TX0, &mxc_sdma_ssi3_16bit_tx0_params},
+ {MXC_DMA_SSI3_24BIT_RX0, &mxc_sdma_ssi3_24bit_rx0_params},
+ {MXC_DMA_SSI3_24BIT_TX0, &mxc_sdma_ssi3_24bit_tx0_params},
+ {MXC_DMA_SSI3_8BIT_RX1, &mxc_sdma_ssi3_8bit_rx1_params},
+ {MXC_DMA_SSI3_8BIT_TX1, &mxc_sdma_ssi3_8bit_tx1_params},
+ {MXC_DMA_SSI3_16BIT_RX1, &mxc_sdma_ssi3_16bit_rx1_params},
+ {MXC_DMA_SSI3_16BIT_TX1, &mxc_sdma_ssi3_16bit_tx1_params},
+ {MXC_DMA_SSI3_24BIT_RX1, &mxc_sdma_ssi3_24bit_rx1_params},
+ {MXC_DMA_SSI3_24BIT_TX1, &mxc_sdma_ssi3_24bit_tx1_params},
+ {MXC_DMA_MEMORY, &mxc_sdma_memory_params},
+ {MXC_DMA_ATA_RX, &mxc_sdma_ata_rx_params},
+ {MXC_DMA_ATA_TX, &mxc_sdma_ata_tx_params},
+ {MXC_DMA_SPDIF_16BIT_TX, &mxc_sdma_spdif_16bit_tx_params},
+ {MXC_DMA_SPDIF_32BIT_TX, &mxc_sdma_spdif_32bit_tx_params},
+ {MXC_DMA_SPDIF_32BIT_RX, &mxc_sdma_spdif_32bit_rx_params},
+ {MXC_DMA_ASRC_A_RX, &mxc_sdma_asrca_rx_params},
+ {MXC_DMA_ASRC_A_TX, &mxc_sdma_asrca_tx_params},
+ {MXC_DMA_ASRC_B_RX, &mxc_sdma_asrcb_rx_params},
+ {MXC_DMA_ASRC_B_TX, &mxc_sdma_asrcb_tx_params},
+ {MXC_DMA_ASRC_C_RX, &mxc_sdma_asrcc_rx_params},
+ {MXC_DMA_ASRC_C_TX, &mxc_sdma_asrcc_tx_params},
+ {MXC_DMA_ASRCA_SSI1_TX0, &mxc_sdma_asrca_ssi1_tx0_params},
+ {MXC_DMA_ASRCA_SSI1_TX1, &mxc_sdma_asrca_ssi1_tx1_params},
+ {MXC_DMA_ASRCA_SSI2_TX0, &mxc_sdma_asrca_ssi2_tx0_params},
+ {MXC_DMA_ASRCA_SSI2_TX1, &mxc_sdma_asrca_ssi2_tx1_params},
+ {MXC_DMA_ASRCB_SSI1_TX0, &mxc_sdma_asrcb_ssi1_tx0_params},
+ {MXC_DMA_ASRCB_SSI1_TX1, &mxc_sdma_asrcb_ssi1_tx1_params},
+ {MXC_DMA_ASRCB_SSI2_TX0, &mxc_sdma_asrcb_ssi2_tx0_params},
+ {MXC_DMA_ASRCB_SSI2_TX1, &mxc_sdma_asrcb_ssi2_tx1_params},
+ {MXC_DMA_ASRCA_ESAI, &mxc_sdma_asrca_esai_params},
+ {MXC_DMA_ASRCB_ESAI, &mxc_sdma_asrcb_esai_params},
+ {MXC_DMA_ASRCC_ESAI, &mxc_sdma_asrcc_esai_params},
+ {MXC_DMA_ESAI_16BIT_RX, &mxc_sdma_esai_16bit_rx_params},
+ {MXC_DMA_ESAI_16BIT_TX, &mxc_sdma_esai_16bit_tx_params},
+ {MXC_DMA_ESAI_24BIT_RX, &mxc_sdma_esai_24bit_rx_params},
+ {MXC_DMA_ESAI_24BIT_TX, &mxc_sdma_esai_24bit_tx_params},
+};
+
+static int mxc_sdma_info_entrys =
+ sizeof(mxc_sdma_active_dma_info) / sizeof(mxc_sdma_active_dma_info[0]);
+
+static int __init dma_fixups(void)
+{
+ mxc_sdma_info_entry_t *p = mxc_sdma_active_dma_info;
+ int i;
+ dma_channel_ext_params *params;
+
+ if (cpu_is_mx51())
+ return 0;
+
+ for (i = 0; i < mxc_sdma_info_entrys; i++, p++) {
+ params = &(((mxc_sdma_channel_ext_params_t *)p->chnl_info)->chnl_ext_params);
+ params->common.per_address -= 0x20000000;
+ if (params->common.ext)
+ params->per_address2 -= 0x20000000;
+ }
+
+ mxc_sdma_uart2_rx_params.chnl_params.event_id = DMA_REQ_FIRI_RX;
+ mxc_sdma_uart2_tx_params.chnl_params.event_id = DMA_REQ_FIRI_TX;
+ mxc_sdma_uart3_rx_params.chnl_params.event_id = DMA_REQ_UART3_RX_MX53;
+ mxc_sdma_uart3_tx_params.chnl_params.event_id = DMA_REQ_UART3_TX_MX53;
+ mxc_sdma_spdif_16bit_tx_params.chnl_params.event_id = DMA_REQ_SPDIF_TX;
+ mxc_sdma_spdif_32bit_tx_params.chnl_params.event_id = DMA_REQ_SPDIF_TX;
+
+ if (cpu_is_mx53()) {
+ mxc_sdma_ssi3_8bit_tx1_params.chnl_params.event_id =
+ DMA_REQ_SSI3_TX2_MX53;
+ mxc_sdma_ssi3_16bit_tx1_params.chnl_params.event_id =
+ DMA_REQ_SSI3_TX2_MX53;
+ mxc_sdma_ssi3_24bit_tx1_params.chnl_params.event_id =
+ DMA_REQ_SSI3_TX2_MX53;
+ } else if (cpu_is_mx50()) {
+ /* mx50 not support double fifo */
+#ifdef CONFIG_MXC_SSI_DUAL_FIFO
+ u32 tx_wm = MXC_SSI_TXFIFO_WML/2;
+ u32 rx_wm = MXC_SSI_RXFIFO_WML/2;
+#else
+ u32 tx_wm = MXC_SSI_TXFIFO_WML;
+ u32 rx_wm = MXC_SSI_RXFIFO_WML;
+#endif
+ mxc_sdma_ssi1_8bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi1_8bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi1_16bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi1_16bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi1_24bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi1_24bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi1_8bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi1_8bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi1_16bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi1_16bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi1_24bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi1_24bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi2_8bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi2_8bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi2_16bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi2_16bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi2_24bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi2_24bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi2_8bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi2_8bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi2_16bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi2_16bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi2_24bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi2_24bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi3_8bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi3_8bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi3_16bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi3_16bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi3_24bit_tx0_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi3_24bit_rx0_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi3_8bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi3_8bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi3_16bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi3_16bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ mxc_sdma_ssi3_24bit_tx1_params.chnl_params.watermark_level =
+ tx_wm;
+ mxc_sdma_ssi3_24bit_rx1_params.chnl_params.watermark_level =
+ rx_wm;
+ }
+ return 0;
+}
+arch_initcall(dma_fixups);
+
+/*!
+ * 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)
+{
+ mxc_sdma_info_entry_t *p = mxc_sdma_active_dma_info;
+ int i;
+
+ for (i = 0; i < mxc_sdma_info_entrys; i++, p++) {
+ if (p->device == channel_id)
+ return p->chnl_info;
+
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(mxc_sdma_get_channel_params);
+
+/*!
+ * 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)
+{
+#ifdef CONFIG_SDMA_IRAM
+ int i;
+ for (i = MXC_DMA_CHANNEL_IRAM; i < MAX_DMA_CHANNELS; i++)
+ chnl[i].dynamic = 0;
+#endif
+}
+EXPORT_SYMBOL(mxc_get_static_channels);
+
+static void __init mx51_sdma_get_script_info(sdma_script_start_addrs *sdma_script_addr)
+{
+ /* AP<->BP */
+ sdma_script_addr->mxc_sdma_ap_2_ap_addr = ap_2_ap_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_ap_2_bp_addr = -1;
+ sdma_script_addr->mxc_sdma_bp_2_ap_addr = -1;
+ sdma_script_addr->mxc_sdma_ap_2_ap_fixed_addr = -1;
+
+ /*misc */
+ sdma_script_addr->mxc_sdma_loopback_on_dsp_side_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1;
+
+ /* firi */
+ sdma_script_addr->mxc_sdma_firi_2_per_addr = -1;
+ sdma_script_addr->mxc_sdma_firi_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_per_2_firi_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_firi_addr = -1;
+
+ /* uart */
+ sdma_script_addr->mxc_sdma_uart_2_per_addr = uart_2_per_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_uart_2_mcu_addr = uart_2_mcu_ADDR_MX51;
+
+ /* UART SH */
+ sdma_script_addr->mxc_sdma_uartsh_2_per_addr = uartsh_2_per_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_uartsh_2_mcu_addr = uartsh_2_mcu_ADDR_MX51;
+
+ /* SHP */
+ sdma_script_addr->mxc_sdma_per_2_shp_addr = per_2_shp_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_shp_2_per_addr = shp_2_per_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR_MX51;
+
+ /* ATA */
+ sdma_script_addr->mxc_sdma_mcu_2_ata_addr = mcu_2_ata_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_ata_2_mcu_addr = ata_2_mcu_ADDR_MX51;
+
+ /* app */
+ sdma_script_addr->mxc_sdma_app_2_per_addr = app_2_per_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_app_2_mcu_addr = app_2_mcu_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_per_2_app_addr = per_2_app_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_mcu_2_app_addr = mcu_2_app_ADDR_MX51;
+
+ /* MSHC */
+ sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1;
+
+ /* spdif */
+ sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = mcu_2_spdif_ADDR_MX51;
+
+ /* IPU */
+ sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr =
+ ext_mem__ipu_ram_ADDR_MX51;
+
+ /* DVFS */
+ sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1;
+
+ /* SSI */
+#ifdef CONFIG_MXC_SSI_DUAL_FIFO
+ sdma_script_addr->mxc_sdma_mcu_2_ssiapp_addr = mcu_2_ssiapp_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_ssiapp_2_mcu_addr = ssiapp_2_mcu_ADDR_MX51;
+
+ sdma_script_addr->mxc_sdma_mcu_2_ssish_addr = mcu_2_ssish_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_ssish_2_mcu_addr = ssish_2_mcu_ADDR_MX51;
+#endif
+
+ /* core */
+ sdma_script_addr->mxc_sdma_start_addr =
+ (unsigned short *)sdma_code_mx51;
+ sdma_script_addr->mxc_sdma_ram_code_start_addr =
+ RAM_CODE_START_ADDR_MX51;
+ sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE_MX51;
+}
+
+static void __init mx53_sdma_get_script_info(sdma_script_start_addrs *sdma_script_addr)
+{
+ /* AP<->BP */
+ sdma_script_addr->mxc_sdma_ap_2_ap_addr = ap_2_ap_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_ap_2_bp_addr = -1;
+ sdma_script_addr->mxc_sdma_bp_2_ap_addr = -1;
+ sdma_script_addr->mxc_sdma_ap_2_ap_fixed_addr = -1;
+
+ /*misc */
+ sdma_script_addr->mxc_sdma_loopback_on_dsp_side_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1;
+
+ /* firi */
+ sdma_script_addr->mxc_sdma_firi_2_per_addr = firi_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_firi_2_mcu_addr = firi_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_per_2_firi_addr = mcu_2_firi_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_mcu_2_firi_addr = mcu_2_firi_ADDR_MX53;
+
+ /* uart */
+ sdma_script_addr->mxc_sdma_uart_2_per_addr = uart_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_uart_2_mcu_addr = uart_2_mcu_ADDR_MX53;
+
+ /* UART SH */
+ sdma_script_addr->mxc_sdma_uartsh_2_per_addr = uartsh_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_uartsh_2_mcu_addr = uartsh_2_mcu_ADDR_MX53;
+
+ /* SHP */
+ sdma_script_addr->mxc_sdma_per_2_shp_addr = mcu_2_shp_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_shp_2_per_addr = shp_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR_MX53;
+
+ /* ATA use it's own DMA */
+ sdma_script_addr->mxc_sdma_mcu_2_ata_addr = -1;
+ sdma_script_addr->mxc_sdma_ata_2_mcu_addr = -1;
+
+ /* app */
+ sdma_script_addr->mxc_sdma_app_2_per_addr = app_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_app_2_mcu_addr = app_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_per_2_app_addr = mcu_2_app_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_mcu_2_app_addr = mcu_2_app_ADDR_MX53;
+
+ /* MSHC */
+ sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1;
+
+ /* spdif */
+ sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = spdif_2_mcu_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = mcu_2_spdif_ADDR_MX53;
+
+ /* asrc script address change to use shp_2_mcu since v01.01 */
+ sdma_script_addr->mxc_sdma_asrc_2_mcu_addr = shp_2_mcu_ADDR_MX53;
+
+ /* IPU */
+ sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr = mcu_2_app_ADDR_MX53;
+
+ /* DVFS */
+ sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1;
+
+ /* SSI */
+#ifdef CONFIG_MXC_SSI_DUAL_FIFO
+ sdma_script_addr->mxc_sdma_mcu_2_ssiapp_addr = mcu_2_ssiapp_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_ssiapp_2_mcu_addr = ssiapp_2_mcu_ADDR_MX53;
+
+ sdma_script_addr->mxc_sdma_mcu_2_ssish_addr = mcu_2_ssish_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_ssish_2_mcu_addr = ssish_2_mcu_ADDR_MX53;
+#endif
+
+ /* core */
+ sdma_script_addr->mxc_sdma_start_addr = (unsigned short *)sdma_code_mx53;
+ sdma_script_addr->mxc_sdma_ram_code_start_addr = RAM_CODE_START_ADDR_MX53;
+ sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE_MX53;
+}
+
+static void __init mx50_sdma_get_script_info(sdma_script_start_addrs *sdma_script_addr)
+{
+ /* AP<->BP */
+ sdma_script_addr->mxc_sdma_ap_2_ap_addr = ap_2_ap_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_ap_2_bp_addr = -1;
+ sdma_script_addr->mxc_sdma_bp_2_ap_addr = -1;
+ sdma_script_addr->mxc_sdma_ap_2_ap_fixed_addr = -1;
+
+ /*misc */
+ sdma_script_addr->mxc_sdma_loopback_on_dsp_side_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1;
+
+ /* firi */
+ sdma_script_addr->mxc_sdma_firi_2_per_addr = -1;
+ sdma_script_addr->mxc_sdma_firi_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_per_2_firi_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_firi_addr = -1;
+
+ /* uart */
+ sdma_script_addr->mxc_sdma_uart_2_per_addr = uart_2_mcu_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_uart_2_mcu_addr = uart_2_mcu_ADDR_MX50;
+
+ /* UART SH */
+ sdma_script_addr->mxc_sdma_uartsh_2_per_addr = uartsh_2_mcu_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_uartsh_2_mcu_addr = uartsh_2_mcu_ADDR_MX50;
+
+ /* SHP */
+ sdma_script_addr->mxc_sdma_per_2_shp_addr = mcu_2_shp_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_shp_2_per_addr = shp_2_mcu_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR_MX50;
+
+ /* ATA use it's own DMA */
+ sdma_script_addr->mxc_sdma_mcu_2_ata_addr = -1;
+ sdma_script_addr->mxc_sdma_ata_2_mcu_addr = -1;
+
+ /* app */
+ sdma_script_addr->mxc_sdma_app_2_per_addr = app_2_mcu_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_app_2_mcu_addr = app_2_mcu_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_per_2_app_addr = mcu_2_app_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_mcu_2_app_addr = mcu_2_app_ADDR_MX50;
+
+ /* MSHC */
+ sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1;
+
+ /* spdif */
+ sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = -1;
+ sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = -1;
+
+ sdma_script_addr->mxc_sdma_asrc_2_mcu_addr = -1;
+
+ /* IPU */
+ sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr = -1;
+
+ /* DVFS */
+ sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1;
+
+ /* core */
+ sdma_script_addr->mxc_sdma_start_addr = (unsigned short *)sdma_code_mx50;
+ sdma_script_addr->mxc_sdma_ram_code_start_addr = RAM_CODE_START_ADDR_MX50;
+ sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE_MX50;
+}
+
+void __init mxc_sdma_get_script_info(sdma_script_start_addrs *sdma_script_addr)
+{
+ if (cpu_is_mx51())
+ mx51_sdma_get_script_info(sdma_script_addr);
+ else if (cpu_is_mx53())
+ mx53_sdma_get_script_info(sdma_script_addr);
+ else
+ mx50_sdma_get_script_info(sdma_script_addr);
+}
+
diff --git a/arch/arm/mach-mx5/dmaengine.c b/arch/arm/mach-mx5/dmaengine.c
new file mode 100644
index 000000000000..e92d9b9202e8
--- /dev/null
+++ b/arch/arm/mach-mx5/dmaengine.c
@@ -0,0 +1,682 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <mach/dmaengine.h>
+
+#include "dma-apbh.h"
+
+static void *mxs_dma_pool;
+static int mxs_dma_alignment = MXS_DMA_ALIGNMENT;
+
+/*
+ * The mutex that arbitrates access to the array of structures that represent
+ * all the DMA channels in the system (see mxs_dma_channels, below).
+ */
+
+static DEFINE_MUTEX(mxs_dma_mutex);
+
+/*
+ * The list of DMA drivers that manage various DMA channels. A DMA device
+ * driver registers to manage DMA channels by calling mxs_dma_device_register().
+ */
+
+static LIST_HEAD(mxs_dma_devices);
+
+/*
+ * The array of struct mxs_dma_chan that represent every DMA channel in the
+ * system. The index of the structure in the array indicates the specific DMA
+ * hardware it represents (see mach-mx28/include/mach/dma.h).
+ */
+
+static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS];
+
+int mxs_dma_request(int channel, struct device *dev, const char *name)
+{
+ int ret = 0;
+ struct mxs_dma_chan *pchan;
+
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+
+ if (!dev || !name)
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ mutex_lock(&mxs_dma_mutex);
+ if ((pchan->flags & MXS_DMA_FLAGS_VALID) != MXS_DMA_FLAGS_VALID) {
+ ret = -ENODEV;
+ goto out;
+ }
+ if (pchan->flags & MXS_DMA_FLAGS_ALLOCATED) {
+ ret = -EBUSY;
+ goto out;
+ }
+ pchan->flags |= MXS_DMA_FLAGS_ALLOCATED;
+ pchan->name = name;
+ pchan->dev = (unsigned long)dev;
+ pchan->active_num = 0;
+ pchan->pending_num = 0;
+ spin_lock_init(&pchan->lock);
+ INIT_LIST_HEAD(&pchan->active);
+ INIT_LIST_HEAD(&pchan->done);
+out:
+ mutex_unlock(&mxs_dma_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_request);
+
+void mxs_dma_release(int channel, struct device *dev)
+{
+ struct mxs_dma_chan *pchan;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+ return;
+
+ if (pchan->dev != (unsigned long)dev)
+ return;
+
+ mutex_lock(&mxs_dma_mutex);
+ pchan->dev = 0;
+ pchan->active_num = 0;
+ pchan->pending_num = 0;
+ pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED;
+ mutex_unlock(&mxs_dma_mutex);
+}
+EXPORT_SYMBOL(mxs_dma_release);
+
+int mxs_dma_enable(int channel)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pchan->pending_num && pdma->enable)
+ ret = pdma->enable(pchan, channel - pdma->chan_base);
+ pchan->flags |= MXS_DMA_FLAGS_BUSY;
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_enable);
+
+void mxs_dma_disable(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ if (!(pchan->flags & MXS_DMA_FLAGS_BUSY))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->disable)
+ pdma->disable(pchan, channel - pdma->chan_base);
+ pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+ pchan->active_num = 0;
+ pchan->pending_num = 0;
+ list_splice_init(&pchan->active, &pchan->done);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_disable);
+
+int mxs_dma_get_info(int channel, struct mxs_dma_info *info)
+{
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+#ifdef DUMPING_DMA_ALL
+ struct list_head *pos;
+ int value, i, offset;
+#endif
+
+ if (!info)
+ return -EINVAL;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EFAULT;
+ pdma = pchan->dma;
+ if (pdma->info)
+ pdma->info(pdma, channel - pdma->chan_base, info);
+
+#ifdef DUMPING_DMA_ALL
+ printk(KERN_INFO "\n[ %s ] channel : %d ,active : %d, pending : %d\n",
+ __func__, channel, pchan->active_num, pchan->pending_num);
+
+ for (i = 0; i < 6; i++) {
+ offset = i * 0x10 + channel * 0x70;
+ value = __raw_readl(pdma->base + offset);
+ printk(KERN_INFO "[ %s ] offset : 0x%.3x -- 0x%.8x\n",
+ __func__, offset, value);
+ }
+ for (i = 0; i < 7; i++) {
+ offset = 0x100 + i * 0x10 + channel * 0x70;
+ value = __raw_readl(pdma->base + offset);
+ printk(KERN_INFO "[ %s ] offset : 0x%.3x -- 0x%.8x\n",
+ __func__, offset, value);
+ }
+
+ offset = 0;
+ list_for_each(pos, &pchan->active) {
+ struct mxs_dma_desc *pdesc;
+
+ pdesc = list_entry(pos, struct mxs_dma_desc, node);
+ printk(KERN_INFO "========================================\n");
+ printk(KERN_INFO "The whole chain of CMD %d is :\n"
+ "\tNEXT_COMMAND_ADDRESS : 0x%.8lx\n"
+ "\tCMD : 0x%.8lx\n"
+ "\tDMA Buffer : 0x%.8x\n"
+ "\taddress : 0x%.8x\n",
+ offset++,
+ pdesc->cmd.next,
+ pdesc->cmd.cmd.data,
+ (int)pdesc->cmd.address,
+ (int)pdesc->address);
+
+ for (i = 0; i < pdesc->cmd.cmd.bits.pio_words; i++) {
+ printk(KERN_INFO "PIO WORD [ %d ] --> 0x%.8lx\n",
+ i, pdesc->cmd.pio_words[i]);
+ }
+ printk(KERN_INFO "==================================\n");
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_get_info);
+
+int mxs_dma_cooked(int channel, struct list_head *head)
+{
+ int sem;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct list_head *p, *q;
+ struct mxs_dma_desc *pdesc;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ sem = mxs_dma_read_semaphore(channel);
+ if (sem < 0)
+ return sem;
+ if (sem == pchan->active_num)
+ return 0;
+ BUG_ON(sem > pchan->active_num);
+ spin_lock_irqsave(&pchan->lock, flags);
+ list_for_each_safe(p, q, &pchan->active) {
+ if ((pchan->active_num) <= sem)
+ break;
+ pdesc = list_entry(p, struct mxs_dma_desc, node);
+ pdesc->flags &= ~MXS_DMA_DESC_READY;
+ if (head)
+ list_move_tail(p, head);
+ else
+ list_move_tail(p, &pchan->done);
+ if (pdesc->flags & MXS_DMA_DESC_LAST)
+ pchan->active_num--;
+ }
+ if (sem == 0)
+ pchan->flags &= ~MXS_DMA_FLAGS_BUSY;
+ spin_unlock_irqrestore(&pchan->lock, flags);
+
+ BUG_ON(sem != pchan->active_num);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_cooked);
+
+void mxs_dma_reset(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->reset)
+ pdma->reset(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_reset);
+
+void mxs_dma_freeze(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->freeze)
+ pdma->freeze(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_freeze);
+
+void mxs_dma_unfreeze(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->unfreeze)
+ pdma->unfreeze(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_unfreeze);
+
+int mxs_dma_read_semaphore(int channel)
+{
+ int ret = -EINVAL;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return ret;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return ret;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->read_semaphore)
+ ret = pdma->read_semaphore(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_read_semaphore);
+
+void mxs_dma_enable_irq(int channel, int en)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->enable_irq)
+ pdma->enable_irq(pdma, channel - pdma->chan_base, en);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_enable_irq);
+
+int mxs_dma_irq_is_pending(int channel)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return ret;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return ret;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->irq_is_pending)
+ ret = pdma->irq_is_pending(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_irq_is_pending);
+
+void mxs_dma_ack_irq(int channel)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->ack_irq)
+ pdma->ack_irq(pdma, channel - pdma->chan_base);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_ack_irq);
+
+void mxs_dma_set_target(int channel, int target)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return;
+ if (pchan->flags & MXS_DMA_FLAGS_BUSY)
+ return;
+ pdma = pchan->dma;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (pdma->set_target)
+ pdma->set_target(pdma, channel - pdma->chan_base, target);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+}
+EXPORT_SYMBOL(mxs_dma_set_target);
+
+/* mxs dma utility function */
+struct mxs_dma_desc *mxs_dma_alloc_desc(void)
+{
+ struct mxs_dma_desc *pdesc;
+ unsigned int address;
+ if (mxs_dma_pool == NULL)
+ return NULL;
+
+ pdesc = dma_pool_alloc(mxs_dma_pool, GFP_KERNEL, &address);
+ if (pdesc == NULL)
+ return NULL;
+ memset(pdesc, 0, sizeof(*pdesc));
+ pdesc->address = address;
+ return pdesc;
+};
+EXPORT_SYMBOL(mxs_dma_alloc_desc);
+
+void mxs_dma_free_desc(struct mxs_dma_desc *pdesc)
+{
+ if (pdesc == NULL)
+ return;
+
+ if (mxs_dma_pool == NULL)
+ return;
+
+ dma_pool_free(mxs_dma_pool, pdesc, pdesc->address);
+}
+EXPORT_SYMBOL(mxs_dma_free_desc);
+
+int mxs_dma_desc_append(int channel, struct mxs_dma_desc *pdesc)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_desc *last;
+ struct mxs_dma_device *pdma;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+ pdma = pchan->dma;
+ pdesc->cmd.next = mxs_dma_cmd_address(pdesc);
+ pdesc->flags |= MXS_DMA_DESC_FIRST | MXS_DMA_DESC_LAST;
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (!list_empty(&pchan->active)) {
+
+ last = list_entry(pchan->active.prev,
+ struct mxs_dma_desc, node);
+
+ pdesc->flags &= ~MXS_DMA_DESC_FIRST;
+ last->flags &= ~MXS_DMA_DESC_LAST;
+
+ last->cmd.next = mxs_dma_cmd_address(pdesc);
+ last->cmd.cmd.bits.chain = 1;
+ }
+ pdesc->flags |= MXS_DMA_DESC_READY;
+ if (pdesc->flags & MXS_DMA_DESC_FIRST)
+ pchan->pending_num++;
+ list_add_tail(&pdesc->node, &pchan->active);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_desc_append);
+
+int mxs_dma_desc_add_list(int channel, struct list_head *head)
+{
+ int ret = 0, size = 0;
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ struct mxs_dma_device *pdma;
+ struct list_head *p;
+ struct mxs_dma_desc *prev = NULL, *pcur;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ if (list_empty(head))
+ return 0;
+
+ pdma = pchan->dma;
+ list_for_each(p, head) {
+ pcur = list_entry(p, struct mxs_dma_desc, node);
+ if (!(pcur->cmd.cmd.bits.dec_sem || pcur->cmd.cmd.bits.chain))
+ return -EINVAL;
+ if (prev)
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ else
+ pcur->flags |= MXS_DMA_DESC_FIRST;
+ pcur->flags |= MXS_DMA_DESC_READY;
+ prev = pcur;
+ size++;
+ }
+ pcur = list_first_entry(head, struct mxs_dma_desc, node);
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ prev->flags |= MXS_DMA_DESC_LAST;
+
+ spin_lock_irqsave(&pchan->lock, flags);
+ if (!list_empty(&pchan->active)) {
+ pcur = list_entry(pchan->active.next,
+ struct mxs_dma_desc, node);
+ if (pcur->cmd.cmd.bits.dec_sem != prev->cmd.cmd.bits.dec_sem) {
+ ret = -EFAULT;
+ goto out;
+ }
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ prev = list_entry(pchan->active.prev,
+ struct mxs_dma_desc, node);
+ pcur = list_first_entry(head, struct mxs_dma_desc, node);
+ pcur->flags &= ~MXS_DMA_DESC_FIRST;
+ prev->flags &= ~MXS_DMA_DESC_LAST;
+ prev->cmd.next = mxs_dma_cmd_address(pcur);
+ }
+ list_splice(head, &pchan->active);
+ pchan->pending_num += size;
+ if (!(pcur->cmd.cmd.bits.dec_sem) && (pcur->flags & MXS_DMA_DESC_FIRST))
+ pchan->pending_num += 1;
+ else
+ pchan->pending_num += size;
+out:
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(mxs_dma_desc_add_list);
+
+int mxs_dma_get_cooked(int channel, struct list_head *head)
+{
+ unsigned long flags;
+ struct mxs_dma_chan *pchan;
+ if ((channel < 0) || (channel >= MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+ pchan = mxs_dma_channels + channel;
+ if (!(pchan->flags & MXS_DMA_FLAGS_ALLOCATED))
+ return -EINVAL;
+
+ if (head == NULL)
+ return 0;
+
+ spin_lock_irqsave(&pchan->lock, flags);
+ list_splice(&pchan->done, head);
+ spin_unlock_irqrestore(&pchan->lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_get_cooked);
+
+int mxs_dma_device_register(struct mxs_dma_device *pdev)
+{
+ int i;
+ struct mxs_dma_chan *pchan;
+
+ if (pdev == NULL || !pdev->chan_num)
+ return -EINVAL;
+
+ if ((pdev->chan_base >= MXS_MAX_DMA_CHANNELS) ||
+ ((pdev->chan_base + pdev->chan_num) > MXS_MAX_DMA_CHANNELS))
+ return -EINVAL;
+
+ mutex_lock(&mxs_dma_mutex);
+ pchan = mxs_dma_channels + pdev->chan_base;
+ for (i = 0; i < pdev->chan_num; i++, pchan++) {
+ pchan->dma = pdev;
+ pchan->flags = MXS_DMA_FLAGS_VALID;
+ }
+ list_add(&pdev->node, &mxs_dma_devices);
+ mutex_unlock(&mxs_dma_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(mxs_dma_device_register);
+
+static int __init mxs_dma_alignment_setup(char *line)
+{
+ get_option(&line, &mxs_dma_alignment);
+ mxs_dma_alignment = (mxs_dma_alignment + 3) & (~3);
+ mxs_dma_alignment = max(mxs_dma_alignment, MXS_DMA_ALIGNMENT);
+ return 1;
+};
+
+__setup("mxs-dma-alignment=", mxs_dma_alignment_setup);
+
+static int mxs_dmaengine_init(void)
+{
+ mxs_dma_pool = dma_pool_create("mxs_dma", NULL,
+ sizeof(struct mxs_dma_desc),
+ mxs_dma_alignment, PAGE_SIZE);
+ if (mxs_dma_pool == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+subsys_initcall(mxs_dmaengine_init);
+
+#ifdef CONFIG_PROC_FS
+
+static void *mxs_dma_proc_seq_start(struct seq_file *file, loff_t * index)
+{
+ if (*index >= MXS_MAX_DMA_CHANNELS)
+ return NULL;
+ return mxs_dma_channels + *index;
+}
+
+static void *mxs_dma_proc_seq_next(struct seq_file *file, void *data,
+ loff_t *index)
+{
+ if (data == NULL)
+ return NULL;
+
+ if (*index >= MXS_MAX_DMA_CHANNELS)
+ return NULL;
+
+ return mxs_dma_channels + (*index)++;
+}
+
+static void mxs_dma_proc_seq_stop(struct seq_file *file, void *data)
+{
+}
+
+static int mxs_dma_proc_seq_show(struct seq_file *file, void *data)
+{
+ int result;
+ struct mxs_dma_chan *pchan = (struct mxs_dma_chan *)data;
+ struct mxs_dma_device *pdev = pchan->dma;
+ result = seq_printf(file, "%s-channel%-d (%s)\n",
+ pdev->name,
+ pchan - mxs_dma_channels,
+ pchan->name ? pchan->name : "idle");
+ return result;
+}
+
+static const struct seq_operations mxc_dma_proc_seq_ops = {
+ .start = mxs_dma_proc_seq_start,
+ .next = mxs_dma_proc_seq_next,
+ .stop = mxs_dma_proc_seq_stop,
+ .show = mxs_dma_proc_seq_show
+};
+
+static int mxs_dma_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &mxc_dma_proc_seq_ops);
+}
+
+static const struct file_operations mxs_dma_proc_info_ops = {
+ .open = mxs_dma_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init mxs_dmaengine_info_init(void)
+{
+ struct proc_dir_entry *res;
+ res = create_proc_entry("dma-engine", 0, NULL);
+ if (!res) {
+ printk(KERN_ERR "Failed to create dma info file \n");
+ return -ENOMEM;
+ }
+ res->proc_fops = &mxs_dma_proc_info_ops;
+ return 0;
+}
+
+late_initcall(mxs_dmaengine_info_init);
+#endif
diff --git a/arch/arm/mach-mx5/dummy_gpio.c b/arch/arm/mach-mx5/dummy_gpio.c
new file mode 100644
index 000000000000..6766cdf43911
--- /dev/null
+++ b/arch/arm/mach-mx5/dummy_gpio.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2007-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+
+void gpio_uart_active(int port, int no_irda) {}
+EXPORT_SYMBOL(gpio_uart_active);
+
+void gpio_uart_inactive(int port, int no_irda) {}
+EXPORT_SYMBOL(gpio_uart_inactive);
+
+void gpio_gps_active(void) {}
+EXPORT_SYMBOL(gpio_gps_active);
+
+void gpio_gps_inactive(void) {}
+EXPORT_SYMBOL(gpio_gps_inactive);
+
+void config_uartdma_event(int port) {}
+EXPORT_SYMBOL(config_uartdma_event);
+
+void gpio_spi_active(int cspi_mod) {}
+EXPORT_SYMBOL(gpio_spi_active);
+
+void gpio_spi_inactive(int cspi_mod) {}
+EXPORT_SYMBOL(gpio_spi_inactive);
+
+void gpio_owire_active(void) {}
+EXPORT_SYMBOL(gpio_owire_active);
+
+void gpio_owire_inactive(void) {}
+EXPORT_SYMBOL(gpio_owire_inactive);
+
+void gpio_i2c_active(int i2c_num) {}
+EXPORT_SYMBOL(gpio_i2c_active);
+
+void gpio_i2c_inactive(int i2c_num) {}
+EXPORT_SYMBOL(gpio_i2c_inactive);
+
+void gpio_i2c_hs_active(void) {}
+EXPORT_SYMBOL(gpio_i2c_hs_active);
+
+void gpio_i2c_hs_inactive(void) {}
+EXPORT_SYMBOL(gpio_i2c_hs_inactive);
+
+void gpio_pmic_active(void) {}
+EXPORT_SYMBOL(gpio_pmic_active);
+
+void gpio_activate_audio_ports(void) {}
+EXPORT_SYMBOL(gpio_activate_audio_ports);
+
+void gpio_sdhc_active(int module) {}
+EXPORT_SYMBOL(gpio_sdhc_active);
+
+void gpio_sdhc_inactive(int module) {}
+EXPORT_SYMBOL(gpio_sdhc_inactive);
+
+void gpio_sensor_select(int sensor) {}
+
+void gpio_sensor_active(unsigned int csi) {}
+EXPORT_SYMBOL(gpio_sensor_active);
+
+void gpio_sensor_inactive(unsigned int csi) {}
+EXPORT_SYMBOL(gpio_sensor_inactive);
+
+void gpio_ata_active(void) {}
+EXPORT_SYMBOL(gpio_ata_active);
+
+void gpio_ata_inactive(void) {}
+EXPORT_SYMBOL(gpio_ata_inactive);
+
+void gpio_nand_active(void) {}
+EXPORT_SYMBOL(gpio_nand_active);
+
+void gpio_nand_inactive(void) {}
+EXPORT_SYMBOL(gpio_nand_inactive);
+
+void gpio_keypad_active(void) {}
+EXPORT_SYMBOL(gpio_keypad_active);
+
+void gpio_keypad_inactive(void) {}
+EXPORT_SYMBOL(gpio_keypad_inactive);
+
+int gpio_usbotg_hs_active(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gpio_usbotg_hs_active);
+
+void gpio_usbotg_hs_inactive(void) {}
+EXPORT_SYMBOL(gpio_usbotg_hs_inactive);
+
+void gpio_fec_active(void) {}
+EXPORT_SYMBOL(gpio_fec_active);
+
+void gpio_fec_inactive(void) {}
+EXPORT_SYMBOL(gpio_fec_inactive);
+
+void gpio_spdif_active(void) {}
+EXPORT_SYMBOL(gpio_spdif_active);
+
+void gpio_spdif_inactive(void) {}
+EXPORT_SYMBOL(gpio_spdif_inactive);
+
+void gpio_mlb_active(void) {}
+EXPORT_SYMBOL(gpio_mlb_active);
+
+void gpio_mlb_inactive(void) {}
+EXPORT_SYMBOL(gpio_mlb_inactive);
diff --git a/arch/arm/mach-mx5/early_setup.c b/arch/arm/mach-mx5/early_setup.c
new file mode 100644
index 000000000000..dd731d7f822e
--- /dev/null
+++ b/arch/arm/mach-mx5/early_setup.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+
+int __initdata primary_di = { 0 };
+static int __init di_setup(char *__unused)
+{
+ primary_di = 1;
+ return 1;
+}
+__setup("di1_primary", di_setup);
+
diff --git a/arch/arm/mach-mx5/iomux.c b/arch/arm/mach-mx5/iomux.c
new file mode 100644
index 000000000000..25b8514b7048
--- /dev/null
+++ b/arch/arm/mach-mx5/iomux.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @defgroup GPIO_MX5 Board GPIO and Muxing Setup
+ * @ingroup MSL_MX5
+ */
+/*!
+ * @file mach-mx5/iomux.c
+ *
+ * @brief I/O Muxing control functions
+ *
+ * @ingroup GPIO_MX5
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include "iomux.h"
+#include "mx51_pins.h"
+
+#define MUX_I_START_MX53 0x0020
+#define PAD_I_START_MX53 0x348
+#define INPUT_CTL_START_MX53 0x730
+#define MUX_I_END_MX53 (PAD_I_START_MX53 - 4)
+
+#define PAD_I_START_MX50 0x2CC
+#define INPUT_CTL_START_MX50 0x6C4
+
+/*!
+ * IOMUX register (base) addressesf
+ */
+#define IOMUXGPR0 (IO_ADDRESS(IOMUXC_BASE_ADDR))
+#define IOMUXGPR1 (IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x004)
+#define IOMUXSW_MUX_CTL (IO_ADDRESS(IOMUXC_BASE_ADDR))
+#define IOMUXSW_INPUT_CTL (IO_ADDRESS(IOMUXC_BASE_ADDR))
+
+static u8 iomux_pin_res_table[(0x3F0 / 4) + 1];
+static DEFINE_SPINLOCK(gpio_mux_lock);
+
+static inline void *_get_sw_pad(void)
+{
+ if (cpu_is_mx51())
+ return IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START_MX51;
+ else if (cpu_is_mx53())
+ return IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START_MX53;
+ else
+ return IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START_MX50;
+}
+
+static inline void *_get_mux_reg(iomux_pin_name_t pin)
+{
+ u32 mux_reg = PIN_TO_IOMUX_MUX(pin);
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) {
+ if ((pin == MX51_PIN_NANDF_RB5) ||
+ (pin == MX51_PIN_NANDF_RB6) ||
+ (pin == MX51_PIN_NANDF_RB7))
+ ; /* Do nothing */
+ else if (mux_reg >= 0x2FC)
+ mux_reg += 8;
+ else if (mux_reg >= 0x130)
+ mux_reg += 0xC;
+ }
+ return IOMUXSW_MUX_CTL + mux_reg;
+}
+
+static inline void *_get_pad_reg(iomux_pin_name_t pin)
+{
+ u32 pad_reg = PIN_TO_IOMUX_PAD(pin);
+ void __iomem *sw_pad_reg = _get_sw_pad();
+
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) {
+ if ((pin == MX51_PIN_NANDF_RB5) ||
+ (pin == MX51_PIN_NANDF_RB6) ||
+ (pin == MX51_PIN_NANDF_RB7))
+ ; /* Do nothing */
+ else if (pad_reg == 0x4D0 - PAD_I_START_MX51)
+ pad_reg += 0x4C;
+ else if (pad_reg == 0x860 - PAD_I_START_MX51)
+ pad_reg += 0x9C;
+ else if (pad_reg >= 0x804 - PAD_I_START_MX51)
+ pad_reg += 0xB0;
+ else if (pad_reg >= 0x7FC - PAD_I_START_MX51)
+ pad_reg += 0xB4;
+ else if (pad_reg >= 0x4E4 - PAD_I_START_MX51)
+ pad_reg += 0xCC;
+ else
+ pad_reg += 8;
+ }
+ return sw_pad_reg + pad_reg;
+}
+
+static inline void *_get_mux_end(void)
+{
+ if (cpu_is_mx50())
+ return IO_ADDRESS(IOMUXC_BASE_ADDR) + 0x2C8;
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0)
+ return IO_ADDRESS(IOMUXC_BASE_ADDR) + (0x3F8 - 4);
+ else
+ return IO_ADDRESS(IOMUXC_BASE_ADDR) + (0x3F0 - 4);
+}
+
+/*!
+ * This function is used to configure a pin through the IOMUX module.
+ * @param pin a pin number as defined in \b #iomux_pin_name_t
+ * @param config a configuration as defined in \b #iomux_pin_cfg_t
+ *
+ * @return 0 if successful; Non-zero otherwise
+ */
+static int iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t config)
+{
+ u32 ret = 0;
+ u32 pin_index = PIN_TO_IOMUX_INDEX(pin);
+ void __iomem *mux_reg = _get_mux_reg(pin);
+ u32 mux_data = 0;
+ u8 *rp;
+
+ BUG_ON((mux_reg > _get_mux_end()) || (mux_reg < IOMUXSW_MUX_CTL));
+ spin_lock(&gpio_mux_lock);
+
+ if (config == IOMUX_CONFIG_GPIO)
+ mux_data = PIN_TO_ALT_GPIO(pin);
+ else
+ mux_data = config;
+
+ __raw_writel(mux_data, mux_reg);
+
+ /*
+ * Log a warning if a pin changes ownership
+ */
+ rp = iomux_pin_res_table + pin_index;
+ if ((mux_data & *rp) && (*rp != mux_data)) {
+ /*
+ * Don't call printk if we're tweaking the console uart or
+ * we'll deadlock.
+ */
+ printk(KERN_ERR "iomux_config_mux: Warning: iomux pin"
+ " config changed, reg=%p, "
+ " prev=0x%x new=0x%x\n", mux_reg, *rp, mux_data);
+ ret = -EINVAL;
+ }
+ *rp = mux_data;
+ spin_unlock(&gpio_mux_lock);
+ return ret;
+}
+
+/*!
+ * Request ownership for an IO pin. This function has to be the first one
+ * being called before that pin is used. The caller has to check the
+ * return value to make sure it returns 0.
+ *
+ * @param pin a name defined by \b iomux_pin_name_t
+ * @param config a configuration as defined in \b #iomux_pin_cfg_t
+ *
+ * @return 0 if successful; Non-zero otherwise
+ */
+int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config)
+{
+ int ret = iomux_config_mux(pin, config);
+ int gpio = IOMUX_TO_GPIO(pin);
+
+ if (!ret && (gpio < MXC_GPIO_IRQS) && ((config == IOMUX_CONFIG_GPIO)
+ || (config == PIN_TO_ALT_GPIO(pin))))
+ ret |= gpio_request(gpio, NULL);
+
+ return ret;
+}
+EXPORT_SYMBOL(mxc_request_iomux);
+
+/*!
+ * Release ownership for an IO pin
+ *
+ * @param pin a name defined by \b iomux_pin_name_t
+ * @param config config as defined in \b #iomux_pin_ocfg_t
+ */
+void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config)
+{
+ u32 pin_index = PIN_TO_IOMUX_INDEX(pin);
+ u8 *rp = iomux_pin_res_table + pin_index;
+ int gpio = IOMUX_TO_GPIO(pin);
+
+ *rp = 0;
+ if ((gpio < MXC_GPIO_IRQS)
+ && ((config == IOMUX_CONFIG_GPIO)
+ || (config == PIN_TO_ALT_GPIO(pin))))
+ gpio_free(gpio);
+
+}
+EXPORT_SYMBOL(mxc_free_iomux);
+
+/*!
+ * This function configures the pad value for a IOMUX pin.
+ *
+ * @param pin a pin number as defined in \b #iomux_pin_name_t
+ * @param config the ORed value of elements defined in \b #iomux_pad_config_t
+ */
+void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config)
+{
+ void __iomem *pad_reg = _get_pad_reg(pin);
+ void __iomem *sw_pad_reg = _get_sw_pad();
+
+ BUG_ON(pad_reg < sw_pad_reg);
+ __raw_writel(config, pad_reg);
+}
+EXPORT_SYMBOL(mxc_iomux_set_pad);
+
+unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin)
+{
+ void __iomem *pad_reg = _get_pad_reg(pin);
+
+ return __raw_readl(pad_reg);
+}
+EXPORT_SYMBOL(mxc_iomux_get_pad);
+
+/*!
+ * This function configures input path.
+ *
+ * @param input index of input select register as defined in \b #iomux_input_select_t
+ * @param config the binary value of elements defined in \b #iomux_input_config_t
+ * */
+void mxc_iomux_set_input(iomux_input_select_t input, u32 config)
+{
+ void __iomem *reg;
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) {
+ if (input == MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT)
+ input -= 4;
+ else if (input == MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT)
+ input -= 3;
+ else if (input >= MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT)
+ input -= 2;
+ else if (input >= MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT)
+ input -= 5;
+ else if (input >= MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT)
+ input -= 3;
+ else if (input >= MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT)
+ input -= 2;
+ else if (input >= MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT)
+ input -= 1;
+
+ reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX51_TO1;
+ } else if (cpu_is_mx51()) {
+ reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX51;
+ } else if (cpu_is_mx53()) {
+ reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX53;
+ } else
+ reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX50;
+
+ BUG_ON(input >= MUX_INPUT_NUM_MUX);
+ __raw_writel(config, reg);
+}
+EXPORT_SYMBOL(mxc_iomux_set_input);
diff --git a/arch/arm/mach-mx5/iomux.h b/arch/arm/mach-mx5/iomux.h
new file mode 100644
index 000000000000..0732f2169e0a
--- /dev/null
+++ b/arch/arm/mach-mx5/iomux.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __MACH_MX5_IOMUX_H__
+#define __MACH_MX5_IOMUX_H__
+
+#include <linux/types.h>
+#include <mach/gpio.h>
+
+/*!
+ * @file mach-mx5/iomux.h
+ *
+ * @brief I/O Muxing control definitions and functions
+ *
+ * @ingroup GPIO_MX5
+ */
+
+/*!
+ * @name IOMUX/PAD Bit field definitions
+ */
+
+/*! @{ */
+
+/*!
+ * In order to identify pins more effectively, each mux-controlled pin's
+ * enumerated value is constructed in the following way:
+ *
+ * -------------------------------------------------------------------
+ * 31-29 | 28 - 24 | 23 - 21 | 20 - 10| 9 - 0
+ * -------------------------------------------------------------------
+ * IO_P | IO_I | GPIO_I | PAD_I | MUX_I
+ * -------------------------------------------------------------------
+ *
+ * Bit 0 to 9 contains MUX_I used to identify the register
+ * offset (0-based. base is IOMUX_module_base) defined in the Section
+ * "sw_pad_ctl & sw_mux_ctl details" of the IC Spec. The
+ * similar field definitions are used for the pad control register.
+ * For example, the MX51_PIN_ETM_D0 is defined in the enumeration:
+ * ( (0x28 - MUX_I_START) << MUX_I)|( (0x250 - PAD_I_START) << PAD_I)
+ * It means the mux control register is at register offset 0x28. The pad control
+ * register offset is: 0x250 and also occupy the least significant bits
+ * within the register.
+ */
+
+/*!
+ * Starting bit position within each entry of \b iomux_pins to represent the
+ * MUX control register offset
+ */
+#define MUX_I 0
+/*!
+ * Starting bit position within each entry of \b iomux_pins to represent the
+ * PAD control register offset
+ */
+#define PAD_I 10
+/*!
+ * Starting bit position within each entry of \b iomux_pins to represent which
+ * mux mode is for GPIO (0-based)
+ */
+#define GPIO_I 21
+
+#define NON_GPIO_PORT 0x7
+#define PIN_TO_MUX_MASK ((1 << (PAD_I - MUX_I)) - 1)
+#define PIN_TO_PAD_MASK ((1 << (GPIO_I - PAD_I)) - 1)
+#define PIN_TO_ALT_GPIO_MASK ((1 << (MUX_IO_I - GPIO_I)) - 1)
+
+#define NON_MUX_I PIN_TO_MUX_MASK
+#define NON_PAD_I PIN_TO_PAD_MASK
+
+#define PIN_TO_IOMUX_MUX(pin) ((pin >> MUX_I) & PIN_TO_MUX_MASK)
+#define PIN_TO_IOMUX_PAD(pin) ((pin >> PAD_I) & PIN_TO_PAD_MASK)
+#define PIN_TO_ALT_GPIO(pin) ((pin >> GPIO_I) & PIN_TO_ALT_GPIO_MASK)
+#define PIN_TO_IOMUX_INDEX(pin) (PIN_TO_IOMUX_MUX(pin) >> 2)
+
+/*! @} End IOMUX/PAD Bit field definitions */
+
+typedef unsigned int iomux_pin_name_t;
+typedef unsigned int iomux_input_select_t;
+
+/*!
+ * various IOMUX output functions
+ */
+typedef enum iomux_config {
+ IOMUX_CONFIG_ALT0, /*!< used as alternate function 0 */
+ IOMUX_CONFIG_ALT1, /*!< used as alternate function 1 */
+ IOMUX_CONFIG_ALT2, /*!< used as alternate function 2 */
+ IOMUX_CONFIG_ALT3, /*!< used as alternate function 3 */
+ IOMUX_CONFIG_ALT4, /*!< used as alternate function 4 */
+ IOMUX_CONFIG_ALT5, /*!< used as alternate function 5 */
+ IOMUX_CONFIG_ALT6, /*!< used as alternate function 6 */
+ IOMUX_CONFIG_ALT7, /*!< used as alternate function 7 */
+ IOMUX_CONFIG_GPIO, /*!< added to help user use GPIO mode */
+ IOMUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */
+} iomux_pin_cfg_t;
+
+/*!
+ * various IOMUX pad functions
+ */
+typedef enum iomux_pad_config {
+ PAD_CTL_SRE_SLOW = 0x0 << 0,
+ PAD_CTL_SRE_FAST = 0x1 << 0,
+ PAD_CTL_DRV_LOW = 0x0 << 1,
+ PAD_CTL_DRV_MEDIUM = 0x1 << 1,
+ PAD_CTL_DRV_HIGH = 0x2 << 1,
+ PAD_CTL_DRV_MAX = 0x3 << 1,
+ PAD_CTL_ODE_OPENDRAIN_NONE = 0x0 << 3,
+ PAD_CTL_ODE_OPENDRAIN_ENABLE = 0x1 << 3,
+ PAD_CTL_100K_PD = 0x0 << 4,
+ PAD_CTL_360K_PD = 0x0 << 4,
+ PAD_CTL_47K_PU = 0x1 << 4,
+ PAD_CTL_75k_PU = 0x1 << 4,
+ PAD_CTL_100K_PU = 0x2 << 4,
+ PAD_CTL_22K_PU = 0x3 << 4,
+ PAD_CTL_PUE_KEEPER = 0x0 << 6,
+ PAD_CTL_PUE_PULL = 0x1 << 6,
+ PAD_CTL_PKE_NONE = 0x0 << 7,
+ PAD_CTL_PKE_ENABLE = 0x1 << 7,
+ PAD_CTL_HYS_NONE = 0x0 << 8,
+ PAD_CTL_HYS_ENABLE = 0x1 << 8,
+ PAD_CTL_DDR_INPUT_CMOS = 0x0 << 9,
+ PAD_CTL_DDR_INPUT_DDR = 0x1 << 9,
+ PAD_CTL_DRV_VOT_LOW = 0x0 << 13,
+ PAD_CTL_DRV_VOT_HIGH = 0x1 << 13,
+} iomux_pad_config_t;
+
+/*!
+ * various IOMUX input functions
+ */
+typedef enum iomux_input_config {
+ INPUT_CTL_PATH0 = 0x0,
+ INPUT_CTL_PATH1,
+ INPUT_CTL_PATH2,
+ INPUT_CTL_PATH3,
+ INPUT_CTL_PATH4,
+ INPUT_CTL_PATH5,
+ INPUT_CTL_PATH6,
+ INPUT_CTL_PATH7,
+} iomux_input_config_t;
+
+struct mxc_iomux_pin_cfg {
+ iomux_pin_name_t pin;
+ u8 mux_mode;
+ u16 pad_cfg;
+ u8 in_select;
+ u8 in_mode;
+};
+
+/*!
+ * Request ownership for an IO pin. This function has to be the first one
+ * being called before that pin is used. The caller has to check the
+ * return value to make sure it returns 0.
+ *
+ * @param pin a name defined by \b iomux_pin_name_t
+ * @param config config as defined in \b #iomux_pin_ocfg_t
+ *
+ * @return 0 if successful; Non-zero otherwise
+ */
+int mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config);
+
+/*!
+ * Release ownership for an IO pin
+ *
+ * @param pin a name defined by \b iomux_pin_name_t
+ * @param config config as defined in \b #iomux_pin_ocfg_t
+ */
+void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config);
+
+/*!
+ * This function configures the pad value for a IOMUX pin.
+ *
+ * @param pin a pin number as defined in \b #iomux_pin_name_t
+ * @param config the ORed value of elements defined in
+ * \b #iomux_pad_config_t
+ */
+void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config);
+
+/*!
+ * This function gets the current pad value for a IOMUX pin.
+ *
+ * @param pin a pin number as defined in \b #iomux_pin_name_t
+ * @return current pad value
+ */
+unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin);
+
+/*!
+ * This function configures input path.
+ *
+ * @param input index of input select register as defined in
+ * \b #iomux_input_select_t
+ * @param config the binary value of elements defined in \b #iomux_input_config_t
+ */
+void mxc_iomux_set_input(iomux_input_select_t input, u32 config);
+
+#endif /* __MACH_MX5_IOMUX_H__ */
diff --git a/arch/arm/mach-mx5/lpmodes.c b/arch/arm/mach-mx5/lpmodes.c
new file mode 100644
index 000000000000..fad2d814fdef
--- /dev/null
+++ b/arch/arm/mach-mx5/lpmodes.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file mx51_lpmodes.c
+ *
+ * @brief Driver for the Freescale Semiconductor MXC low power modes setup.
+ *
+ * MX51 is designed to play and video with minimal power consumption.
+ * This driver enables the platform to enter and exit audio and video low
+ * power modes.
+ *
+ * @ingroup PM
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.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 <mach/clock.h>
+#include <mach/hardware.h>
+#include <linux/regulator/machine.h>
+
+#define ARM_LP_CLK 166250000
+#define GP_LPM_VOLTAGE 775000
+#define GP_NORMAL_VOLTAGE 1050000
+
+static int org_cpu_rate;
+int lp_video_mode;
+int lp_audio_mode;
+static struct device *lpmode_dev;
+struct regulator *gp_core;
+
+void enter_lp_video_mode(void)
+{
+}
+
+void exit_lp_video_mode(void)
+{
+}
+
+void enter_lp_audio_mode(void)
+{
+ struct clk *tclk;
+ int ret;
+
+ struct clk *p_clk;
+ struct clk *amode_parent_clk;
+
+
+ tclk = clk_get(NULL, "ipu_clk");
+ if (clk_get_usecount(tclk) != 0) {
+ printk(KERN_INFO
+ "Cannot enter AUDIO LPM mode - display is still active\n");
+ return;
+ }
+
+ tclk = clk_get(NULL, "cpu_clk");
+ org_cpu_rate = clk_get_rate(tclk);
+
+#ifdef CHANGE_DDR2_TO_PLL2
+ tclk = clk_get(NULL, "ddr_clk");
+ clk_set_parent(tclk, clk_get(NULL, "axi_a_clk"));
+
+ /* Set CPU clock to be derived from PLL2 instead of PLL1 */
+ tclk = clk_get(NULL, "pll1_sw_clk");
+ clk_set_parent(tclk, clk_get(NULL, "pll2"));
+ clk_enable(tclk);
+
+ tclk = clk_get(NULL, "ddr_clk");
+ clk_set_parent(tclk, clk_get(NULL, "ddr_hf_clk"));
+#endif
+
+ /*Change the DDR freq to 133Mhz. */
+ tclk = clk_get(NULL, "ddr_hf_clk");
+ clk_set_rate(tclk, clk_round_rate(tclk, 133000000));
+
+ tclk = clk_get(NULL, "cpu_clk");
+ ret = clk_set_rate(tclk, ARM_LP_CLK);
+ if (ret != 0)
+ printk(KERN_DEBUG "cannot set CPU clock rate\n");
+ clk_put(tclk);
+ /* Set the voltage to 0.775v for the GP domain. */
+ ret = regulator_set_voltage(gp_core, GP_LPM_VOLTAGE, GP_LPM_VOLTAGE);
+ if (ret < 0)
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!\n");
+
+ tclk = clk_get(NULL, "periph_apm_clk");
+ amode_parent_clk = clk_get(NULL, "lp_apm");
+ p_clk = clk_get_parent(tclk);
+ /* Make sure osc_clk is the parent of lp_apm. */
+ clk_set_parent(amode_parent_clk, clk_get(NULL, "osc"));
+ /* Set the parent of periph_apm_clk to be lp_apm */
+ clk_set_parent(tclk, amode_parent_clk);
+
+ amode_parent_clk = tclk;
+
+ tclk = clk_get(NULL, "main_bus_clk");
+ p_clk = clk_get_parent(tclk);
+ /* Set the parent of main_bus_clk to be periph_apm_clk */
+ clk_set_parent(tclk, amode_parent_clk);
+
+ clk_set_rate(clk_get(NULL, "axi_a_clk"), 24000000);
+ clk_set_rate(clk_get(NULL, "axi_b_clk"), 24000000);
+ clk_set_rate(clk_get(NULL, "ahb_clk"), 24000000);
+ clk_set_rate(clk_get(NULL, "emi_slow_clk"), 24000000);
+ clk_set_rate(clk_get(NULL, "nfc_clk"), 12000000);
+
+ /* disable PLL3 */
+ tclk = clk_get(NULL, "pll3");
+ if (tclk->usecount == 1)
+ clk_disable(tclk);
+
+ /* disable PLL2 */
+ tclk = clk_get(NULL, "pll2");
+ if (tclk->usecount == 1)
+ clk_disable(tclk);
+
+ /* disable PLL1 */
+ tclk = clk_get(NULL, "pll1_main_clk");
+ if (tclk->usecount == 1)
+ clk_disable(tclk);
+
+ lp_audio_mode = 1;
+}
+
+void exit_lp_audio_mode(void)
+{
+ struct clk *tclk;
+ struct clk *p_clk;
+ struct clk *rmode_parent_clk;
+ int ret;
+
+ /* Set the voltage to 1.05v for the GP domain. */
+ ret = regulator_set_voltage(gp_core,
+ GP_NORMAL_VOLTAGE, GP_NORMAL_VOLTAGE);
+ if (ret < 0)
+ printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!\n");
+
+ rmode_parent_clk = clk_get(NULL, "pll2");
+ clk_enable(rmode_parent_clk);
+
+ tclk = clk_get(NULL, "main_bus_clk");
+ p_clk = clk_get_parent(tclk);
+
+ /* Set the dividers before setting the parent clock. */
+ clk_set_rate(clk_get(NULL, "axi_a_clk"), 6000000);
+ clk_set_rate(clk_get(NULL, "axi_b_clk"), 4800000);
+ clk_set_rate(clk_get(NULL, "ahb_clk"), 4800000);
+ clk_set_rate(clk_get(NULL, "emi_slow_clk"), 4800000);
+ clk_set_rate(clk_get(NULL, "nfc_clk"), 1200000);
+ /* Set the parent of main_bus_clk to be pll2 */
+ clk_set_parent(tclk, rmode_parent_clk);
+
+#ifdef CHANGE_DDR2_TO_PLL2
+ tclk = clk_get(NULL, "ddr_clk");
+ clk_set_parent(tclk, clk_get(NULL, "axi_a_clk"));
+
+ /* Set CPU clock to be derived from PLL1 instead of PLL2 */
+ tclk = clk_get(NULL, "pll1_sw_clk");
+ clk_set_parent(tclk, clk_get(NULL, "pll1_main_clk"));
+ clk_disable(tclk);
+
+ tclk = clk_get(NULL, "ddr_clk");
+ clk_set_parent(tclk, clk_get(NULL, "ddr_hf_clk"));
+#endif
+
+ tclk = clk_get(NULL, "cpu_clk");
+ ret = clk_set_rate(tclk, org_cpu_rate);
+ if (ret != 0)
+ printk(KERN_DEBUG "cannot set CPU clock rate\n");
+ clk_put(tclk);
+
+ tclk = clk_get(NULL, "cpu_clk");
+
+ ret = clk_set_rate(tclk, org_cpu_rate);
+ if (ret != 0)
+ printk(KERN_DEBUG "cannot set CPU clock rate\n");
+
+
+ /*Change the DDR freq to 200MHz*/
+ tclk = clk_get(NULL, "ddr_hf_clk");
+ clk_set_rate(tclk, clk_round_rate(tclk, 200000000));
+ lp_audio_mode = 0;
+
+}
+
+static ssize_t lp_curr_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (lp_video_mode)
+ return sprintf(buf, "in lp_video_mode\n");
+ else if (lp_audio_mode)
+ return sprintf(buf, "in lp_audio_mode\n");
+ else
+ return sprintf(buf, "in normal mode\n");
+}
+
+static ssize_t set_lp_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ printk(KERN_DEBUG "In set_lp_mode() \n");
+
+ if (strstr(buf, "enable_lp_video") != NULL) {
+ if (!lp_video_mode)
+ enter_lp_video_mode();
+ } else if (strstr(buf, "disable_lp_video") != NULL) {
+ if (lp_video_mode)
+ exit_lp_video_mode();
+ } else if (strstr(buf, "enable_lp_audio") != NULL) {
+ if (!lp_audio_mode)
+ enter_lp_audio_mode();
+ } else if (strstr(buf, "disable_lp_audio") != NULL) {
+ if (lp_audio_mode)
+ exit_lp_audio_mode();
+ }
+ return size;
+}
+
+static DEVICE_ATTR(lp_modes, 0644, lp_curr_mode, set_lp_mode);
+
+/*!
+ * This is the probe routine for the lp_mode driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ *
+ */
+static int __devinit mx51_lpmode_probe(struct platform_device *pdev)
+{
+ u32 res = 0;
+ lpmode_dev = &pdev->dev;
+
+ res = sysfs_create_file(&lpmode_dev->kobj, &dev_attr_lp_modes.attr);
+ if (res) {
+ printk(KERN_ERR
+ "lpmode_dev: Unable to register sysdev entry for lpmode_dev");
+ return res;
+ }
+
+ if (res != 0) {
+ printk(KERN_ERR "lpmode_dev: Unable to start");
+ return res;
+ }
+ gp_core = regulator_get(NULL, "SW1");
+ lp_video_mode = 0;
+ lp_audio_mode = 0;
+
+ return 0;
+}
+
+static struct platform_driver mx51_lpmode_driver = {
+ .driver = {
+ .name = "mx51_lpmode",
+ },
+ .probe = mx51_lpmode_probe,
+};
+
+/*!
+ * Initialise the mx51_lpmode_driver.
+ *
+ * @return The function always returns 0.
+ */
+
+static int __init lpmode_init(void)
+{
+ if (platform_driver_register(&mx51_lpmode_driver) != 0) {
+ printk(KERN_ERR "mx37_lpmode_driver register failed\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "LPMode driver module loaded\n");
+ return 0;
+}
+
+static void __exit lpmode_cleanup(void)
+{
+ sysfs_remove_file(&lpmode_dev->kobj, &dev_attr_lp_modes.attr);
+
+ /* Unregister the device structure */
+ platform_driver_unregister(&mx51_lpmode_driver);
+}
+
+module_init(lpmode_init);
+module_exit(lpmode_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("LPMode driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index b7677ef80cc4..a17ae5a588c2 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
@@ -15,69 +15,50 @@
#include <linux/init.h>
#include <asm/mach/map.h>
+#include <mach/iomux-v3.h>
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-v3.h>
-/*
- * Define the MX51 memory map.
+/*!
+ * This structure defines the MX5x memory map.
*/
-static struct map_desc mxc_io_desc[] __initdata = {
+static struct map_desc mx5_io_desc[] __initdata = {
+ {
+ .virtual = AIPS1_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS1_BASE_ADDR),
+ .length = AIPS1_SIZE,
+ .type = MT_DEVICE},
{
- .virtual = MX51_IRAM_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(MX51_IRAM_BASE_ADDR),
- .length = MX51_IRAM_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = MX51_DEBUG_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(MX51_DEBUG_BASE_ADDR),
- .length = MX51_DEBUG_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = MX51_AIPS1_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(MX51_AIPS1_BASE_ADDR),
- .length = MX51_AIPS1_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = MX51_SPBA0_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(MX51_SPBA0_BASE_ADDR),
- .length = MX51_SPBA0_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = MX51_AIPS2_BASE_ADDR_VIRT,
- .pfn = __phys_to_pfn(MX51_AIPS2_BASE_ADDR),
- .length = MX51_AIPS2_SIZE,
- .type = MT_DEVICE
- },
+ .virtual = SPBA0_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
+ .length = SPBA0_SIZE,
+ .type = MT_DEVICE},
+ {
+ .virtual = AIPS2_BASE_ADDR_VIRT,
+ .pfn = __phys_to_pfn(AIPS2_BASE_ADDR),
+ .length = AIPS2_SIZE,
+ .type = MT_DEVICE},
};
-/*
+/*!
* This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
+ * system startup to create static physical to virtual memory map for
+ * the IO modules.
*/
-void __init mx51_map_io(void)
+void __init mx5_map_io(void)
{
- mxc_set_cpu_type(MXC_CPU_MX51);
- mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
- mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG_BASE_ADDR));
- iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
-}
-
-void __init mx51_init_irq(void)
-{
- unsigned long tzic_addr;
- void __iomem *tzic_virt;
+ int i;
- if (mx51_revision() < MX51_CHIP_REV_2_0)
- tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
- else
- tzic_addr = MX51_TZIC_BASE_ADDR;
+ mxc_iomux_v3_init(IO_ADDRESS(IOMUXC_BASE_ADDR));
+ /* Fixup the mappings for MX53 */
+ if (cpu_is_mx53() || cpu_is_mx50()) {
+ for (i = 0; i < ARRAY_SIZE(mx5_io_desc); i++)
+ mx5_io_desc[i].pfn -= __phys_to_pfn(0x20000000);
+ }
- tzic_virt = ioremap(tzic_addr, SZ_16K);
- if (!tzic_virt)
- panic("unable to map TZIC interrupt controller\n");
-
- tzic_init_irq(tzic_virt);
+ iotable_init(mx5_io_desc, ARRAY_SIZE(mx5_io_desc));
+ mxc_arch_reset_init(IO_ADDRESS(WDOG1_BASE_ADDR));
}
+
diff --git a/arch/arm/mach-mx5/mx50_arm2.c b/arch/arm/mach-mx5/mx50_arm2.c
new file mode 100644
index 000000000000..01d6d3db4533
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_arm2.c
@@ -0,0 +1,1260 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max17135.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/videodev2.h>
+#include <linux/mxcfb.h>
+#include <linux/fec.h>
+#include <linux/gpmi-nfc.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/arc_otg.h>
+#include <mach/memory.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/iomux-mx50.h>
+#include <mach/i2c.h>
+
+#include "devices.h"
+#include "crm_regs.h"
+#include "usb.h"
+#include "dma-apbh.h"
+
+#define SD1_WP (3*32 + 19) /*GPIO_4_19 */
+#define SD1_CD (0*32 + 27) /*GPIO_1_27 */
+#define SD2_WP (4*32 + 16) /*GPIO_5_16 */
+#define SD2_CD (4*32 + 17) /*GPIO_5_17 */
+#define SD3_WP (4*32 + 28) /*GPIO_5_28 */
+#define SD3_CD (3*32 + 4) /*GPIO_4_4 */
+#define HP_DETECT (3*32 + 15) /*GPIO_4_15 */
+#define PWR_INT (3*32 + 18) /*GPIO_4_18 */
+
+#define EPDC_D0 (2*32 + 0) /*GPIO_3_0 */
+#define EPDC_D1 (2*32 + 1) /*GPIO_3_1 */
+#define EPDC_D2 (2*32 + 2) /*GPIO_3_2 */
+#define EPDC_D3 (2*32 + 3) /*GPIO_3_3 */
+#define EPDC_D4 (2*32 + 4) /*GPIO_3_4 */
+#define EPDC_D5 (2*32 + 5) /*GPIO_3_5 */
+#define EPDC_D6 (2*32 + 6) /*GPIO_3_6 */
+#define EPDC_D7 (2*32 + 7) /*GPIO_3_7 */
+#define EPDC_GDCLK (2*32 + 16) /*GPIO_3_16 */
+#define EPDC_GDSP (2*32 + 17) /*GPIO_3_17 */
+#define EPDC_GDOE (2*32 + 18) /*GPIO_3_18 */
+#define EPDC_GDRL (2*32 + 19) /*GPIO_3_19 */
+#define EPDC_SDCLK (2*32 + 20) /*GPIO_3_20 */
+#define EPDC_SDOE (2*32 + 23) /*GPIO_3_23 */
+#define EPDC_SDLE (2*32 + 24) /*GPIO_3_24 */
+#define EPDC_SDSHR (2*32 + 26) /*GPIO_3_26 */
+#define EPDC_BDR0 (3*32 + 23) /*GPIO_4_23 */
+#define EPDC_SDCE0 (3*32 + 25) /*GPIO_4_25 */
+#define EPDC_SDCE1 (3*32 + 26) /*GPIO_4_26 */
+#define EPDC_SDCE2 (3*32 + 27) /*GPIO_4_27 */
+
+#define EPDC_PMIC_WAKE (5*32 + 16) /*GPIO_6_16 */
+#define EPDC_PMIC_INT (5*32 + 17) /*GPIO_6_17 */
+#define EPDC_VCOM (3*32 + 21) /*GPIO_4_21 */
+#define EPDC_PWRSTAT (2*32 + 28) /*GPIO_3_28 */
+#define EPDC_ELCDIF_BACKLIGHT (1*32 + 18) /*GPIO_2_18 */
+#define CSPI_CS1 (3*32 + 13) /*GPIO_4_13 */
+#define CSPI_CS2 (3*32 + 11) /*GPIO_4_11*/
+#define USB_OTG_PWR (5*32 + 25) /*GPIO_6_25*/
+
+extern int __init mx50_arm2_init_mc13892(void);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+static int max17135_regulator_init(struct max17135 *max17135);
+static int num_cpu_wp = 2;
+
+static struct pad_desc mx50_armadillo2[] = {
+ /* SD1 */
+ MX50_PAD_ECSPI2_SS0__GPIO_4_19,
+ MX50_PAD_EIM_CRE__GPIO_1_27,
+ MX50_PAD_SD1_CMD__SD1_CMD,
+
+ MX50_PAD_SD1_CLK__SD1_CLK,
+ MX50_PAD_SD1_D0__SD1_D0,
+ MX50_PAD_SD1_D1__SD1_D1,
+ MX50_PAD_SD1_D2__SD1_D2,
+ MX50_PAD_SD1_D3__SD1_D3,
+
+ /* SD2 */
+ MX50_PAD_SD2_CD__GPIO_5_17,
+ MX50_PAD_SD2_WP__GPIO_5_16,
+ MX50_PAD_SD2_CMD__SD2_CMD,
+ MX50_PAD_SD2_CLK__SD2_CLK,
+ MX50_PAD_SD2_D0__SD2_D0,
+ MX50_PAD_SD2_D1__SD2_D1,
+ MX50_PAD_SD2_D2__SD2_D2,
+ MX50_PAD_SD2_D3__SD2_D3,
+ MX50_PAD_SD2_D4__SD2_D4,
+ MX50_PAD_SD2_D5__SD2_D5,
+ MX50_PAD_SD2_D6__SD2_D6,
+ MX50_PAD_SD2_D7__SD2_D7,
+
+ /* SD3 */
+ MX50_PAD_SD3_WP__GPIO_5_28,
+ MX50_PAD_KEY_COL2__GPIO_4_4,
+ MX50_PAD_SD3_CMD__SD3_CMD,
+ MX50_PAD_SD3_CLK__SD3_CLK,
+ MX50_PAD_SD3_D0__SD3_D0,
+ MX50_PAD_SD3_D1__SD3_D1,
+ MX50_PAD_SD3_D2__SD3_D2,
+ MX50_PAD_SD3_D3__SD3_D3,
+ MX50_PAD_SD3_D4__SD3_D4,
+ MX50_PAD_SD3_D5__SD3_D5,
+ MX50_PAD_SD3_D6__SD3_D6,
+ MX50_PAD_SD3_D7__SD3_D7,
+
+ MX50_PAD_SSI_RXD__SSI_RXD,
+ MX50_PAD_SSI_TXD__SSI_TXD,
+ MX50_PAD_SSI_TXC__SSI_TXC,
+ MX50_PAD_SSI_TXFS__SSI_TXFS,
+
+ /* LINE1_DETECT (headphone detect) */
+ MX50_PAD_ECSPI1_SS0__GPIO_4_15,
+
+ /* PWR_INT */
+ MX50_PAD_ECSPI2_MISO__GPIO_4_18,
+
+ /* UART pad setting */
+ MX50_PAD_UART1_TXD__UART1_TXD,
+ MX50_PAD_UART1_RXD__UART1_RXD,
+ MX50_PAD_UART1_CTS__UART1_CTS,
+ MX50_PAD_UART1_RTS__UART1_RTS,
+ MX50_PAD_UART2_TXD__UART2_TXD,
+ MX50_PAD_UART2_RXD__UART2_RXD,
+ MX50_PAD_UART2_CTS__UART2_CTS,
+ MX50_PAD_UART2_RTS__UART2_RTS,
+
+ MX50_PAD_I2C1_SCL__I2C1_SCL,
+ MX50_PAD_I2C1_SDA__I2C1_SDA,
+ MX50_PAD_I2C2_SCL__I2C2_SCL,
+ MX50_PAD_I2C2_SDA__I2C2_SDA,
+ MX50_PAD_I2C3_SCL__I2C3_SCL,
+ MX50_PAD_I2C3_SDA__I2C3_SDA,
+
+ /* EPDC pins */
+ MX50_PAD_EPDC_D0__EPDC_D0,
+ MX50_PAD_EPDC_D1__EPDC_D1,
+ MX50_PAD_EPDC_D2__EPDC_D2,
+ MX50_PAD_EPDC_D3__EPDC_D3,
+ MX50_PAD_EPDC_D4__EPDC_D4,
+ MX50_PAD_EPDC_D5__EPDC_D5,
+ MX50_PAD_EPDC_D6__EPDC_D6,
+ MX50_PAD_EPDC_D7__EPDC_D7,
+ MX50_PAD_EPDC_GDCLK__EPDC_GDCLK,
+ MX50_PAD_EPDC_GDSP__EPDC_GDSP,
+ MX50_PAD_EPDC_GDOE__EPDC_GDOE ,
+ MX50_PAD_EPDC_GDRL__EPDC_GDRL,
+ MX50_PAD_EPDC_SDCLK__EPDC_SDCLK,
+ MX50_PAD_EPDC_SDOE__EPDC_SDOE,
+ MX50_PAD_EPDC_SDLE__EPDC_SDLE,
+ MX50_PAD_EPDC_SDSHR__EPDC_SDSHR,
+ MX50_PAD_EPDC_BDR0__EPDC_BDR0,
+ MX50_PAD_EPDC_SDCE0__EPDC_SDCE0,
+ MX50_PAD_EPDC_SDCE1__EPDC_SDCE1,
+ MX50_PAD_EPDC_SDCE2__EPDC_SDCE2,
+
+ MX50_PAD_EPDC_PWRSTAT__GPIO_3_28,
+ MX50_PAD_EPDC_VCOM0__GPIO_4_21,
+
+ MX50_PAD_DISP_D8__DISP_D8,
+ MX50_PAD_DISP_D9__DISP_D9,
+ MX50_PAD_DISP_D10__DISP_D10,
+ MX50_PAD_DISP_D11__DISP_D11,
+ MX50_PAD_DISP_D12__DISP_D12,
+ MX50_PAD_DISP_D13__DISP_D13,
+ MX50_PAD_DISP_D14__DISP_D14,
+ MX50_PAD_DISP_D15__DISP_D15,
+ MX50_PAD_DISP_RS__ELCDIF_VSYNC,
+
+ /* ELCDIF contrast */
+ MX50_PAD_DISP_BUSY__GPIO_2_18,
+
+ MX50_PAD_DISP_CS__ELCDIF_HSYNC,
+ MX50_PAD_DISP_RD__ELCDIF_EN,
+ MX50_PAD_DISP_WR__ELCDIF_PIXCLK,
+
+ /* EPD PMIC WAKEUP */
+ MX50_PAD_UART4_TXD__GPIO_6_16,
+
+ /* EPD PMIC intr */
+ MX50_PAD_UART4_RXD__GPIO_6_17,
+
+ MX50_PAD_EPITO__USBH1_PWR,
+ /* Need to comment below line if
+ * one needs to debug owire.
+ */
+ MX50_PAD_OWIRE__USBH1_OC,
+ /* using gpio to control otg pwr */
+ MX50_PAD_PWM2__GPIO_6_25,
+ MX50_PAD_PWM1__USBOTG_OC,
+
+ MX50_PAD_SSI_RXC__FEC_MDIO,
+ MX50_PAD_SSI_RXC__FEC_MDIO,
+ MX50_PAD_DISP_D0__FEC_TXCLK,
+ MX50_PAD_DISP_D1__FEC_RX_ER,
+ MX50_PAD_DISP_D2__FEC_RX_DV,
+ MX50_PAD_DISP_D3__FEC_RXD1,
+ MX50_PAD_DISP_D4__FEC_RXD0,
+ MX50_PAD_DISP_D5__FEC_TX_EN,
+ MX50_PAD_DISP_D6__FEC_TXD1,
+ MX50_PAD_DISP_D7__FEC_TXD0,
+ MX50_PAD_SSI_RXFS__FEC_MDC,
+
+ MX50_PAD_CSPI_SS0__CSPI_SS0,
+ MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
+ MX50_PAD_CSPI_MOSI__CSPI_MOSI,
+ MX50_PAD_CSPI_MISO__CSPI_MISO,
+};
+
+static struct pad_desc mx50_gpmi_nand[] = {
+ MX50_PIN_EIM_DA8__NANDF_CLE,
+ MX50_PIN_EIM_DA9__NANDF_ALE,
+ MX50_PIN_EIM_DA10__NANDF_CE0,
+ MX50_PIN_EIM_DA11__NANDF_CE1,
+ MX50_PIN_EIM_DA12__NANDF_CE2,
+ MX50_PIN_EIM_DA13__NANDF_CE3,
+ MX50_PIN_EIM_DA14__NANDF_READY,
+ MX50_PIN_EIM_DA15__NANDF_DQS,
+ MX50_PIN_SD3_D4__NANDF_D0,
+ MX50_PIN_SD3_D5__NANDF_D1,
+ MX50_PIN_SD3_D6__NANDF_D2,
+ MX50_PIN_SD3_D7__NANDF_D3,
+ MX50_PIN_SD3_D0__NANDF_D4,
+ MX50_PIN_SD3_D1__NANDF_D5,
+ MX50_PIN_SD3_D2__NANDF_D6,
+ MX50_PIN_SD3_D3__NANDF_D7,
+ MX50_PIN_SD3_CLK__NANDF_RDN,
+ MX50_PIN_SD3_CMD__NANDF_WRN,
+ MX50_PIN_SD3_WP__NANDF_RESETN,
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "SW1",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+ .num_wp = 2,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "SW1",
+ .lp_reg_id = "SW2",
+};
+
+/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */
+static struct cpu_wp cpu_wp_auto[] = {
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1050000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 160000000,
+ .pdf = 4,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 4,
+ .cpu_voltage = 850000,},
+};
+
+static struct cpu_wp *mx50_arm2_get_cpu_wp(int *wp)
+{
+ *wp = num_cpu_wp;
+ return cpu_wp_auto;
+}
+
+static void mx50_arm2_set_num_cpu_wp(int num)
+{
+ num_cpu_wp = num;
+ return;
+}
+
+static struct mxc_w1_config mxc_w1_data = {
+ .search_rom_accelerator = 1,
+};
+
+static struct fec_platform_data fec_data = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+/* workaround for cspi chipselect pin may not keep correct level when idle */
+static void mx50_arm2_gpio_spi_chipselect_active(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 3:
+ switch (chipselect) {
+ case 0x1:
+ {
+ struct pad_desc cspi_ss0 = MX50_PAD_CSPI_SS0__CSPI_SS0;
+ struct pad_desc cspi_cs1 = MX50_PAD_ECSPI1_MOSI__GPIO_4_13;
+
+ /* pull up/down deassert it */
+ mxc_iomux_v3_setup_pad(&cspi_ss0);
+ mxc_iomux_v3_setup_pad(&cspi_cs1);
+
+ gpio_request(CSPI_CS1, "cspi-cs1");
+ gpio_direction_input(CSPI_CS1);
+ }
+ break;
+ case 0x2:
+ {
+ struct pad_desc cspi_ss1 = MX50_PAD_ECSPI1_MOSI__CSPI_SS1;
+ struct pad_desc cspi_ss0 = MX50_PAD_CSPI_SS0__GPIO_4_11;
+
+ /*disable other ss */
+ mxc_iomux_v3_setup_pad(&cspi_ss1);
+ mxc_iomux_v3_setup_pad(&cspi_ss0);
+
+ /* pull up/down deassert it */
+ gpio_request(CSPI_CS2, "cspi-cs2");
+ gpio_direction_input(CSPI_CS2);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void mx50_arm2_gpio_spi_chipselect_inactive(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 3:
+ switch (chipselect) {
+ case 0x1:
+ gpio_free(CSPI_CS1);
+ break;
+ case 0x2:
+ gpio_free(CSPI_CS2);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+ .chipselect_active = mx50_arm2_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx50_arm2_gpio_spi_chipselect_inactive,
+};
+
+static struct mxc_spi_master mxcspi3_data = {
+ .maxchipselect = 4,
+ .spi_version = 7,
+ .chipselect_active = mx50_arm2_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx50_arm2_gpio_spi_chipselect_inactive,
+};
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+#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)
+
+static struct regulator_init_data max17135_init_data[] __initdata = {
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ },
+};
+
+static void epdc_get_pins(void)
+{
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ gpio_request(EPDC_D0, "epdc_d0");
+ gpio_request(EPDC_D1, "epdc_d1");
+ gpio_request(EPDC_D2, "epdc_d2");
+ gpio_request(EPDC_D3, "epdc_d3");
+ gpio_request(EPDC_D4, "epdc_d4");
+ gpio_request(EPDC_D5, "epdc_d5");
+ gpio_request(EPDC_D6, "epdc_d6");
+ gpio_request(EPDC_D7, "epdc_d7");
+ gpio_request(EPDC_GDCLK, "epdc_gdclk");
+ gpio_request(EPDC_GDSP, "epdc_gdsp");
+ gpio_request(EPDC_GDOE, "epdc_gdoe");
+ gpio_request(EPDC_GDRL, "epdc_gdrl");
+ gpio_request(EPDC_SDCLK, "epdc_sdclk");
+ gpio_request(EPDC_SDOE, "epdc_sdoe");
+ gpio_request(EPDC_SDLE, "epdc_sdle");
+ gpio_request(EPDC_SDSHR, "epdc_sdshr");
+ gpio_request(EPDC_BDR0, "epdc_bdr0");
+ gpio_request(EPDC_SDCE0, "epdc_sdce0");
+ gpio_request(EPDC_SDCE1, "epdc_sdce1");
+ gpio_request(EPDC_SDCE2, "epdc_sdce2");
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(EPDC_D0);
+ gpio_free(EPDC_D1);
+ gpio_free(EPDC_D2);
+ gpio_free(EPDC_D3);
+ gpio_free(EPDC_D4);
+ gpio_free(EPDC_D5);
+ gpio_free(EPDC_D6);
+ gpio_free(EPDC_D7);
+ gpio_free(EPDC_GDCLK);
+ gpio_free(EPDC_GDSP);
+ gpio_free(EPDC_GDOE);
+ gpio_free(EPDC_GDRL);
+ gpio_free(EPDC_SDCLK);
+ gpio_free(EPDC_SDOE);
+ gpio_free(EPDC_SDLE);
+ gpio_free(EPDC_SDSHR);
+ gpio_free(EPDC_BDR0);
+ gpio_free(EPDC_SDCE0);
+ gpio_free(EPDC_SDCE1);
+ gpio_free(EPDC_SDCE2);
+}
+
+static struct pad_desc mx50_epdc_pads_enabled[] = {
+ MX50_PAD_EPDC_D0__EPDC_D0,
+ MX50_PAD_EPDC_D1__EPDC_D1,
+ MX50_PAD_EPDC_D2__EPDC_D2,
+ MX50_PAD_EPDC_D3__EPDC_D3,
+ MX50_PAD_EPDC_D4__EPDC_D4,
+ MX50_PAD_EPDC_D5__EPDC_D5,
+ MX50_PAD_EPDC_D6__EPDC_D6,
+ MX50_PAD_EPDC_D7__EPDC_D7,
+ MX50_PAD_EPDC_GDCLK__EPDC_GDCLK,
+ MX50_PAD_EPDC_GDSP__EPDC_GDSP,
+ MX50_PAD_EPDC_GDOE__EPDC_GDOE,
+ MX50_PAD_EPDC_GDRL__EPDC_GDRL,
+ MX50_PAD_EPDC_SDCLK__EPDC_SDCLK,
+ MX50_PAD_EPDC_SDOE__EPDC_SDOE,
+ MX50_PAD_EPDC_SDLE__EPDC_SDLE,
+ MX50_PAD_EPDC_SDSHR__EPDC_SDSHR,
+ MX50_PAD_EPDC_BDR0__EPDC_BDR0,
+ MX50_PAD_EPDC_SDCE0__EPDC_SDCE0,
+ MX50_PAD_EPDC_SDCE1__EPDC_SDCE1,
+ MX50_PAD_EPDC_SDCE2__EPDC_SDCE2,
+};
+
+static struct pad_desc mx50_epdc_pads_disabled[] = {
+ MX50_PAD_EPDC_D0__GPIO_3_0,
+ MX50_PAD_EPDC_D1__GPIO_3_1,
+ MX50_PAD_EPDC_D2__GPIO_3_2,
+ MX50_PAD_EPDC_D3__GPIO_3_3,
+ MX50_PAD_EPDC_D4__GPIO_3_4,
+ MX50_PAD_EPDC_D5__GPIO_3_5,
+ MX50_PAD_EPDC_D6__GPIO_3_6,
+ MX50_PAD_EPDC_D7__GPIO_3_7,
+ MX50_PAD_EPDC_GDCLK__GPIO_3_16,
+ MX50_PAD_EPDC_GDSP__GPIO_3_17,
+ MX50_PAD_EPDC_GDOE__GPIO_3_18,
+ MX50_PAD_EPDC_GDRL__GPIO_3_19,
+ MX50_PAD_EPDC_SDCLK__GPIO_3_20,
+ MX50_PAD_EPDC_SDOE__GPIO_3_23,
+ MX50_PAD_EPDC_SDLE__GPIO_3_24,
+ MX50_PAD_EPDC_SDSHR__GPIO_3_26,
+ MX50_PAD_EPDC_BDR0__GPIO_4_23,
+ MX50_PAD_EPDC_SDCE0__GPIO_4_25,
+ MX50_PAD_EPDC_SDCE1__GPIO_4_26,
+ MX50_PAD_EPDC_SDCE2__GPIO_4_27,
+};
+
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx50_epdc_pads_enabled, \
+ ARRAY_SIZE(mx50_epdc_pads_enabled));
+
+ gpio_direction_input(EPDC_D0);
+ gpio_direction_input(EPDC_D1);
+ gpio_direction_input(EPDC_D2);
+ gpio_direction_input(EPDC_D3);
+ gpio_direction_input(EPDC_D4);
+ gpio_direction_input(EPDC_D5);
+ gpio_direction_input(EPDC_D6);
+ gpio_direction_input(EPDC_D7);
+ gpio_direction_input(EPDC_GDCLK);
+ gpio_direction_input(EPDC_GDSP);
+ gpio_direction_input(EPDC_GDOE);
+ gpio_direction_input(EPDC_GDRL);
+ gpio_direction_input(EPDC_SDCLK);
+ gpio_direction_input(EPDC_SDOE);
+ gpio_direction_input(EPDC_SDLE);
+ gpio_direction_input(EPDC_SDSHR);
+ gpio_direction_input(EPDC_BDR0);
+ gpio_direction_input(EPDC_SDCE0);
+ gpio_direction_input(EPDC_SDCE1);
+ gpio_direction_input(EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx50_epdc_pads_disabled, \
+ ARRAY_SIZE(mx50_epdc_pads_disabled));
+
+ gpio_direction_output(EPDC_D0, 0);
+ gpio_direction_output(EPDC_D1, 0);
+ gpio_direction_output(EPDC_D2, 0);
+ gpio_direction_output(EPDC_D3, 0);
+ gpio_direction_output(EPDC_D4, 0);
+ gpio_direction_output(EPDC_D5, 0);
+ gpio_direction_output(EPDC_D6, 0);
+ gpio_direction_output(EPDC_D7, 0);
+ gpio_direction_output(EPDC_GDCLK, 0);
+ gpio_direction_output(EPDC_GDSP, 0);
+ gpio_direction_output(EPDC_GDOE, 0);
+ gpio_direction_output(EPDC_GDRL, 0);
+ gpio_direction_output(EPDC_SDCLK, 0);
+ gpio_direction_output(EPDC_SDOE, 0);
+ gpio_direction_output(EPDC_SDLE, 0);
+ gpio_direction_output(EPDC_SDSHR, 0);
+ gpio_direction_output(EPDC_BDR0, 0);
+ gpio_direction_output(EPDC_SDCE0, 0);
+ gpio_direction_output(EPDC_SDCE1, 0);
+ gpio_direction_output(EPDC_SDCE2, 0);
+}
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 32000000,
+ .left_margin = 8,
+ .right_margin = 166,
+ .upper_margin = 4,
+ .lower_margin = 26,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct mxc_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct mxc_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = EPDC_VCOM,
+ .gpio_pmic_wakeup = EPDC_PMIC_WAKE,
+ .gpio_pmic_intr = EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int max17135_regulator_init(struct max17135 *max17135)
+{
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i <= MAX17135_VPOS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ regulator_has_full_constraints();
+
+ return 0;
+}
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "backlight-i2c",
+ .addr = 0x2c,
+ },
+ {
+ .type = "eeprom",
+ .addr = 0x50,
+ },
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17135", 0x48),
+ .platform_data = &max17135_pdata,
+ },
+};
+
+static struct mtd_partition mxc_dataflash_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x000100000,},
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,},
+};
+
+static struct flash_platform_data mxc_spi_flash_data[] = {
+ {
+ .name = "mxc_dataflash",
+ .parts = mxc_dataflash_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_dataflash_partitions),
+ .type = "at45db321d",}
+};
+
+
+static struct spi_board_info mxc_dataflash_device[] __initdata = {
+ {
+ .modalias = "mxc_dataflash",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 3,
+ .chip_select = 1,
+ .platform_data = &mxc_spi_flash_data[0],},
+};
+
+static void mx50_arm2_usb_set_vbus(bool enable)
+{
+ gpio_set_value(USB_OTG_PWR, enable);
+}
+
+
+static int sdhc_write_protect(struct device *dev)
+{
+ unsigned short rc = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ rc = gpio_get_value(SD1_WP);
+ else if (to_platform_device(dev)->id == 1)
+ rc = gpio_get_value(SD2_WP);
+ else if (to_platform_device(dev)->id == 2)
+ rc = gpio_get_value(SD3_WP);
+
+ return rc;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret = 0;
+ if (to_platform_device(dev)->id == 0)
+ ret = gpio_get_value(SD1_CD);
+ else if (to_platform_device(dev)->id == 1)
+ ret = gpio_get_value(SD2_CD);
+ else if (to_platform_device(dev)->id == 2)
+ ret = gpio_get_value(SD3_CD);
+
+ return ret;
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static struct mxc_mmc_platform_data mmc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | MMC_CAP_DATA_DDR,
+ .min_clk = 400000,
+ .max_clk = 40000000,
+ .dll_override_en = 1,
+ .dll_delay_cells = 0xc,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static int mxc_sgtl5000_amp_enable(int enable)
+{
+/* TO DO */
+ return 0;
+}
+
+static int headphone_det_status(void)
+{
+ return (gpio_get_value(HP_DETECT) != 0);
+}
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_irq = IOMUX_TO_IRQ_V3(HP_DETECT),
+ .hp_status = headphone_det_status,
+ .amp_enable = mxc_sgtl5000_amp_enable,
+ .sysclk = 12288000,
+};
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+static struct pad_desc armadillo2_wvga_pads[] = {
+ MX50_PAD_DISP_D0__DISP_D0,
+ MX50_PAD_DISP_D1__DISP_D1,
+ MX50_PAD_DISP_D2__DISP_D2,
+ MX50_PAD_DISP_D3__DISP_D3,
+ MX50_PAD_DISP_D4__DISP_D4,
+ MX50_PAD_DISP_D5__DISP_D5,
+ MX50_PAD_DISP_D6__DISP_D6,
+ MX50_PAD_DISP_D7__DISP_D7,
+};
+
+static void wvga_reset(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(armadillo2_wvga_pads, \
+ ARRAY_SIZE(armadillo2_wvga_pads));
+ return;
+}
+
+static struct mxc_lcd_platform_data lcd_wvga_data = {
+ .reset = wvga_reset,
+};
+
+static struct platform_device lcd_wvga_device = {
+ .name = "lcd_claa",
+ .dev = {
+ .platform_data = &lcd_wvga_data,
+ },
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB565,
+ .mode_str = "CLAA-WVGA",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+static int __initdata enable_w1 = { 0 };
+static int __init w1_setup(char *__unused)
+{
+ enable_w1 = 1;
+ return cpu_is_mx50();
+}
+
+__setup("w1", w1_setup);
+
+static struct mxs_dma_plat_data dma_apbh_data = {
+ .chan_base = MXS_DMA_CHANNEL_AHB_APBH,
+ .chan_num = MXS_MAX_DMA_CHANNELS,
+};
+
+static int gpmi_nfc_platform_init(unsigned int max_chip_count)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx50_gpmi_nand,
+ ARRAY_SIZE(mx50_gpmi_nand));
+ return 0;
+}
+
+static void gpmi_nfc_platform_exit(unsigned int max_chip_count)
+{
+}
+
+static const char *gpmi_nfc_partition_source_types[] = { "cmdlinepart", 0 };
+
+static struct gpmi_nfc_platform_data gpmi_nfc_platform_data = {
+ .nfc_version = 2,
+ .boot_rom_version = 1,
+ .clock_name = "gpmi-nfc",
+ .platform_init = gpmi_nfc_platform_init,
+ .platform_exit = gpmi_nfc_platform_exit,
+ .min_prop_delay_in_ns = 5,
+ .max_prop_delay_in_ns = 9,
+ .max_chip_count = 2,
+ .boot_area_size_in_bytes = 20 * SZ_1M,
+ .partition_source_types = gpmi_nfc_partition_source_types,
+ .partitions = 0,
+ .partition_count = 0,
+};
+
+/* OTP data */
+/* Building up eight registers's names of a bank */
+#define BANK(a, b, c, d, e, f, g, h) \
+ {\
+ ("HW_OCOTP_"#a), ("HW_OCOTP_"#b), ("HW_OCOTP_"#c), ("HW_OCOTP_"#d), \
+ ("HW_OCOTP_"#e), ("HW_OCOTP_"#f), ("HW_OCOTP_"#g), ("HW_OCOTP_"#h) \
+ }
+
+#define BANKS (5)
+#define BANK_ITEMS (8)
+static const char *bank_reg_desc[BANKS][BANK_ITEMS] = {
+ BANK(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
+ BANK(MEM0, MEM1, MEM2, MEM3, MEM4, MEM5, GP0, GP1),
+ BANK(SCC0, SCC1, SCC2, SCC3, SCC4, SCC5, SCC6, SCC7),
+ BANK(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
+ BANK(SJC0, SJC1, MAC0, MAC1, HWCAP0, HWCAP1, HWCAP2, SWCAP),
+};
+
+static struct fsl_otp_data otp_data = {
+ .fuse_name = (char **)bank_reg_desc,
+ .fuse_num = BANKS * BANK_ITEMS,
+};
+#undef BANK
+#undef BANKS
+#undef BANK_ITEMS
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ mxc_set_cpu_type(MXC_CPU_MX50);
+
+ get_cpu_wp = mx50_arm2_get_cpu_wp;
+ set_num_cpu_wp = mx50_arm2_set_num_cpu_wp;
+}
+
+static void __init mx50_arm2_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx50_armadillo2, \
+ ARRAY_SIZE(mx50_armadillo2));
+
+ gpio_request(SD1_WP, "sdhc1-wp");
+ gpio_direction_input(SD1_WP);
+
+ gpio_request(SD1_CD, "sdhc1-cd");
+ gpio_direction_input(SD1_CD);
+
+ gpio_request(SD2_WP, "sdhc2-wp");
+ gpio_direction_input(SD2_WP);
+
+ gpio_request(SD2_CD, "sdhc2-cd");
+ gpio_direction_input(SD2_CD);
+
+ gpio_request(SD3_WP, "sdhc3-wp");
+ gpio_direction_input(SD3_WP);
+
+ gpio_request(SD3_CD, "sdhc3-cd");
+ gpio_direction_input(SD3_CD);
+
+ gpio_request(HP_DETECT, "hp-det");
+ gpio_direction_input(HP_DETECT);
+
+ gpio_request(PWR_INT, "pwr-int");
+ gpio_direction_input(PWR_INT);
+
+ gpio_request(EPDC_PMIC_WAKE, "epdc-pmic-wake");
+ gpio_direction_output(EPDC_PMIC_WAKE, 0);
+
+ gpio_request(EPDC_VCOM, "epdc-vcom");
+ gpio_direction_output(EPDC_VCOM, 0);
+
+ gpio_request(EPDC_PMIC_INT, "epdc-pmic-int");
+ gpio_direction_input(EPDC_PMIC_INT);
+
+ gpio_request(EPDC_PWRSTAT, "epdc-pwrstat");
+ gpio_direction_input(EPDC_PWRSTAT);
+
+ /* ELCDIF backlight */
+ gpio_request(EPDC_ELCDIF_BACKLIGHT, "elcdif-backlight");
+ gpio_direction_output(EPDC_ELCDIF_BACKLIGHT, 1);
+
+ if (enable_w1) {
+ struct pad_desc one_wire = MX50_PAD_OWIRE__OWIRE;
+ mxc_iomux_v3_setup_pad(&one_wire);
+ }
+
+ /* USB OTG PWR */
+ gpio_request(USB_OTG_PWR, "usb otg power");
+ gpio_direction_output(USB_OTG_PWR, 1);
+ gpio_set_value(USB_OTG_PWR, 0);
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ /* SD card detect irqs */
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(SD1_CD);
+ mxcsdhc2_device.resource[2].start = IOMUX_TO_IRQ_V3(SD2_CD);
+ mxcsdhc2_device.resource[2].end = IOMUX_TO_IRQ_V3(SD2_CD);
+ mxcsdhc3_device.resource[2].start = IOMUX_TO_IRQ_V3(SD3_CD);
+ mxcsdhc3_device.resource[2].end = IOMUX_TO_IRQ_V3(SD3_CD);
+
+ mxc_cpu_common_init();
+ mx50_arm2_io_init();
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxs_dma_apbh_device, &dma_apbh_data);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxcspi3_device, &mxcspi3_data);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[2], &mxci2c_data);
+
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_w1_master_device, &mxc_w1_data);
+ mxc_register_device(&gpu_device, &z160_revision);
+ mxc_register_device(&mxc_pxp_device, NULL);
+ mxc_register_device(&mxc_pxp_client_device, NULL);
+ mxc_register_device(&mxc_pxp_v4l2, NULL);
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+
+ /*
+ mxc_register_device(&mx53_lpmode_device, NULL);
+ mxc_register_device(&mxc_dvfs_per_device, &dvfs_per_data);
+ */
+
+/* mxc_register_device(&mxc_keypad_device, &keypad_plat_data); */
+
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc2_device, &mmc2_data);
+ mxc_register_device(&mxcsdhc3_device, &mmc3_data);
+ mxc_register_device(&mxc_ssi1_device, NULL);
+ mxc_register_device(&mxc_ssi2_device, NULL);
+ mxc_register_device(&mxc_fec_device, &fec_data);
+ spi_register_board_info(mxc_dataflash_device,
+ ARRAY_SIZE(mxc_dataflash_device));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+ mxc_register_device(&max17135_sensor_device, NULL);
+ mxc_register_device(&epdc_device, &epdc_data);
+ mxc_register_device(&lcd_wvga_device, &lcd_wvga_data);
+ mxc_register_device(&elcdif_device, &fb_data[0]);
+ mxc_register_device(&mxs_viim, NULL);
+
+ mx50_arm2_init_mc13892();
+/*
+ pm_power_off = mxc_power_off;
+ */
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+ mxc_register_device(&gpmi_nfc_device, &gpmi_nfc_platform_data);
+
+ mx5_set_otghost_vbus_func(mx50_arm2_usb_set_vbus);
+ mx5_usb_dr_init();
+ mx5_usbh1_init();
+
+ mxc_register_device(&mxc_rngb_device, NULL);
+ mxc_register_device(&dcp_device, NULL);
+ mxc_register_device(&fsl_otp_device, &otp_data);
+ if (cpu_is_mx50_rev(CHIP_REV_1_1) >= 1)
+ mxc_register_device(&mxc_zq_calib_device, NULL);
+ mxc_register_device(&mxc_perfmon, &mxc_perfmon_data);
+}
+
+static void __init mx50_arm2_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx50_clocks_init(32768, 24000000, 22579200);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(MX53_BASE_ADDR(UART1_BASE_ADDR), uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx50_arm2_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX50_ARM2 data structure.
+ */
+MACHINE_START(MX50_ARM2, "Freescale MX50 ARM2 Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx50_arm2_pmic_mc13892.c b/arch/arm/mach-mx5/mx50_arm2_pmic_mc13892.c
new file mode 100644
index 000000000000..014ec1a985d7
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_arm2_pmic_mc13892.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/pmic_external.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13892/core.h>
+#include <mach/irqs.h>
+
+#include <mach/iomux-mx50.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)
+
+/* Coin cell charger enable */
+#define COINCHEN_LSH 23
+#define COINCHEN_WID 1
+/* Coin cell charger voltage setting */
+#define VCOIN_LSH 20
+#define VCOIN_WID 3
+
+/* Coin Charger voltage */
+#define VCOIN_2_5V 0x0
+#define VCOIN_2_7V 0x1
+#define VCOIN_2_8V 0x2
+#define VCOIN_2_9V 0x3
+#define VCOIN_3_0V 0x4
+#define VCOIN_3_1V 0x5
+#define VCOIN_3_2V 0x6
+#define VCOIN_3_3V 0x7
+
+/* Keeps VSRTC and CLK32KMCU on for all states */
+#define DRM_LSH 4
+#define DRM_WID 1
+
+/* regulator standby mask */
+#define GEN1_STBY_MASK (1 << 1)
+#define IOHI_STBY_MASK (1 << 4)
+#define DIG_STBY_MASK (1 << 10)
+#define GEN2_STBY_MASK (1 << 13)
+#define PLL_STBY_MASK (1 << 16)
+#define USB2_STBY_MASK (1 << 19)
+
+#define GEN3_STBY_MASK (1 << 1)
+#define CAM_STBY_MASK (1 << 7)
+#define VIDEO_STBY_MASK (1 << 13)
+#define AUDIO_STBY_MASK (1 << 16)
+#define SD_STBY_MASK (1 << 19)
+
+#define REG_MODE_0_ALL_MASK (DIG_STBY_MASK | GEN1_STBY_MASK)
+#define REG_MODE_1_ALL_MASK (CAM_STBY_MASK | VIDEO_STBY_MASK |\
+ AUDIO_STBY_MASK | SD_STBY_MASK)
+
+/* switch mode setting */
+#define SW1MODE_LSB 0
+#define SW2MODE_LSB 10
+#define SW3MODE_LSB 0
+#define SW4MODE_LSB 8
+
+#define SWMODE_MASK 0xF
+#define SWMODE_AUTO 0x8
+
+/* CPU */
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ /* sgtl5000 */
+ .supply = "VDDA",
+ .dev_name = "1-000a",
+ },
+ {
+ /* sgtl5000 */
+ .supply = "VDDIO",
+ .dev_name = "1-000a",
+ },
+};
+
+struct mc13892;
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = mV_to_uV(600),
+ .max_uV = mV_to_uV(1375),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 850000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(1200),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ },
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .min_uV = mV_to_uV(2400),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .min_uV = mV_to_uV(2775),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ },
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = mV_to_uV(2300),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vsd_init = {
+ .constraints = {
+ .name = "VSD",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ .min_uV = mV_to_uV(3000),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vgen1_consumers),
+ .consumer_supplies = vgen1_consumers,
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(2900),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .name = "GPO1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo2_init = {
+ .constraints = {
+ .name = "GPO2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .name = "GPO3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo4_init = {
+ .constraints = {
+ .name = "GPO4",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static int mc13892_regulator_init(struct mc13892 *mc13892)
+{
+ unsigned int value, register_mask;
+ printk("Initializing regulators for mx50 arm2.\n");
+
+ /* enable standby controll for all regulators */
+ pmic_read_reg(REG_MODE_0, &value, 0xffffff);
+ value |= REG_MODE_0_ALL_MASK;
+ pmic_write_reg(REG_MODE_0, value, 0xffffff);
+
+ pmic_read_reg(REG_MODE_1, &value, 0xffffff);
+ value |= REG_MODE_1_ALL_MASK;
+ pmic_write_reg(REG_MODE_1, value, 0xffffff);
+
+ /* enable switch audo mode */
+ pmic_read_reg(REG_IDENTIFICATION, &value, 0xffffff);
+ /* only for mc13892 2.0A */
+ if ((value & 0x0000FFFF) == 0x45d0) {
+ pmic_read_reg(REG_SW_4, &value, 0xffffff);
+ register_mask = (SWMODE_MASK << SW1MODE_LSB) |
+ (SWMODE_MASK << SW2MODE_LSB);
+ value &= ~register_mask;
+ value |= (SWMODE_AUTO << SW1MODE_LSB) |
+ (SWMODE_AUTO << SW2MODE_LSB);
+ pmic_write_reg(REG_SW_4, value, 0xffffff);
+
+ pmic_read_reg(REG_SW_5, &value, 0xffffff);
+ register_mask = (SWMODE_MASK << SW3MODE_LSB) |
+ (SWMODE_MASK << SW4MODE_LSB);
+ value &= ~register_mask;
+ value |= (SWMODE_AUTO << SW3MODE_LSB) |
+ (SWMODE_AUTO << SW4MODE_LSB);
+ pmic_write_reg(REG_SW_5, value, 0xffffff);
+ }
+ /* Enable coin cell charger */
+ value = BITFVAL(COINCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V);
+ register_mask = BITFMASK(COINCHEN) | BITFMASK(VCOIN);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+
+#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE)
+ value = BITFVAL(DRM, 1);
+ register_mask = BITFMASK(DRM);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+#endif
+
+ mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init);
+ mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init);
+ mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init);
+ mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init);
+ mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init);
+ mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init);
+ mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init);
+ mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init);
+ mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init);
+ mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init);
+ mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init);
+ mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init);
+
+ regulator_has_full_constraints();
+
+ return 0;
+}
+
+static struct mc13892_platform_data mc13892_plat = {
+ .init = mc13892_regulator_init,
+};
+
+static struct spi_board_info __initdata mc13892_spi_device = {
+ .modalias = "pmic_spi",
+ .irq = IOMUX_TO_IRQ_V3(114),
+ .max_speed_hz = 6000000, /* max spi SCK clock speed in HZ */
+ .bus_num = 3,
+ .chip_select = 0,
+ .platform_data = &mc13892_plat,
+};
+
+
+int __init mx50_arm2_init_mc13892(void)
+{
+ return spi_register_board_info(&mc13892_spi_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx50_ddr_freq.S b/arch/arm/mach-mx5/mx50_ddr_freq.S
new file mode 100644
index 000000000000..38317675c52f
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_ddr_freq.S
@@ -0,0 +1,832 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * mx50_ddr_freq_change
+ *
+ * Idle the processor (eg, wait for interrupt).
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ */
+ENTRY(mx50_ddr_freq_change)
+ stmfd sp!, {r3,r4,r5,r6, r7} @ Save registers
+
+ mov r6, r0 @save CCM address
+ mov r5, r1 @save DataBahn address
+ mov r4, r2 @save new freq requested
+
+ /* Make sure no TLB miss will occur when the DDR is in self refresh. */
+ /* Invalidate TLB single entry to ensure that the address is not
+ * already in the TLB.
+ */
+ adr r3, LoopCKE2 @Address in this function.
+ mcr p15, 0, r3, c8, c7, 1 @ Make sure freq code address
+ @ is not already in TLB.
+ mcr p15, 0, r6, c8, c7, 1 @ Make sure CCM address
+ @ is not already in TLB.
+ mcr p15, 0, r5, c8, c7, 1 @ make sure Databahn address
+ @ is not already in TLB.
+ mrc p15, 0, r0, c10, c0, 0 @ Read the TLB lockdown register
+ orr r0, r0, #1 @ Set the Preserve bit.
+ mcr p15, 0, r0, c10, c0, 0 @ Write to the lockdown register
+ ldr r2, [r6] @ TLB will miss,
+ @CCM address will be loaded
+ ldr r2, [r5] @ TLB will miss,
+ @Databahn address will be loaded
+ ldr r2, [r3] @ TLB will miss
+ mrc p15, 0, r0, c10, c0, 0 @ Read the lockdown register
+ @ (victim will be incremented)
+ bic r0, r0, #1 @ Clear the preserve bit
+ mcr p15, 0, r0, c10, c0, 0 @ Write to the lockdown register.
+
+ /* If Databahn is in LPM4, exit that mode first. */
+ ldr r1,[r5, #0x50] @Store LPM mode in r1.
+ mov r0, r1
+ bic r0, #0x1F
+ str r0,[r5, #0x50]
+
+LoopCKE2:
+ /*Wait for CKE = 1 */
+ ldr r0,[r5, #0xfc]
+ and r0, r0, #0x10000
+ ldr r2, =0x10000
+ cmp r0, r2
+ bne LoopCKE2
+
+/* Wait for the databahn to idle
+ Meaning, no access to the databahn is
+ being made.
+*/
+NotIdle:
+ ldr r0,[r5, #0x13c]
+ and r0, r0, #0x100
+ ldr r2, =0x100
+ cmp r0, r2
+ beq NotIdle
+
+ /*
+ * Make sure the DDR is self-refresh, before switching its frequency
+ * and clock source
+ */
+
+ /* Step 1: Enter self-refresh mode */
+ ldr r0,[r5, #0x4c]
+ orr r0,r0,#0x1
+ str r0,[r5, #0x4c]
+
+ /* Step 2: Poll the CKE_STATUS bit. */
+LoopCKE0:
+ /* Wait for CKE = 0 */
+ ldr r0,[r5, #0xfc]
+ and r0, r0, #0x10000
+ ldr r2, =0x10000
+ cmp r0, r2
+ beq LoopCKE0
+
+ /* Step 3: Mask the DLL lock state change, set bit 8 in int_mask. */
+ ldr r0, [r5, #0xac]
+ orr r0, r0, #0x100
+ str r0, [r5, #0xac]
+
+ /* Step 4: Stop the Controller. */
+ ldr r0,[r5]
+ bic r0, r0, #0x1
+ str r0,[r5]
+
+ /* Step 5: Clear the DLL lock state change bit 8 in int_ack */
+ ldr r0, [r5, #0xa8]
+ orr r0, r0, #0x1000000
+ str r0, [r5, #0xa8]
+
+ /* Step 6: Clear the interrupt mask for DLL lock state.
+ * Bit 8 in int_mask */
+ ldr r0, [r5, #0xac]
+ bic r0, r0, #0x100
+ str r0, [r5, #0xac]
+
+ /* Change the freq now */
+ /* If the freq req is below 24MHz, set DDR to synchronous mode.
+ * else set to async mode. */
+ ldr r0, =24000000
+ cmp r4, r0
+ bgt Async_Mode
+
+ /* Set the DDR to be Synchronous
+ mode. */
+ /* Set the Databahn to sync mode. */
+ ldr r0, [r5, #0xdc]
+ orr r0, r0, #0x30000
+ str r0, [r5, #0xdc]
+
+ /* Turn OFF the DDR_CKLGATE_MASK in MXC_CCM_DDR */
+ ldr r0, [r6, #0x98]
+ bic r0, r0, #0xC0000000
+ str r0, [r6, #0x98]
+
+ /* Check if XTAL can source the DDR. */
+ ldr r0, =24000000
+ cmp r4, r0
+ ble databahn_ddr_24
+
+ /*Source DDR from PLL1. Setup the dividers accordingly. */
+ ldr r0, =800000000
+ ldr r3, =1
+Loop1:
+ sub r0, r0, r4
+ cmp r0, r4
+ blt Div_Found
+ add r3, r3, #1
+ bgt Loop1
+
+Div_Found:
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x3f
+ orr r0, r0, r3
+ str r0, [r6, #0x94]
+ /* Set the DDR to sourced from PLL1 in sync path */
+ ldr r0, [r6, #0x90]
+ orr r0, r0, #0x3
+ str r0, [r6, #0x90]
+
+ /* Turn OFF the DDR_CKLGATE_MASK in MXC_CCM_DDR */
+ ldr r0, [r6, #0x98]
+ bic r0, r0, #0xC0000000
+ str r0, [r6, #0x98]
+
+ ldr r0, =24000000
+ cmp r4, r0
+ beq databahn_ddr_24
+
+ b Ddr_not_24
+
+databahn_ddr_24:
+
+ /* Check for mDDR v LPDDR2 memory type */
+ ldr r0, [r5]
+ ldr r2, =0x100
+ and r0, r0, #0xF00
+ cmp r0, r2
+ beq mddr_24
+
+ /* LPDDR2 settings */
+ ldr r0, =0x00000003
+ str r0, [r5, #0x08]
+ ldr r0, =0x000012c0
+ str r0, [r5, #0x0c]
+ ldr r0, =0x00000018
+
+ str r0, [r5, #0x10]
+ ldr r0, =0x000000f0
+ str r0, [r5, #0x14]
+ ldr r0, =0x02030b0c
+ str r0, [r5, #0x18]
+ ldr r0, =0x02020104
+ str r0, [r5, #0x1c]
+
+ ldr r0, =0x05010102
+ str r0, [r5, #0x20]
+ ldr r0, =0x00068005
+ str r0, [r5, #0x24]
+ ldr r0, =0x01000103
+ str r0, [r5, #0x28]
+ ldr r0, =0x04030101
+ str r0, [r5, #0x2c]
+
+ ldr r0, =0x00000202
+ str r0, [r5, #0x34]
+ ldr r0, =0x00000001
+ str r0, [r5, #0x38]
+ ldr r0, =0x00000401
+ str r0, [r5, #0x3c]
+
+ /* Set TREF. */
+ ldr r0, =0x00030050
+ str r0, [r5, #0x40]
+ ldr r0, =0x00040004
+ str r0, [r5, #0x48]
+
+ ldr r0, =0x00040022
+ str r0, [r5, #0x6c]
+
+ ldr r0, =0x00040022
+ str r0, [r5, #0x78]
+
+ ldr r0, =0x00180000
+ str r0, [r5, #0x80]
+ ldr r0, =0x00000009
+ str r0, [r5, #0x84]
+ ldr r0, =0x02400003
+ str r0, [r5, #0x88]
+ ldr r0, =0x01000200
+ str r0, [r5, #0x8c]
+
+ ldr r0, =0x00000000
+ str r0, [r5, #0xcc]
+
+ ldr r0, =0x01010301
+ str r0, [r5, #0xd4]
+ ldr r0, =0x00000101
+ str r0, [r5, #0xd8]
+
+ ldr r0, =0x02000602
+ str r0, [r5, #0x104]
+ ldr r0, =0x00560000
+ str r0, [r5, #0x108]
+ ldr r0, =0x00560056
+ str r0, [r5, #0x10c]
+
+ ldr r0, =0x00560056
+ str r0, [r5, #0x110]
+ ldr r0, =0x03060056
+ str r0, [r5, #0x114]
+
+ /* Set the Databahn DLL in bypass mode */
+ /* PHY Register settings. */
+ ldr r0, =0x0
+ str r0, [r5, #0x200]
+ ldr r0, =0x0
+ str r0, [r5, #0x204]
+ ldr r0, =0xf3003a27
+ str r0, [r5, #0x208]
+ ldr r0, =0x074002c1
+ str r0, [r5, #0x20c]
+
+ ldr r0, =0xf3003a27
+ str r0, [r5, #0x210]
+ ldr r0, =0x074002c1
+ str r0, [r5, #0x214]
+ ldr r0, =0xf3003a27
+ str r0, [r5, #0x218]
+ ldr r0, =0x074002c1
+ str r0, [r5, #0x21c]
+
+ ldr r0, =0xf3003a27
+ str r0, [r5, #0x220]
+ ldr r0, =0x074002c1
+ str r0, [r5, #0x224]
+ ldr r0, =0xf3003a27
+ str r0, [r5, #0x228]
+ ldr r0, =0x074002c1
+ str r0, [r5, #0x22c]
+
+ ldr r0, =0x00810004
+ str r0, [r5, #0x234]
+ ldr r0, =0x30219fd3
+ str r0, [r5, #0x238]
+ ldr r0, =0x00219fc1
+ str r0, [r5, #0x23c]
+
+ ldr r0, =0x30219fd3
+ str r0, [r5, #0x240]
+ ldr r0, =0x00219fc1
+ str r0, [r5, #0x244]
+ ldr r0, =0x30219fd3
+ str r0, [r5, #0x248]
+ ldr r0, =0x00219fc1
+ str r0, [r5, #0x24c]
+
+ ldr r0, =0x30219fd3
+ str r0, [r5, #0x250]
+ ldr r0, =0x00219fc1
+ str r0, [r5, #0x254]
+ ldr r0, =0x30219fd3
+ str r0, [r5, #0x258]
+ ldr r0, =0x00219fc1
+ str r0, [r5, #0x25c]
+
+ b clocking
+
+/* mDDR settings */
+mddr_24:
+ ldr r0, =0x000012c0
+ str r0, [r5, #0x08]
+ ldr r0, =0x02000000
+ str r0, [r5, #0x14]
+ ldr r0, =0x01010506
+ str r0, [r5, #0x18]
+ ldr r0, =0x01020101
+ str r0, [r5, #0x1c]
+
+ ldr r0, =0x02000103
+ str r0, [r5, #0x20]
+ ldr r0, =0x01069002
+ str r0, [r5, #0x24]
+ ldr r0, =0x01000101
+ str r0, [r5, #0x28]
+ ldr r0, =0x02010101
+ str r0, [r5, #0x2c]
+
+ ldr r0, =0x00000602
+ str r0, [r5, #0x34]
+ ldr r0, =0x00000001
+ str r0, [r5, #0x38]
+ ldr r0, =0x00000301
+ str r0, [r5, #0x3c]
+
+ /* Set TREF. */
+ ldr r0, =0x000500b0
+ str r0, [r5, #0x40]
+ ldr r0, =0x00030003
+ str r0, [r5, #0x48]
+
+ ldr r0, =0x00000000
+ str r0, [r5, #0x6c]
+
+ ldr r0, =0x00000200
+ str r0, [r5, #0xd4]
+
+ ldr r0, =0x00b30000
+ str r0, [r5, #0x108]
+ ldr r0, =0x00b300b3
+ str r0, [r5, #0x10c]
+
+ ldr r0, =0x00b300b3
+ str r0, [r5, #0x110]
+ ldr r0, =0x010300b3
+ str r0, [r5, #0x114]
+
+ /* Set the Databahn DLL in bypass mode */
+ /* PHY Register settings. */
+ ldr r0, =0x00000100
+ str r0, [r5, #0x200]
+ ldr r0, =0x0
+ str r0, [r5, #0x204]
+ ldr r0, =0xf4003a27
+ str r0, [r5, #0x208]
+ ldr r0, =0x074002c0
+ str r0, [r5, #0x20c]
+
+ ldr r0, =0xf4003a27
+ str r0, [r5, #0x210]
+ ldr r0, =0x074002c0
+ str r0, [r5, #0x214]
+ ldr r0, =0xf4003a27
+ str r0, [r5, #0x218]
+ ldr r0, =0x074002c0
+ str r0, [r5, #0x21c]
+
+ ldr r0, =0xf4003a27
+ str r0, [r5, #0x220]
+ ldr r0, =0x074002c0
+ str r0, [r5, #0x224]
+ ldr r0, =0xf4003a27
+ str r0, [r5, #0x228]
+ ldr r0, =0x074002c0
+ str r0, [r5, #0x22c]
+
+ ldr r0, =0x00800005
+ str r0, [r5, #0x234]
+ ldr r0, =0x30319f14
+ str r0, [r5, #0x238]
+ ldr r0, =0x00319f01
+ str r0, [r5, #0x23c]
+
+ ldr r0, =0x30319f14
+ str r0, [r5, #0x240]
+ ldr r0, =0x00319f01
+ str r0, [r5, #0x244]
+ ldr r0, =0x30319f14
+ str r0, [r5, #0x248]
+ ldr r0, =0x00319f01
+ str r0, [r5, #0x24c]
+
+ ldr r0, =0x30319f14
+ str r0, [r5, #0x250]
+ ldr r0, =0x00319f01
+ str r0, [r5, #0x254]
+ ldr r0, =0x30319f14
+ str r0, [r5, #0x258]
+ ldr r0, =0x00319f01
+ str r0, [r5, #0x25c]
+
+clocking:
+ /* Set SYS_CLK to be sourced from 24MHz. */
+ /* Set the SYS_XTAL_DIV */
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x3c0
+ orr r0, r0, #0x40
+ str r0, [r6, #0x94]
+
+ /* Enable SYS_XTAL_CLKGATE. */
+ ldr r0, [r6, #0x94]
+ orr r0, r0, #0xC0000000
+ str r0, [r6, #0x94]
+
+ /* set SYS_CLK to be sourced from XTAL. */
+ ldr r0, [r6, #0x90]
+ bic r0, r0, #0x1
+ str r0, [r6, #0x90]
+
+ /* Disable SYS_PLL_CLKGATE.*/
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x30000000
+ str r0, [r6, #0x94]
+ b Setup_Done
+
+Async_Mode:
+ /* If SYS_CLK is running at 24MHz, increase
+ * it to 200MHz.
+ */
+ /* r7 indicates that we are moving from 133Mhz<-> 266MHz */
+ ldr r7, =1
+ ldr r0, [r6, #0x90]
+ and r0, r0, #0x1
+ cmp r0, #0
+ bne Sys_Clk_Not_24
+ ldr r7, =0
+
+ /* Disable SYS_PLL_CLKGATE. */
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x30000000
+ str r0, [r6, #0x94]
+
+ /* Set the new divider. */
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x3f
+ orr r0, r0, #4
+ str r0, [r6, #0x94]
+
+ /* Enable SYS_PLL_CLKGATE. */
+ ldr r0, [r6, #0x94]
+ orr r0, r0, #0x30000000
+ str r0, [r6, #0x94]
+
+ /* SYS_CLK to be sourced from PLL1. */
+ ldr r0, [r6, #0x90]
+ orr r0, r0, #0x3
+ str r0, [r6, #0x90]
+
+ /* Disable SYS_XTAL_CLKGATE. */
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0xC0000000
+ str r0, [r6, #0x94]
+
+Sys_Clk_Not_24:
+ /* Set the Databahn to async mode. */
+ ldr r0, [r5, #0xdc]
+ and r0, r0, #0xfffcffff
+ str r0, [r5, #0xdc]
+
+ /*Source DDR from PLL1. Setup the dividers accordingly. */
+ ldr r0, =800000000
+ ldr r3, =1
+Loop2:
+ sub r0, r0, r4
+ cmp r0, r4
+ blt Div_Found1
+ add r3, r3, #1
+ bgt Loop2
+
+Div_Found1:
+ /* Turn OFF the DDR_CKLGATE_MASK in MXC_CCM_DDR */
+ ldr r0, [r6, #0x98]
+ bic r0, r0, #0xC0000000
+ str r0, [r6, #0x98]
+
+ ldr r0, [r6, #0x98]
+ bic r0, r0, #0x3f
+ orr r0, r0, r3
+ str r0, [r6, #0x98]
+
+ /* Set the DDR to sourced from PLL1 in async path */
+ ldr r0, [r6, #0x98]
+ bic r0, r0, #0x40
+ str r0, [r6, #0x98]
+
+ /* Turn ON the DDR_CKLGATE_MASK in MXC_CCM_DDR */
+ ldr r0, [r6, #0x98]
+ orr r0, r0, #0xC0000000
+ str r0, [r6, #0x98]
+
+ ldr r0, =24000000
+ cmp r4, r0
+ beq databahn_ddr_24
+
+Ddr_not_24:
+ /* Check for mDDR v LPDDR2 memory type */
+ ldr r0, [r5]
+ ldr r2, =0x100
+ and r0, r0, #0xF00
+ cmp r0, r2
+ beq mddr_not_24
+
+ cmp r7, #1
+ beq just_set_tref
+
+ ldr r0, =0x0000001b
+ str r0, [r5, #0x8]
+ ldr r0, =0x0000d056
+ str r0, [r5, #0xc]
+
+ ldr r0, =0x0000010b
+ str r0, [r5, #0x10]
+ ldr r0, =0x00000a6b
+ str r0, [r5, #0x14]
+ ldr r0, =0x02030d0c
+ str r0, [r5, #0x18]
+ ldr r0, =0x0c110304
+ str r0, [r5, #0x1c]
+
+ ldr r0, =0x05020503
+ str r0, [r5, #0x20]
+ ldr r0, =0x0048D005
+ str r0, [r5, #0x24]
+ ldr r0, =0x01000403
+ str r0, [r5, #0x28]
+ ldr r0, =0x09040501
+ str r0, [r5, #0x2c]
+
+ ldr r0, =0x00000e02
+ str r0, [r5, #0x34]
+ ldr r0, =0x00000006
+ str r0, [r5, #0x38]
+ ldr r0, =0x00002301
+ str r0, [r5, #0x3c]
+
+just_set_tref:
+ ldr r0, =133333333
+ cmp r4, r0
+ bgt ddr_266
+ ldr r0, =0x00050180
+ b tref_done
+ddr_266:
+ ldr r0, =0x00050300
+tref_done:
+ str r0, [r5, #0x40]
+
+ cmp r7, #1
+ beq Setup_Done
+
+ ldr r0, =0x00260026
+ str r0, [r5, #0x48]
+
+ ldr r0, =0x00040042
+ str r0, [r5, #0x6c]
+
+ ldr r0, =0x00040042
+ str r0, [r5, #0x78]
+
+ ldr r0, =0x010b0000
+ str r0, [r5, #0x80]
+ ldr r0, =0x00000060
+ str r0, [r5, #0x84]
+ ldr r0, =0x02400018
+ str r0, [r5, #0x88]
+ ldr r0, =0x01000e00
+ str r0, [r5, #0x8c]
+
+ ldr r0, =0x01000000
+ str r0, [r5, #0xcc]
+
+ ldr r0, =0x00000200
+ str r0, [r5, #0xd4]
+ ldr r0, =0x00000102
+ str r0, [r5, #0xd8]
+
+ ldr r0, =0x02000802
+ str r0, [r5, #0x104]
+ ldr r0, =0x04080000
+ str r0, [r5, #0x108]
+ ldr r0, =0x04080408
+ str r0, [r5, #0x10c]
+
+ ldr r0, =0x04080408
+ str r0, [r5, #0x110]
+ ldr r0, =0x03060408
+ str r0, [r5, #0x114]
+
+ /* PHY setting for 266MHz */
+ ldr r0, =0x00000000
+ str r0, [r5, #0x200]
+ ldr r0, =0x00000000
+ str r0, [r5, #0x204]
+ ldr r0, =0xf5003a27
+ str r0, [r5, #0x208]
+
+ ldr r0, =0xf5003a27
+ str r0, [r5, #0x210]
+ ldr r0, =0xf5003a27
+ str r0, [r5, #0x218]
+
+ ldr r0, =0xf5003a27
+ str r0, [r5, #0x220]
+ ldr r0, =0xf5003a27
+ str r0, [r5, #0x228]
+
+ ldr r0, =0x074002e1
+ str r0, [r5, #0x20c]
+ ldr r0, =0x074002e1
+ str r0, [r5, #0x214]
+ ldr r0, =0x074002e1
+ str r0, [r5, #0x21c]
+ ldr r0, =0x074002e1
+ str r0, [r5, #0x224]
+ ldr r0, =0x074002e1
+ str r0, [r5, #0x22c]
+
+ ldr r0, =0x00810006
+ str r0, [r5, #0x234]
+ ldr r0, =0x60099414
+ str r0, [r5, #0x238]
+ ldr r0, =0x000a0b01
+ str r0, [r5, #0x23c]
+
+ ldr r0, =0x60099414
+ str r0, [r5, #0x240]
+ ldr r0, =0x000a0b01
+ str r0, [r5, #0x244]
+ ldr r0, =0x60099414
+ str r0, [r5, #0x248]
+ ldr r0, =0x000a0b01
+ str r0, [r5, #0x24c]
+
+ ldr r0, =0x60099414
+ str r0, [r5, #0x250]
+ ldr r0, =0x000a0b01
+ str r0, [r5, #0x254]
+ ldr r0, =0x60099414
+ str r0, [r5, #0x258]
+ ldr r0, =0x000a0b01
+ str r0, [r5, #0x25c]
+
+ b Setup_Done
+
+mddr_not_24:
+ /* mDDR settings */
+ cmp r7, #1
+ beq just_set_tref_mddr
+
+ ldr r0, =0x00009c40
+ str r0, [r5, #0x8]
+
+ ldr r0, =0x02000000
+ str r0, [r5, #0x14]
+ ldr r0, =0x01010706
+ str r0, [r5, #0x18]
+ ldr r0, =0x080b0201
+ str r0, [r5, #0x1c]
+
+ ldr r0, =0x02000303
+ str r0, [r5, #0x20]
+ ldr r0, =0x0136b002
+ str r0, [r5, #0x24]
+ ldr r0, =0x01000101
+ str r0, [r5, #0x28]
+ ldr r0, =0x06030301
+ str r0, [r5, #0x2c]
+
+ ldr r0, =0x00000a02
+ str r0, [r5, #0x34]
+ ldr r0, =0x00000003
+ str r0, [r5, #0x38]
+ ldr r0, =0x00001401
+ str r0, [r5, #0x3c]
+
+just_set_tref_mddr:
+ ldr r0, =133333333
+ cmp r4, r0
+ bgt mddr_200
+ ldr r0, =0x00050208
+ b tref_done1
+mddr_200:
+ ldr r0, =0x0005030f
+tref_done1:
+ str r0, [r5, #0x40]
+
+ cmp r7, #1
+ beq Setup_Done
+
+ ldr r0, =0x00180018
+ str r0, [r5, #0x48]
+
+ ldr r0, =0x00800000
+ str r0, [r5, #0x6c]
+
+ ldr r0, =0x02030302
+ str r0, [r5, #0xd4]
+
+ ldr r0, =0x06120000
+ str r0, [r5, #0x108]
+ ldr r0, =0x06120612
+ str r0, [r5, #0x10c]
+
+ ldr r0, =0x06120612
+ str r0, [r5, #0x110]
+ ldr r0, =0x01030612
+ str r0, [r5, #0x114]
+
+ /* PHY setting for 200 MHz */
+ ldr r0, =0x00000000
+ str r0, [r5, #0x200]
+ ldr r0, =0x00000000
+ str r0, [r5, #0x204]
+ ldr r0, =0xf5002725
+ str r0, [r5, #0x208]
+
+ ldr r0, =0xf5002725
+ str r0, [r5, #0x210]
+ ldr r0, =0xf5002725
+ str r0, [r5, #0x218]
+
+ ldr r0, =0xf5002725
+ str r0, [r5, #0x220]
+ ldr r0, =0xf5002725
+ str r0, [r5, #0x228]
+
+ ldr r0, =0x070002d0
+ str r0, [r5, #0x20c]
+ ldr r0, =0x074002d0
+ str r0, [r5, #0x214]
+ ldr r0, =0x074002d0
+ str r0, [r5, #0x21c]
+ ldr r0, =0x074002d0
+ str r0, [r5, #0x224]
+ ldr r0, =0x074002d0
+ str r0, [r5, #0x22c]
+
+ ldr r0, =0x00800006
+ str r0, [r5, #0x234]
+ ldr r0, =0x200e1014
+ str r0, [r5, #0x238]
+ ldr r0, =0x000d9f01
+ str r0, [r5, #0x23c]
+
+ ldr r0, =0x200e1014
+ str r0, [r5, #0x240]
+ ldr r0, =0x000d9f01
+ str r0, [r5, #0x244]
+ ldr r0, =0x200e1014
+ str r0, [r5, #0x248]
+ ldr r0, =0x000d9f01
+ str r0, [r5, #0x24c]
+
+ ldr r0, =0x200e1014
+ str r0, [r5, #0x250]
+ ldr r0, =0x000d9f01
+ str r0, [r5, #0x254]
+ ldr r0, =0x200e1014
+ str r0, [r5, #0x258]
+ ldr r0, =0x000d9f01
+ str r0, [r5, #0x25c]
+
+Setup_Done:
+ /* Start controller */
+ ldr r0,[r5]
+ orr r0, r0,#0x1
+ str r0,[r5]
+
+ /* Poll the DLL lock state change in int_status reg*/
+ /* DLL is bypassed in the 24MHz mode, so no waiting for DLL to lock. */
+ ldr r0, =24000000
+ cmp r4, r0
+ beq Exit_Self_Refresh
+
+DllLock:
+ ldr r0, [r5, #0xa8]
+ and r0, r0, #0x100
+ ldr r2, =0x100
+ cmp r0, r2
+ bne DllLock
+
+ /*Leave self-refresh mode */
+Exit_Self_Refresh:
+ ldr r0,[r5, #0x4c]
+ and r0,r0,#0xfffffffe
+ str r0,[r5, #0x4c]
+
+LoopCKE1:
+ /*Wait for CKE = 1 */
+ ldr r0,[r5, #0xfc]
+ and r0, r0, #0x10000
+ ldr r2, =0x10000
+ cmp r0, r2
+ bne LoopCKE1
+
+ /* Put the databahn back to into the LPM mode. */
+ str r1,[r5, #0x50]
+
+ /* Restore registers */
+ ldmfd sp!, {r3,r4,r5,r6, r7}
+ mov pc, lr
+
+ .type mx50_do_ddr_freq_change, #object
+ENTRY(mx50_do_ddr_freq_change)
+ .word mx50_ddr_freq_change
+ .size mx50_ddr_freq_change, . - mx50_ddr_freq_change
diff --git a/arch/arm/mach-mx5/mx50_rdp.c b/arch/arm/mach-mx5/mx50_rdp.c
new file mode 100644
index 000000000000..f5b64400f4a5
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_rdp.c
@@ -0,0 +1,1595 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/max17135.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/videodev2.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/gpmi-nfc.h>
+#include <linux/powerkey.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/keypad.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/memory.h>
+#include <mach/arc_otg.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/iomux-mx50.h>
+#include <mach/i2c.h>
+
+#include "devices.h"
+#include "usb.h"
+#include "crm_regs.h"
+#include "dma-apbh.h"
+
+#define SD1_WP (3*32 + 19) /*GPIO_4_19 */
+#define SD1_CD (0*32 + 27) /*GPIO_1_27 */
+#define SD2_WP (4*32 + 16) /*GPIO_5_16 */
+#define SD2_CD (4*32 + 17) /*GPIO_5_17 */
+#define HP_DETECT (3*32 + 15) /*GPIO_4_15 */
+#define PWR_INT (3*32 + 18) /*GPIO_4_18 */
+#define EPDC_D0 (2*32 + 0) /*GPIO_3_0 */
+#define EPDC_D1 (2*32 + 1) /*GPIO_3_1 */
+#define EPDC_D2 (2*32 + 2) /*GPIO_3_2 */
+#define EPDC_D3 (2*32 + 3) /*GPIO_3_3 */
+#define EPDC_D4 (2*32 + 4) /*GPIO_3_4 */
+#define EPDC_D5 (2*32 + 5) /*GPIO_3_5 */
+#define EPDC_D6 (2*32 + 6) /*GPIO_3_6 */
+#define EPDC_D7 (2*32 + 7) /*GPIO_3_7 */
+#define EPDC_GDCLK (2*32 + 16) /*GPIO_3_16 */
+#define EPDC_GDSP (2*32 + 17) /*GPIO_3_17 */
+#define EPDC_GDOE (2*32 + 18) /*GPIO_3_18 */
+#define EPDC_GDRL (2*32 + 19) /*GPIO_3_19 */
+#define EPDC_SDCLK (2*32 + 20) /*GPIO_3_20 */
+#define EPDC_SDOE (2*32 + 23) /*GPIO_3_23 */
+#define EPDC_SDLE (2*32 + 24) /*GPIO_3_24 */
+#define EPDC_SDSHR (2*32 + 26) /*GPIO_3_26 */
+#define EPDC_BDR0 (3*32 + 23) /*GPIO_4_23 */
+#define EPDC_SDCE0 (3*32 + 25) /*GPIO_4_25 */
+#define EPDC_SDCE1 (3*32 + 26) /*GPIO_4_26 */
+#define EPDC_SDCE2 (3*32 + 27) /*GPIO_4_27 */
+#define EPDC_PMIC_WAKE (5*32 + 16) /*GPIO_6_16 */
+#define EPDC_PMIC_INT (5*32 + 17) /*GPIO_6_17 */
+#define EPDC_VCOM (3*32 + 21) /*GPIO_4_21 */
+#define EPDC_PWRSTAT (2*32 + 28) /*GPIO_3_28 */
+#define ELCDIF_PWR_ON (1*32 + 21) /*GPIO_2_21 */
+#define ELCDIF_DAT0_DUMMY (0*32 + 0) /*GPIO_1_0 */
+#define ELCDIF_DAT1_DUMMY (0*32 + 1) /*GPIO_1_1 */
+#define ELCDIF_DAT2_DUMMY (0*32 + 2) /*GPIO_1_2 */
+#define ELCDIF_DAT8_DUMMY (0*32 + 3) /*GPIO_1_3 */
+#define ELCDIF_DAT9_DUMMY (0*32 + 4) /*GPIO_1_4 */
+#define ELCDIF_DAT16_DUMMY (0*32 + 5) /*GPIO_1_5 */
+#define ELCDIF_DAT17_DUMMY (0*32 + 6) /*GPIO_1_6 */
+#define ELCDIF_DAT18_DUMMY (0*32 + 7) /*GPIO_1_7 */
+#define CSPI_CS1 (3*32 + 13) /*GPIO_4_13 */
+#define CSPI_CS2 (3*32 + 11) /*GPIO_4_11*/
+#define SGTL_OSCEN (5*32 + 8) /*GPIO_6_8*/
+#define SGTL_AMP_SHDN (5*32 + 15) /*GPIO_6_15*/
+#define FEC_EN (5*32 + 23) /*GPIO_6_23*/
+#define FEC_RESET_B (3*32 + 12) /*GPIO_4_12*/
+#define USB_OTG_PWR (5*32 + 25) /*GPIO_6_25*/
+
+extern int __init mx50_rdp_init_mc13892(void);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+static int max17135_regulator_init(struct max17135 *max17135);
+static int num_cpu_wp = 2;
+
+static struct pad_desc mx50_rdp[] = {
+ /* SD1 */
+ MX50_PAD_ECSPI2_SS0__GPIO_4_19,
+ MX50_PAD_EIM_CRE__GPIO_1_27,
+ MX50_PAD_SD1_CMD__SD1_CMD,
+
+ MX50_PAD_SD1_CLK__SD1_CLK,
+ MX50_PAD_SD1_D0__SD1_D0,
+ MX50_PAD_SD1_D1__SD1_D1,
+ MX50_PAD_SD1_D2__SD1_D2,
+ MX50_PAD_SD1_D3__SD1_D3,
+
+ /* SD2 */
+ MX50_PAD_SD2_CD__GPIO_5_17,
+ MX50_PAD_SD2_WP__GPIO_5_16,
+ MX50_PAD_SD2_CMD__SD2_CMD,
+ MX50_PAD_SD2_CLK__SD2_CLK,
+ MX50_PAD_SD2_D0__SD2_D0,
+ MX50_PAD_SD2_D1__SD2_D1,
+ MX50_PAD_SD2_D2__SD2_D2,
+ MX50_PAD_SD2_D3__SD2_D3,
+ MX50_PAD_SD2_D4__SD2_D4,
+ MX50_PAD_SD2_D5__SD2_D5,
+ MX50_PAD_SD2_D6__SD2_D6,
+ MX50_PAD_SD2_D7__SD2_D7,
+
+ /* SD3 */
+ MX50_PAD_SD3_CMD__SD3_CMD,
+ MX50_PAD_SD3_CLK__SD3_CLK,
+ MX50_PAD_SD3_D0__SD3_D0,
+ MX50_PAD_SD3_D1__SD3_D1,
+ MX50_PAD_SD3_D2__SD3_D2,
+ MX50_PAD_SD3_D3__SD3_D3,
+ MX50_PAD_SD3_D4__SD3_D4,
+ MX50_PAD_SD3_D5__SD3_D5,
+ MX50_PAD_SD3_D6__SD3_D6,
+ MX50_PAD_SD3_D7__SD3_D7,
+
+ MX50_PAD_SSI_RXD__SSI_RXD,
+ MX50_PAD_SSI_TXD__SSI_TXD,
+ MX50_PAD_SSI_TXC__SSI_TXC,
+ MX50_PAD_SSI_TXFS__SSI_TXFS,
+
+ /* HP_DET_B (headphone detect) */
+ MX50_PAD_ECSPI1_SS0__GPIO_4_15,
+
+ /* PWR_INT */
+ MX50_PAD_ECSPI2_MISO__GPIO_4_18,
+
+ /* UART pad setting */
+ MX50_PAD_UART1_TXD__UART1_TXD,
+ MX50_PAD_UART1_RXD__UART1_RXD,
+ MX50_PAD_UART1_RTS__UART1_RTS,
+ MX50_PAD_UART2_TXD__UART2_TXD,
+ MX50_PAD_UART2_RXD__UART2_RXD,
+ MX50_PAD_UART2_CTS__UART2_CTS,
+ MX50_PAD_UART2_RTS__UART2_RTS,
+
+ MX50_PAD_I2C1_SCL__I2C1_SCL,
+ MX50_PAD_I2C1_SDA__I2C1_SDA,
+ MX50_PAD_I2C2_SCL__I2C2_SCL,
+ MX50_PAD_I2C2_SDA__I2C2_SDA,
+
+ /* EPDC pins */
+ MX50_PAD_EPDC_D0__EPDC_D0,
+ MX50_PAD_EPDC_D1__EPDC_D1,
+ MX50_PAD_EPDC_D2__EPDC_D2,
+ MX50_PAD_EPDC_D3__EPDC_D3,
+ MX50_PAD_EPDC_D4__EPDC_D4,
+ MX50_PAD_EPDC_D5__EPDC_D5,
+ MX50_PAD_EPDC_D6__EPDC_D6,
+ MX50_PAD_EPDC_D7__EPDC_D7,
+ MX50_PAD_EPDC_GDCLK__EPDC_GDCLK,
+ MX50_PAD_EPDC_GDSP__EPDC_GDSP,
+ MX50_PAD_EPDC_GDOE__EPDC_GDOE ,
+ MX50_PAD_EPDC_GDRL__EPDC_GDRL,
+ MX50_PAD_EPDC_SDCLK__EPDC_SDCLK,
+ MX50_PAD_EPDC_SDOE__EPDC_SDOE,
+ MX50_PAD_EPDC_SDLE__EPDC_SDLE,
+ MX50_PAD_EPDC_SDSHR__EPDC_SDSHR,
+ MX50_PAD_EPDC_BDR0__EPDC_BDR0,
+ MX50_PAD_EPDC_SDCE0__EPDC_SDCE0,
+ MX50_PAD_EPDC_SDCE1__EPDC_SDCE1,
+ MX50_PAD_EPDC_SDCE2__EPDC_SDCE2,
+
+ MX50_PAD_EPDC_PWRSTAT__GPIO_3_28,
+ MX50_PAD_EPDC_VCOM0__GPIO_4_21,
+
+ MX50_PAD_DISP_D8__DISP_D8,
+ MX50_PAD_DISP_D9__DISP_D9,
+ MX50_PAD_DISP_D10__DISP_D10,
+ MX50_PAD_DISP_D11__DISP_D11,
+ MX50_PAD_DISP_D12__DISP_D12,
+ MX50_PAD_DISP_D13__DISP_D13,
+ MX50_PAD_DISP_D14__DISP_D14,
+ MX50_PAD_DISP_D15__DISP_D15,
+ MX50_PAD_DISP_RS__ELCDIF_VSYNC,
+
+ /* ELCDIF contrast */
+ MX50_PAD_PWM1__PWMO,
+
+ /* ELCDIF power on */
+ MX50_PAD_DISP_CS__GPIO_2_21,
+
+ MX50_PAD_DISP_BUSY__ELCDIF_HSYNC,
+ MX50_PAD_DISP_RD__ELCDIF_EN,
+ MX50_PAD_DISP_WR__ELCDIF_PIXCLK,
+
+ /* EPD PMIC WAKEUP */
+ MX50_PAD_UART4_TXD__GPIO_6_16,
+
+ /* EPD PMIC intr */
+ MX50_PAD_UART4_RXD__GPIO_6_17,
+
+ MX50_PAD_EPITO__USBH1_PWR,
+ /* Need to comment below line if
+ * one needs to debug owire.
+ */
+ MX50_PAD_OWIRE__USBH1_OC,
+ /* using gpio to control otg pwr */
+ MX50_PAD_PWM2__GPIO_6_25,
+ MX50_PAD_I2C3_SCL__USBOTG_OC,
+
+ MX50_PAD_SSI_RXC__FEC_MDIO,
+ MX50_PAD_SSI_RXC__FEC_MDIO,
+ MX50_PAD_DISP_D0__FEC_TXCLK,
+ MX50_PAD_DISP_D1__FEC_RX_ER,
+ MX50_PAD_DISP_D2__FEC_RX_DV,
+ MX50_PAD_DISP_D3__FEC_RXD1,
+ MX50_PAD_DISP_D4__FEC_RXD0,
+ MX50_PAD_DISP_D5__FEC_TX_EN,
+ MX50_PAD_DISP_D6__FEC_TXD1,
+ MX50_PAD_DISP_D7__FEC_TXD0,
+ MX50_PAD_SSI_RXFS__FEC_MDC,
+ MX50_PAD_I2C3_SDA__GPIO_6_23,
+ MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
+
+ MX50_PAD_CSPI_SS0__CSPI_SS0,
+ MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
+ MX50_PAD_CSPI_MOSI__CSPI_MOSI,
+ MX50_PAD_CSPI_MISO__CSPI_MISO,
+
+ /* SGTL500_OSC_EN */
+ MX50_PAD_UART1_CTS__GPIO_6_8,
+
+ /* SGTL_AMP_SHDN */
+ MX50_PAD_UART3_RXD__GPIO_6_15,
+
+ /* Keypad */
+ MX50_PAD_KEY_COL0__KEY_COL0,
+ MX50_PAD_KEY_ROW0__KEY_ROW0,
+ MX50_PAD_KEY_COL1__KEY_COL1,
+ MX50_PAD_KEY_ROW1__KEY_ROW1,
+ MX50_PAD_KEY_COL2__KEY_COL2,
+ MX50_PAD_KEY_ROW2__KEY_ROW2,
+ MX50_PAD_KEY_COL3__KEY_COL3,
+ MX50_PAD_KEY_ROW3__KEY_ROW3,
+ MX50_PAD_EIM_DA0__KEY_COL4,
+ MX50_PAD_EIM_DA1__KEY_ROW4,
+ MX50_PAD_EIM_DA2__KEY_COL5,
+ MX50_PAD_EIM_DA3__KEY_ROW5,
+ MX50_PAD_EIM_DA4__KEY_COL6,
+ MX50_PAD_EIM_DA5__KEY_ROW6,
+ MX50_PAD_EIM_DA6__KEY_COL7,
+ MX50_PAD_EIM_DA7__KEY_ROW7,
+ /*EIM pads */
+ MX50_PAD_EIM_DA8__GPIO_1_8,
+ MX50_PAD_EIM_DA9__GPIO_1_9,
+ MX50_PAD_EIM_DA10__GPIO_1_10,
+ MX50_PAD_EIM_DA11__GPIO_1_11,
+ MX50_PAD_EIM_DA12__GPIO_1_12,
+ MX50_PAD_EIM_DA13__GPIO_1_13,
+ MX50_PAD_EIM_DA14__GPIO_1_14,
+ MX50_PAD_EIM_DA15__GPIO_1_15,
+ MX50_PAD_EIM_CS2__GPIO_1_16,
+ MX50_PAD_EIM_CS1__GPIO_1_17,
+ MX50_PAD_EIM_CS0__GPIO_1_18,
+ MX50_PAD_EIM_EB0__GPIO_1_19,
+ MX50_PAD_EIM_EB1__GPIO_1_20,
+ MX50_PAD_EIM_WAIT__GPIO_1_21,
+ MX50_PAD_EIM_BCLK__GPIO_1_22,
+ MX50_PAD_EIM_RDY__GPIO_1_23,
+ MX50_PAD_EIM_OE__GPIO_1_24,
+ MX50_PAD_EIM_RW__GPIO_1_25,
+ MX50_PAD_EIM_LBA__GPIO_1_26,
+};
+
+static struct pad_desc mx50_gpmi_nand[] = {
+ MX50_PIN_EIM_DA8__NANDF_CLE,
+ MX50_PIN_EIM_DA9__NANDF_ALE,
+ MX50_PIN_EIM_DA10__NANDF_CE0,
+ MX50_PIN_EIM_DA11__NANDF_CE1,
+ MX50_PIN_EIM_DA12__NANDF_CE2,
+ MX50_PIN_EIM_DA13__NANDF_CE3,
+ MX50_PIN_EIM_DA14__NANDF_READY,
+ MX50_PIN_EIM_DA15__NANDF_DQS,
+ MX50_PIN_SD3_D4__NANDF_D0,
+ MX50_PIN_SD3_D5__NANDF_D1,
+ MX50_PIN_SD3_D6__NANDF_D2,
+ MX50_PIN_SD3_D7__NANDF_D3,
+ MX50_PIN_SD3_D0__NANDF_D4,
+ MX50_PIN_SD3_D1__NANDF_D5,
+ MX50_PIN_SD3_D2__NANDF_D6,
+ MX50_PIN_SD3_D3__NANDF_D7,
+ MX50_PIN_SD3_CLK__NANDF_RDN,
+ MX50_PIN_SD3_CMD__NANDF_WRN,
+ MX50_PIN_SD3_WP__NANDF_RESETN,
+};
+
+static struct pad_desc suspend_enter_pads[] = {
+ MX50_PAD_EIM_DA0__GPIO_1_0,
+ MX50_PAD_EIM_DA1__GPIO_1_1,
+ MX50_PAD_EIM_DA2__GPIO_1_2,
+ MX50_PAD_EIM_DA3__GPIO_1_3,
+ MX50_PAD_EIM_DA4__GPIO_1_4,
+ MX50_PAD_EIM_DA5__GPIO_1_5,
+ MX50_PAD_EIM_DA6__GPIO_1_6,
+ MX50_PAD_EIM_DA7__GPIO_1_7,
+
+ MX50_PAD_EIM_DA8__GPIO_1_8,
+ MX50_PAD_EIM_DA9__GPIO_1_9,
+ MX50_PAD_EIM_DA10__GPIO_1_10,
+ MX50_PAD_EIM_DA11__GPIO_1_11,
+ MX50_PAD_EIM_DA12__GPIO_1_12,
+ MX50_PAD_EIM_DA13__GPIO_1_13,
+ MX50_PAD_EIM_DA14__GPIO_1_14,
+ MX50_PAD_EIM_DA15__GPIO_1_15,
+ MX50_PAD_EIM_CS2__GPIO_1_16,
+ MX50_PAD_EIM_CS1__GPIO_1_17,
+ MX50_PAD_EIM_CS0__GPIO_1_18,
+ MX50_PAD_EIM_EB0__GPIO_1_19,
+ MX50_PAD_EIM_EB1__GPIO_1_20,
+ MX50_PAD_EIM_WAIT__GPIO_1_21,
+ MX50_PAD_EIM_BCLK__GPIO_1_22,
+ MX50_PAD_EIM_RDY__GPIO_1_23,
+ MX50_PAD_EIM_OE__GPIO_1_24,
+ MX50_PAD_EIM_RW__GPIO_1_25,
+ MX50_PAD_EIM_LBA__GPIO_1_26,
+ MX50_PAD_EIM_CRE__GPIO_1_27,
+
+ /* NVCC_NANDF pads */
+ MX50_PAD_DISP_D8__GPIO_2_8,
+ MX50_PAD_DISP_D9__GPIO_2_9,
+ MX50_PAD_DISP_D10__GPIO_2_10,
+ MX50_PAD_DISP_D11__GPIO_2_11,
+ MX50_PAD_DISP_D12__GPIO_2_12,
+ MX50_PAD_DISP_D13__GPIO_2_13,
+ MX50_PAD_DISP_D14__GPIO_2_14,
+ MX50_PAD_DISP_D15__GPIO_2_15,
+ MX50_PAD_SD3_CMD__GPIO_5_18,
+ MX50_PAD_SD3_CLK__GPIO_5_19,
+ MX50_PAD_SD3_D0__GPIO_5_20,
+ MX50_PAD_SD3_D1__GPIO_5_21,
+ MX50_PAD_SD3_D2__GPIO_5_22,
+ MX50_PAD_SD3_D3__GPIO_5_23,
+ MX50_PAD_SD3_D4__GPIO_5_24,
+ MX50_PAD_SD3_D5__GPIO_5_25,
+ MX50_PAD_SD3_D6__GPIO_5_26,
+ MX50_PAD_SD3_D7__GPIO_5_27,
+ MX50_PAD_SD3_WP__GPIO_5_28,
+
+ /* NVCC_LCD pads */
+ MX50_PAD_DISP_D0__GPIO_2_0,
+ MX50_PAD_DISP_D1__GPIO_2_1,
+ MX50_PAD_DISP_D2__GPIO_2_2,
+ MX50_PAD_DISP_D3__GPIO_2_3,
+ MX50_PAD_DISP_D4__GPIO_2_4,
+ MX50_PAD_DISP_D5__GPIO_2_5,
+ MX50_PAD_DISP_D6__GPIO_2_6,
+ MX50_PAD_DISP_D7__GPIO_2_7,
+ MX50_PAD_DISP_WR__GPIO_2_16,
+ MX50_PAD_DISP_RS__GPIO_2_17,
+ MX50_PAD_DISP_BUSY__GPIO_2_18,
+ MX50_PAD_DISP_RD__GPIO_2_19,
+ MX50_PAD_DISP_RESET__GPIO_2_20,
+ MX50_PAD_DISP_CS__GPIO_2_21,
+
+ /* CSPI pads */
+ MX50_PAD_CSPI_SCLK__GPIO_4_8,
+ MX50_PAD_CSPI_MOSI__GPIO_4_9,
+ MX50_PAD_CSPI_MISO__GPIO_4_10,
+ MX50_PAD_CSPI_SS0__GPIO_4_11,
+
+ /*NVCC_MISC pins as GPIO */
+ MX50_PAD_I2C1_SCL__GPIO_6_18,
+ MX50_PAD_I2C1_SDA__GPIO_6_19,
+ MX50_PAD_I2C2_SCL__GPIO_6_20,
+ MX50_PAD_I2C2_SDA__GPIO_6_21,
+ MX50_PAD_I2C3_SCL__GPIO_6_22,
+ MX50_PAD_I2C3_SDA__GPIO_6_23,
+
+ /* NVCC_MISC_PWM_USB_OTG pins */
+ MX50_PAD_PWM1__GPIO_6_24,
+ MX50_PAD_PWM2__GPIO_6_25,
+ MX50_PAD_EPITO__GPIO_6_27,
+ MX50_PAD_WDOG__GPIO_6_28,
+
+ /* FEC related. */
+ MX50_PAD_EPDC_D10__GPIO_3_10,
+ MX50_PAD_SSI_RXC__GPIO_6_5,
+ MX50_PAD_SSI_RXFS__GPIO_6_4,
+};
+
+static struct pad_desc suspend_exit_pads[ARRAY_SIZE(suspend_enter_pads)];
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "SW1",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 80,
+ .num_wp = 2,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "SW1",
+ .lp_reg_id = "SW2",
+};
+
+/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */
+static struct cpu_wp cpu_wp_auto[] = {
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1050000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 160000000,
+ .pdf = 4,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 4,
+ .cpu_voltage = 850000,},
+};
+
+static struct cpu_wp *mx50_rdp_get_cpu_wp(int *wp)
+{
+ *wp = num_cpu_wp;
+ return cpu_wp_auto;
+}
+
+static void mx50_rdp_set_num_cpu_wp(int num)
+{
+ num_cpu_wp = num;
+ return;
+}
+
+static struct mxc_w1_config mxc_w1_data = {
+ .search_rom_accelerator = 1,
+};
+
+static struct fec_platform_data fec_data = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static u16 keymapping[] = {
+ KEY_9, KEY_0, KEY_O, KEY_P, KEY_L, KEY_DELETE, KEY_SLASH, KEY_ENTER,
+ KEY_F4, KEY_F1, KEY_F6, KEY_F9, KEY_F5, KEY_BACKSPACE, KEY_MENU, 0,
+ KEY_PREVIOUS, KEY_NEXT, KEY_HOME, KEY_NEXT, KEY_F2, KEY_F3, KEY_F8, KEY_F7,
+ KEY_F11, KEY_CAPSLOCK, KEY_SPACE, KEY_SPACE, KEY_LEFTALT, KEY_LEFTSHIFT, 0, 0,
+ KEY_COMMA, KEY_M, KEY_N, KEY_B, KEY_V, KEY_C, KEY_X, KEY_Z,
+ KEY_K, KEY_J, KEY_H, KEY_G, KEY_F, KEY_D, KEY_S, KEY_A,
+ KEY_I, KEY_U, KEY_Y, KEY_T, KEY_R, KEY_E, KEY_W, KEY_Q,
+ KEY_8, KEY_7, KEY_6, KEY_5, KEY_4, KEY_3, KEY_2, KEY_1
+};
+
+static struct keypad_data keypad_plat_data = {
+ .rowmax = 8,
+ .colmax = 8,
+ .irq = MXC_INT_KPP,
+ .learning = 0,
+ .delay = 2,
+ .matrix = keymapping,
+};
+
+
+/* workaround for cspi chipselect pin may not keep correct level when idle */
+static void mx50_rdp_gpio_spi_chipselect_active(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 3:
+ switch (chipselect) {
+ case 0x1:
+ {
+ struct pad_desc cspi_ss0 = MX50_PAD_CSPI_SS0__CSPI_SS0;
+ struct pad_desc cspi_cs1 =
+ MX50_PAD_ECSPI1_MOSI__GPIO_4_13;
+
+ /* pull up/down deassert it */
+ mxc_iomux_v3_setup_pad(&cspi_ss0);
+ mxc_iomux_v3_setup_pad(&cspi_cs1);
+
+ gpio_request(CSPI_CS1, "cspi-cs1");
+ gpio_direction_input(CSPI_CS1);
+ }
+ break;
+ case 0x2:
+ {
+ struct pad_desc cspi_ss1 =
+ MX50_PAD_ECSPI1_MOSI__CSPI_SS1;
+ struct pad_desc cspi_ss0 = MX50_PAD_CSPI_SS0__GPIO_4_11;
+
+ /*disable other ss */
+ mxc_iomux_v3_setup_pad(&cspi_ss1);
+ mxc_iomux_v3_setup_pad(&cspi_ss0);
+
+ /* pull up/down deassert it */
+ gpio_request(CSPI_CS2, "cspi-cs2");
+ gpio_direction_input(CSPI_CS2);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void mx50_rdp_gpio_spi_chipselect_inactive(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ break;
+ case 2:
+ break;
+ case 3:
+ switch (chipselect) {
+ case 0x1:
+ gpio_free(CSPI_CS1);
+ break;
+ case 0x2:
+ gpio_free(CSPI_CS2);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+}
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+ .chipselect_active = mx50_rdp_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx50_rdp_gpio_spi_chipselect_inactive,
+};
+
+static struct mxc_spi_master mxcspi3_data = {
+ .maxchipselect = 4,
+ .spi_version = 7,
+ .chipselect_active = mx50_rdp_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx50_rdp_gpio_spi_chipselect_inactive,
+};
+
+#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)
+
+static struct regulator_init_data max17135_init_data[] __initdata = {
+ {
+ .constraints = {
+ .name = "DISPLAY",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ }, {
+ .constraints = {
+ .name = "GVDD",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "GVEE",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINN",
+ .min_uV = V_to_uV(-22),
+ .max_uV = V_to_uV(-22),
+ },
+ }, {
+ .constraints = {
+ .name = "HVINP",
+ .min_uV = V_to_uV(20),
+ .max_uV = V_to_uV(20),
+ },
+ }, {
+ .constraints = {
+ .name = "VCOM",
+ .min_uV = mV_to_uV(-4325),
+ .max_uV = mV_to_uV(-500),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ }, {
+ .constraints = {
+ .name = "VNEG",
+ .min_uV = V_to_uV(-15),
+ .max_uV = V_to_uV(-15),
+ },
+ }, {
+ .constraints = {
+ .name = "VPOS",
+ .min_uV = V_to_uV(15),
+ .max_uV = V_to_uV(15),
+ },
+ },
+};
+
+/* Fixed voltage regulator DCDC_3V15 */
+static struct regulator_consumer_supply fixed_volt_reg_consumers[] = {
+ {
+ /* sgtl5000 */
+ .supply = "VDDIO",
+ .dev_name = "1-000a",
+ },
+};
+
+static struct regulator_init_data fixed_volt_reg_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(fixed_volt_reg_consumers),
+ .consumer_supplies = fixed_volt_reg_consumers,
+};
+
+static struct fixed_voltage_config fixed_volt_reg_pdata = {
+ .supply_name = "DCDC_3V15",
+ .microvolts = 3150000,
+ .init_data = &fixed_volt_reg_init_data,
+ .gpio = -EINVAL,
+};
+
+static void epdc_get_pins(void)
+{
+ /* Claim GPIOs for EPDC pins - used during power up/down */
+ gpio_request(EPDC_D0, "epdc_d0");
+ gpio_request(EPDC_D1, "epdc_d1");
+ gpio_request(EPDC_D2, "epdc_d2");
+ gpio_request(EPDC_D3, "epdc_d3");
+ gpio_request(EPDC_D4, "epdc_d4");
+ gpio_request(EPDC_D5, "epdc_d5");
+ gpio_request(EPDC_D6, "epdc_d6");
+ gpio_request(EPDC_D7, "epdc_d7");
+ gpio_request(EPDC_GDCLK, "epdc_gdclk");
+ gpio_request(EPDC_GDSP, "epdc_gdsp");
+ gpio_request(EPDC_GDOE, "epdc_gdoe");
+ gpio_request(EPDC_GDRL, "epdc_gdrl");
+ gpio_request(EPDC_SDCLK, "epdc_sdclk");
+ gpio_request(EPDC_SDOE, "epdc_sdoe");
+ gpio_request(EPDC_SDLE, "epdc_sdle");
+ gpio_request(EPDC_SDSHR, "epdc_sdshr");
+ gpio_request(EPDC_BDR0, "epdc_bdr0");
+ gpio_request(EPDC_SDCE0, "epdc_sdce0");
+ gpio_request(EPDC_SDCE1, "epdc_sdce1");
+ gpio_request(EPDC_SDCE2, "epdc_sdce2");
+}
+
+static void epdc_put_pins(void)
+{
+ gpio_free(EPDC_D0);
+ gpio_free(EPDC_D1);
+ gpio_free(EPDC_D2);
+ gpio_free(EPDC_D3);
+ gpio_free(EPDC_D4);
+ gpio_free(EPDC_D5);
+ gpio_free(EPDC_D6);
+ gpio_free(EPDC_D7);
+ gpio_free(EPDC_GDCLK);
+ gpio_free(EPDC_GDSP);
+ gpio_free(EPDC_GDOE);
+ gpio_free(EPDC_GDRL);
+ gpio_free(EPDC_SDCLK);
+ gpio_free(EPDC_SDOE);
+ gpio_free(EPDC_SDLE);
+ gpio_free(EPDC_SDSHR);
+ gpio_free(EPDC_BDR0);
+ gpio_free(EPDC_SDCE0);
+ gpio_free(EPDC_SDCE1);
+ gpio_free(EPDC_SDCE2);
+}
+
+static struct pad_desc mx50_epdc_pads_enabled[] = {
+ MX50_PAD_EPDC_D0__EPDC_D0,
+ MX50_PAD_EPDC_D1__EPDC_D1,
+ MX50_PAD_EPDC_D2__EPDC_D2,
+ MX50_PAD_EPDC_D3__EPDC_D3,
+ MX50_PAD_EPDC_D4__EPDC_D4,
+ MX50_PAD_EPDC_D5__EPDC_D5,
+ MX50_PAD_EPDC_D6__EPDC_D6,
+ MX50_PAD_EPDC_D7__EPDC_D7,
+ MX50_PAD_EPDC_GDCLK__EPDC_GDCLK,
+ MX50_PAD_EPDC_GDSP__EPDC_GDSP,
+ MX50_PAD_EPDC_GDOE__EPDC_GDOE,
+ MX50_PAD_EPDC_GDRL__EPDC_GDRL,
+ MX50_PAD_EPDC_SDCLK__EPDC_SDCLK,
+ MX50_PAD_EPDC_SDOE__EPDC_SDOE,
+ MX50_PAD_EPDC_SDLE__EPDC_SDLE,
+ MX50_PAD_EPDC_SDSHR__EPDC_SDSHR,
+ MX50_PAD_EPDC_BDR0__EPDC_BDR0,
+ MX50_PAD_EPDC_SDCE0__EPDC_SDCE0,
+ MX50_PAD_EPDC_SDCE1__EPDC_SDCE1,
+ MX50_PAD_EPDC_SDCE2__EPDC_SDCE2,
+};
+
+static struct pad_desc mx50_epdc_pads_disabled[] = {
+ MX50_PAD_EPDC_D0__GPIO_3_0,
+ MX50_PAD_EPDC_D1__GPIO_3_1,
+ MX50_PAD_EPDC_D2__GPIO_3_2,
+ MX50_PAD_EPDC_D3__GPIO_3_3,
+ MX50_PAD_EPDC_D4__GPIO_3_4,
+ MX50_PAD_EPDC_D5__GPIO_3_5,
+ MX50_PAD_EPDC_D6__GPIO_3_6,
+ MX50_PAD_EPDC_D7__GPIO_3_7,
+ MX50_PAD_EPDC_GDCLK__GPIO_3_16,
+ MX50_PAD_EPDC_GDSP__GPIO_3_17,
+ MX50_PAD_EPDC_GDOE__GPIO_3_18,
+ MX50_PAD_EPDC_GDRL__GPIO_3_19,
+ MX50_PAD_EPDC_SDCLK__GPIO_3_20,
+ MX50_PAD_EPDC_SDOE__GPIO_3_23,
+ MX50_PAD_EPDC_SDLE__GPIO_3_24,
+ MX50_PAD_EPDC_SDSHR__GPIO_3_26,
+ MX50_PAD_EPDC_BDR0__GPIO_4_23,
+ MX50_PAD_EPDC_SDCE0__GPIO_4_25,
+ MX50_PAD_EPDC_SDCE1__GPIO_4_26,
+ MX50_PAD_EPDC_SDCE2__GPIO_4_27,
+};
+
+static void epdc_enable_pins(void)
+{
+ /* Configure MUX settings to enable EPDC use */
+ mxc_iomux_v3_setup_multiple_pads(mx50_epdc_pads_enabled, \
+ ARRAY_SIZE(mx50_epdc_pads_enabled));
+
+ gpio_direction_input(EPDC_D0);
+ gpio_direction_input(EPDC_D1);
+ gpio_direction_input(EPDC_D2);
+ gpio_direction_input(EPDC_D3);
+ gpio_direction_input(EPDC_D4);
+ gpio_direction_input(EPDC_D5);
+ gpio_direction_input(EPDC_D6);
+ gpio_direction_input(EPDC_D7);
+ gpio_direction_input(EPDC_GDCLK);
+ gpio_direction_input(EPDC_GDSP);
+ gpio_direction_input(EPDC_GDOE);
+ gpio_direction_input(EPDC_GDRL);
+ gpio_direction_input(EPDC_SDCLK);
+ gpio_direction_input(EPDC_SDOE);
+ gpio_direction_input(EPDC_SDLE);
+ gpio_direction_input(EPDC_SDSHR);
+ gpio_direction_input(EPDC_BDR0);
+ gpio_direction_input(EPDC_SDCE0);
+ gpio_direction_input(EPDC_SDCE1);
+ gpio_direction_input(EPDC_SDCE2);
+}
+
+static void epdc_disable_pins(void)
+{
+ /* Configure MUX settings for EPDC pins to
+ * GPIO and drive to 0. */
+ mxc_iomux_v3_setup_multiple_pads(mx50_epdc_pads_disabled, \
+ ARRAY_SIZE(mx50_epdc_pads_disabled));
+
+ gpio_direction_output(EPDC_D0, 0);
+ gpio_direction_output(EPDC_D1, 0);
+ gpio_direction_output(EPDC_D2, 0);
+ gpio_direction_output(EPDC_D3, 0);
+ gpio_direction_output(EPDC_D4, 0);
+ gpio_direction_output(EPDC_D5, 0);
+ gpio_direction_output(EPDC_D6, 0);
+ gpio_direction_output(EPDC_D7, 0);
+ gpio_direction_output(EPDC_GDCLK, 0);
+ gpio_direction_output(EPDC_GDSP, 0);
+ gpio_direction_output(EPDC_GDOE, 0);
+ gpio_direction_output(EPDC_GDRL, 0);
+ gpio_direction_output(EPDC_SDCLK, 0);
+ gpio_direction_output(EPDC_SDOE, 0);
+ gpio_direction_output(EPDC_SDLE, 0);
+ gpio_direction_output(EPDC_SDSHR, 0);
+ gpio_direction_output(EPDC_BDR0, 0);
+ gpio_direction_output(EPDC_SDCE0, 0);
+ gpio_direction_output(EPDC_SDCE1, 0);
+ gpio_direction_output(EPDC_SDCE2, 0);
+}
+
+static struct fb_videomode e60_v110_mode = {
+ .name = "E60_V110",
+ .refresh = 50,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 18604700,
+ .left_margin = 8,
+ .right_margin = 178,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e60_v220_mode = {
+ .name = "E60_V220",
+ .refresh = 85,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 32000000,
+ .left_margin = 8,
+ .right_margin = 166,
+ .upper_margin = 4,
+ .lower_margin = 26,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct fb_videomode e97_v110_mode = {
+ .name = "E97_V110",
+ .refresh = 50,
+ .xres = 1200,
+ .yres = 825,
+ .pixclock = 32000000,
+ .left_margin = 12,
+ .right_margin = 128,
+ .upper_margin = 4,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 4,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .flag = 0,
+};
+
+static struct mxc_epdc_fb_mode panel_modes[] = {
+ {
+ &e60_v110_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e60_v220_mode,
+ 4, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 428, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 1, /* num_ce */
+ },
+ {
+ &e97_v110_mode,
+ 8, /* vscan_holdoff */
+ 10, /* sdoed_width */
+ 20, /* sdoed_delay */
+ 10, /* sdoez_width */
+ 20, /* sdoez_delay */
+ 632, /* gdclk_hp_offs */
+ 20, /* gdsp_offs */
+ 0, /* gdoe_offs */
+ 1, /* gdclk_offs */
+ 3, /* num_ce */
+ }
+};
+
+static struct mxc_epdc_fb_platform_data epdc_data = {
+ .epdc_mode = panel_modes,
+ .num_modes = ARRAY_SIZE(panel_modes),
+ .get_pins = epdc_get_pins,
+ .put_pins = epdc_put_pins,
+ .enable_pins = epdc_enable_pins,
+ .disable_pins = epdc_disable_pins,
+};
+
+static struct platform_device max17135_sensor_device = {
+ .name = "max17135_sensor",
+ .id = 0,
+};
+
+static struct max17135_platform_data max17135_pdata __initdata = {
+ .vneg_pwrup = 1,
+ .gvee_pwrup = 1,
+ .vpos_pwrup = 2,
+ .gvdd_pwrup = 1,
+ .gvdd_pwrdn = 1,
+ .vpos_pwrdn = 2,
+ .gvee_pwrdn = 1,
+ .vneg_pwrdn = 1,
+ .gpio_pmic_pwrgood = EPDC_PWRSTAT,
+ .gpio_pmic_vcom_ctrl = EPDC_VCOM,
+ .gpio_pmic_wakeup = EPDC_PMIC_WAKE,
+ .gpio_pmic_intr = EPDC_PMIC_INT,
+ .regulator_init = max17135_init_data,
+ .init = max17135_regulator_init,
+};
+
+static int max17135_regulator_init(struct max17135 *max17135)
+{
+ struct max17135_platform_data *pdata = &max17135_pdata;
+ int i, ret;
+
+ max17135->gvee_pwrup = pdata->gvee_pwrup;
+ max17135->vneg_pwrup = pdata->vneg_pwrup;
+ max17135->vpos_pwrup = pdata->vpos_pwrup;
+ max17135->gvdd_pwrup = pdata->gvdd_pwrup;
+ max17135->gvdd_pwrdn = pdata->gvdd_pwrdn;
+ max17135->vpos_pwrdn = pdata->vpos_pwrdn;
+ max17135->vneg_pwrdn = pdata->vneg_pwrdn;
+ max17135->gvee_pwrdn = pdata->gvee_pwrdn;
+
+ max17135->max_wait = pdata->vpos_pwrup + pdata->vneg_pwrup +
+ pdata->gvdd_pwrup + pdata->gvee_pwrup;
+
+ max17135->gpio_pmic_pwrgood = pdata->gpio_pmic_pwrgood;
+ max17135->gpio_pmic_vcom_ctrl = pdata->gpio_pmic_vcom_ctrl;
+ max17135->gpio_pmic_wakeup = pdata->gpio_pmic_wakeup;
+ max17135->gpio_pmic_intr = pdata->gpio_pmic_intr;
+
+ max17135->vcom_setup = false;
+ max17135->init_done = false;
+
+ for (i = 0; i <= MAX17135_VPOS; i++) {
+ ret = max17135_register_regulator(max17135, i,
+ &pdata->regulator_init[i]);
+ if (ret != 0) {
+ printk(KERN_ERR"max17135 regulator init failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ regulator_has_full_constraints();
+
+ return 0;
+}
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("max17135", 0x48),
+ .platform_data = &max17135_pdata,
+ },
+ {
+ .type = "mma8450",
+ .addr = 0x1c,
+ },
+ {
+ .type = "eeprom",
+ .addr = 0x50,
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+};
+
+static struct mtd_partition mxc_dataflash_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x000100000,},
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,},
+};
+
+static struct flash_platform_data mxc_spi_flash_data[] = {
+ {
+ .name = "mxc_dataflash",
+ .parts = mxc_dataflash_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_dataflash_partitions),
+ .type = "at45db321d",}
+};
+
+
+static struct spi_board_info mxc_dataflash_device[] __initdata = {
+ {
+ .modalias = "mxc_dataflash",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 3,
+ .chip_select = 1,
+ .platform_data = &mxc_spi_flash_data[0],},
+};
+
+static int sdhc_write_protect(struct device *dev)
+{
+ unsigned short rc = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ rc = gpio_get_value(SD1_WP);
+ else if (to_platform_device(dev)->id == 1)
+ rc = gpio_get_value(SD2_WP);
+ else if (to_platform_device(dev)->id == 2)
+ rc = 0;
+
+ return rc;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret = 0;
+ if (to_platform_device(dev)->id == 0)
+ ret = gpio_get_value(SD1_CD);
+ else if (to_platform_device(dev)->id == 1)
+ ret = gpio_get_value(SD2_CD);
+ else if (to_platform_device(dev)->id == 2)
+ ret = 1;
+
+ return ret;
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = "VSD"
+};
+
+static struct mxc_mmc_platform_data mmc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static int mxc_sgtl5000_amp_enable(int enable)
+{
+ gpio_set_value(SGTL_AMP_SHDN, !enable);
+ return 0;
+}
+
+static int mxc_sgtl5000_clock_enable(int enable)
+{
+ gpio_set_value(SGTL_OSCEN, enable);
+ return 0;
+}
+
+static int headphone_det_status(void)
+{
+ return (gpio_get_value(HP_DETECT) == 0);
+}
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_irq = IOMUX_TO_IRQ_V3(HP_DETECT),
+ .hp_status = headphone_det_status,
+ .amp_enable = mxc_sgtl5000_amp_enable,
+ .clock_enable = mxc_sgtl5000_clock_enable,
+ .sysclk = 12288000,
+};
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+static struct pad_desc rdp_wvga_pads[] = {
+ MX50_PAD_DISP_D0__DISP_D0,
+ MX50_PAD_DISP_D1__DISP_D1,
+ MX50_PAD_DISP_D2__DISP_D2,
+ MX50_PAD_DISP_D3__DISP_D3,
+ MX50_PAD_DISP_D4__DISP_D4,
+ MX50_PAD_DISP_D5__DISP_D5,
+ MX50_PAD_DISP_D6__DISP_D6,
+ MX50_PAD_DISP_D7__DISP_D7,
+ MX50_PAD_EIM_DA0__GPIO_1_0,
+ MX50_PAD_EIM_DA1__GPIO_1_1,
+ MX50_PAD_EIM_DA2__GPIO_1_2,
+ MX50_PAD_EIM_DA3__GPIO_1_3,
+ MX50_PAD_EIM_DA4__GPIO_1_4,
+ MX50_PAD_EIM_DA5__GPIO_1_5,
+ MX50_PAD_EIM_DA6__GPIO_1_6,
+ MX50_PAD_EIM_DA7__GPIO_1_7,
+};
+
+static void wvga_reset(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(rdp_wvga_pads, \
+ ARRAY_SIZE(rdp_wvga_pads));
+
+ gpio_direction_output(FEC_EN, 1);
+
+ gpio_request(ELCDIF_DAT0_DUMMY, "elcdif-data0");
+ gpio_direction_output(ELCDIF_DAT0_DUMMY, 0);
+ gpio_request(ELCDIF_DAT1_DUMMY, "elcdif-data1");
+ gpio_direction_output(ELCDIF_DAT1_DUMMY, 0);
+ gpio_request(ELCDIF_DAT2_DUMMY, "elcdif-data2");
+ gpio_direction_output(ELCDIF_DAT2_DUMMY, 0);
+ gpio_request(ELCDIF_DAT8_DUMMY, "elcdif-data8");
+ gpio_direction_output(ELCDIF_DAT8_DUMMY, 0);
+ gpio_request(ELCDIF_DAT9_DUMMY, "elcdif-data9");
+ gpio_direction_output(ELCDIF_DAT9_DUMMY, 0);
+ gpio_request(ELCDIF_DAT16_DUMMY, "elcdif-data16");
+ gpio_direction_output(ELCDIF_DAT16_DUMMY, 0);
+ gpio_request(ELCDIF_DAT17_DUMMY, "elcdif-data17");
+ gpio_direction_output(ELCDIF_DAT17_DUMMY, 0);
+
+ return;
+}
+
+static struct mxc_lcd_platform_data lcd_wvga_data = {
+ .reset = wvga_reset,
+};
+
+static struct platform_device lcd_wvga_device = {
+ .name = "lcd_seiko",
+ .dev = {
+ .platform_data = &lcd_wvga_data,
+ },
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 32MHz */
+ "SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB565,
+ .mode_str = "SEIKO-WVGA",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+static struct platform_pwm_backlight_data mxc_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 2000000,
+};
+
+static void mx50_arm2_usb_set_vbus(bool enable)
+{
+ gpio_set_value(USB_OTG_PWR, enable);
+}
+
+static void mxc_register_powerkey(pwrkey_callback pk_cb)
+{
+ pmic_event_callback_t power_key_event;
+
+ power_key_event.param = (void *)1;
+ power_key_event.func = (void *)pk_cb;
+ pmic_event_subscribe(EVENT_PWRONI, power_key_event);
+ power_key_event.param = (void *)3;
+ pmic_event_subscribe(EVENT_PWRON3I, power_key_event);
+}
+
+static int mxc_pwrkey_getstatus(int id)
+{
+ int sense, off = 3;
+
+ pmic_read_reg(REG_INT_SENSE1, &sense, 0xffffffff);
+ switch (id) {
+ case 2:
+ off = 4;
+ break;
+ case 3:
+ off = 2;
+ break;
+ }
+
+ if (sense & (1 << off))
+ return 0;
+
+ return 1;
+}
+
+static struct power_key_platform_data pwrkey_data = {
+ .key_value = KEY_F4,
+ .register_pwrkey = mxc_register_powerkey,
+ .get_key_status = mxc_pwrkey_getstatus,
+};
+
+
+static int __initdata enable_w1 = { 0 };
+static int __init w1_setup(char *__unused)
+{
+ enable_w1 = 1;
+ return cpu_is_mx50();
+}
+
+__setup("w1", w1_setup);
+
+static int __initdata enable_keypad = {0};
+static int __init keypad_setup(char *__unused)
+{
+ enable_keypad = 1;
+ return cpu_is_mx50();
+}
+
+__setup("keypad", keypad_setup);
+
+static struct mxs_dma_plat_data dma_apbh_data = {
+ .chan_base = MXS_DMA_CHANNEL_AHB_APBH,
+ .chan_num = MXS_MAX_DMA_CHANNELS,
+};
+
+static int gpmi_nfc_platform_init(unsigned int max_chip_count)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx50_gpmi_nand,
+ ARRAY_SIZE(mx50_gpmi_nand));
+
+ return 0;
+}
+
+static void gpmi_nfc_platform_exit(unsigned int max_chip_count)
+{
+}
+
+static const char *gpmi_nfc_partition_source_types[] = { "cmdlinepart", 0 };
+
+static struct gpmi_nfc_platform_data gpmi_nfc_platform_data = {
+ .nfc_version = 2,
+ .boot_rom_version = 1,
+ .clock_name = "gpmi-nfc",
+ .platform_init = gpmi_nfc_platform_init,
+ .platform_exit = gpmi_nfc_platform_exit,
+ .min_prop_delay_in_ns = 5,
+ .max_prop_delay_in_ns = 9,
+ .max_chip_count = 2,
+ .boot_area_size_in_bytes = 20 * SZ_1M,
+ .partition_source_types = gpmi_nfc_partition_source_types,
+ .partitions = 0,
+ .partition_count = 0,
+};
+
+static void fec_gpio_iomux_init()
+{
+ struct pad_desc iomux_setting =
+ MX50_PAD_I2C3_SDA__GPIO_6_23;
+
+ /* Enable the Pull/keeper */
+ iomux_setting.pad_ctrl = 0x84;
+ mxc_iomux_v3_setup_pad(&iomux_setting);
+ gpio_request(FEC_EN, "fec-en");
+ gpio_direction_output(FEC_EN, 0);
+ gpio_request(FEC_RESET_B, "fec-reset_b");
+ gpio_direction_output(FEC_RESET_B, 0);
+ udelay(500);
+ gpio_set_value(FEC_RESET_B, 1);
+}
+
+static void fec_gpio_iomux_deinit()
+{
+ struct pad_desc iomux_setting =
+ MX50_PAD_I2C3_SDA__GPIO_6_23;
+
+ /* Disable the Pull/keeper */
+ iomux_setting.pad_ctrl = 0xE4;
+ mxc_iomux_v3_setup_pad(&iomux_setting);
+ gpio_request(FEC_EN, "fec-en");
+ gpio_direction_input(FEC_EN);
+ gpio_request(FEC_RESET_B, "fec-reset_b");
+ gpio_direction_input(FEC_RESET_B);
+}
+
+static void mx50_suspend_enter()
+{
+ struct pad_desc *p = suspend_enter_pads;
+ int i;
+ /* Set PADCTRL to 0 for all IOMUX. */
+ for (i = 0; i < ARRAY_SIZE(suspend_enter_pads); i++) {
+ suspend_exit_pads[i] = *p;
+ p->pad_ctrl = 0;
+ p++;
+ }
+ mxc_iomux_v3_get_multiple_pads(suspend_exit_pads,
+ ARRAY_SIZE(suspend_exit_pads));
+ mxc_iomux_v3_setup_multiple_pads(
+ suspend_enter_pads,
+ ARRAY_SIZE(suspend_enter_pads));
+
+ fec_gpio_iomux_deinit();
+}
+
+static void mx50_suspend_exit()
+{
+ mxc_iomux_v3_setup_multiple_pads(
+ suspend_exit_pads,
+ ARRAY_SIZE(suspend_exit_pads));
+ fec_gpio_iomux_init();
+}
+
+static struct mxc_pm_platform_data mx50_pm_data = {
+ .suspend_enter = mx50_suspend_enter,
+ .suspend_exit = mx50_suspend_exit,
+};
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ mxc_set_cpu_type(MXC_CPU_MX50);
+
+ get_cpu_wp = mx50_rdp_get_cpu_wp;
+ set_num_cpu_wp = mx50_rdp_set_num_cpu_wp;
+}
+
+static void __init mx50_rdp_io_init(void)
+{
+ struct pad_desc cspi_keeper = MX50_PAD_ECSPI1_SCLK__GPIO_4_12;
+ struct pad_desc *p = mx50_rdp;
+ int i;
+
+ /* Set PADCTRL to 0 for all IOMUX. */
+ for (i = 0; i < ARRAY_SIZE(mx50_rdp); i++) {
+ int pad_ctl = p->pad_ctrl;
+ p->pad_ctrl = 0;
+ mxc_iomux_v3_setup_pad(p);
+ p->pad_ctrl = pad_ctl;
+ p++;
+ }
+
+ mxc_iomux_v3_setup_multiple_pads(mx50_rdp, \
+ ARRAY_SIZE(mx50_rdp));
+
+ gpio_request(SD1_WP, "sdhc1-wp");
+ gpio_direction_input(SD1_WP);
+
+ gpio_request(SD1_CD, "sdhc1-cd");
+ gpio_direction_input(SD1_CD);
+
+ gpio_request(SD2_WP, "sdhc2-wp");
+ gpio_direction_input(SD2_WP);
+
+ gpio_request(SD2_CD, "sdhc2-cd");
+ gpio_direction_input(SD2_CD);
+
+ gpio_request(HP_DETECT, "hp-det");
+ gpio_direction_input(HP_DETECT);
+
+ gpio_request(PWR_INT, "pwr-int");
+ gpio_direction_input(PWR_INT);
+
+ gpio_request(EPDC_PMIC_WAKE, "epdc-pmic-wake");
+ gpio_direction_output(EPDC_PMIC_WAKE, 0);
+
+ gpio_request(EPDC_VCOM, "epdc-vcom");
+ gpio_direction_output(EPDC_VCOM, 0);
+
+ gpio_request(EPDC_PMIC_INT, "epdc-pmic-int");
+ gpio_direction_input(EPDC_PMIC_INT);
+
+ gpio_request(EPDC_PWRSTAT, "epdc-pwrstat");
+ gpio_direction_input(EPDC_PWRSTAT);
+
+ gpio_request(ELCDIF_PWR_ON, "elcdif-power-on");
+ gpio_direction_output(ELCDIF_PWR_ON, 1);
+
+ if (enable_w1) {
+ struct pad_desc one_wire = MX50_PAD_OWIRE__OWIRE;
+ mxc_iomux_v3_setup_pad(&one_wire);
+ }
+
+ /* SGTL5000_OSC_EN */
+ gpio_request(SGTL_OSCEN, "sgtl5000-osc-en");
+ gpio_direction_output(SGTL_OSCEN, 1);
+
+ gpio_request(SGTL_AMP_SHDN, "sgtl5000-amp-shdn");
+ gpio_direction_output(SGTL_AMP_SHDN, 1);
+
+ fec_gpio_iomux_init();
+
+ /* USB OTG PWR */
+ gpio_request(USB_OTG_PWR, "usb otg power");
+ gpio_direction_output(USB_OTG_PWR, 0);
+
+ cspi_keeper.pad_ctrl = 0x0; /* Disable all keepers */
+ mxc_iomux_v3_setup_pad(&cspi_keeper);
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ /* SD card detect irqs */
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(SD1_CD);
+ mxcsdhc2_device.resource[2].start = IOMUX_TO_IRQ_V3(SD2_CD);
+ mxcsdhc2_device.resource[2].end = IOMUX_TO_IRQ_V3(SD2_CD);
+
+ mxc_cpu_common_init();
+ mx50_rdp_io_init();
+
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxcspi3_device, &mxcspi3_data);
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxs_dma_apbh_device, &dma_apbh_data);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[2], &mxci2c_data);
+
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_w1_master_device, &mxc_w1_data);
+ mxc_register_device(&gpu_device, &z160_revision);
+ mxc_register_device(&mxc_pxp_device, NULL);
+ mxc_register_device(&mxc_pxp_client_device, NULL);
+ mxc_register_device(&mxc_pxp_v4l2, NULL);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+ mxc_register_device(&pm_device, &mx50_pm_data);
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+
+ if (enable_keypad)
+ mxc_register_device(&mxc_keypad_device, &keypad_plat_data);
+
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc2_device, &mmc2_data);
+ mxc_register_device(&mxcsdhc3_device, &mmc3_data);
+ mxc_register_device(&mxc_ssi1_device, NULL);
+ mxc_register_device(&mxc_ssi2_device, NULL);
+ mxc_register_device(&mxc_fec_device, &fec_data);
+ spi_register_board_info(mxc_dataflash_device,
+ ARRAY_SIZE(mxc_dataflash_device));
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+
+ mxc_register_device(&max17135_sensor_device, NULL);
+ mxc_register_device(&epdc_device, &epdc_data);
+ mxc_register_device(&lcd_wvga_device, &lcd_wvga_data);
+ mxc_register_device(&elcdif_device, &fb_data[0]);
+ mxc_register_device(&mxc_pwm1_device, NULL);
+ mxc_register_device(&mxc_pwm1_backlight_device,
+ &mxc_pwm_backlight_data);
+ mxc_register_device(&mxs_viim, NULL);
+ mxc_register_device(&mxc_rngb_device, NULL);
+ mxc_register_device(&dcp_device, NULL);
+ mxc_register_device(&mxc_powerkey_device, &pwrkey_data);
+ mxc_register_device(&fixed_volt_reg_device, &fixed_volt_reg_pdata);
+ if (cpu_is_mx50_rev(CHIP_REV_1_1) >= 1)
+ mxc_register_device(&mxc_zq_calib_device, NULL);
+ mx50_rdp_init_mc13892();
+/*
+ pm_power_off = mxc_power_off;
+ */
+ mx5_set_otghost_vbus_func(mx50_arm2_usb_set_vbus);
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+ mxc_register_device(&gpmi_nfc_device, &gpmi_nfc_platform_data);
+ mx5_usb_dr_init();
+ mx5_usbh1_init();
+ mxc_register_device(&mxc_perfmon, &mxc_perfmon_data);
+}
+
+static void __init mx50_rdp_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx50_clocks_init(32768, 24000000, 22579200);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(MX53_BASE_ADDR(UART1_BASE_ADDR), uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx50_rdp_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX50_RDP data structure.
+ */
+MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx50_rdp_pmic_mc13892.c b/arch/arm/mach-mx5/mx50_rdp_pmic_mc13892.c
new file mode 100644
index 000000000000..883108a2b53a
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_rdp_pmic_mc13892.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/pmic_external.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13892/core.h>
+#include <mach/irqs.h>
+
+#include <mach/iomux-mx50.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)
+
+/* Coin cell charger enable */
+#define COINCHEN_LSH 23
+#define COINCHEN_WID 1
+/* Coin cell charger voltage setting */
+#define VCOIN_LSH 20
+#define VCOIN_WID 3
+
+/* Coin Charger voltage */
+#define VCOIN_2_5V 0x0
+#define VCOIN_2_7V 0x1
+#define VCOIN_2_8V 0x2
+#define VCOIN_2_9V 0x3
+#define VCOIN_3_0V 0x4
+#define VCOIN_3_1V 0x5
+#define VCOIN_3_2V 0x6
+#define VCOIN_3_3V 0x7
+
+/* Keeps VSRTC and CLK32KMCU on for all states */
+#define DRM_LSH 4
+#define DRM_WID 1
+
+/* regulator standby mask */
+#define GEN1_STBY_MASK (1 << 1)
+#define IOHI_STBY_MASK (1 << 4)
+#define DIG_STBY_MASK (1 << 10)
+#define GEN2_STBY_MASK (1 << 13)
+#define PLL_STBY_MASK (1 << 16)
+#define USB2_STBY_MASK (1 << 19)
+
+#define GEN3_STBY_MASK (1 << 1)
+#define CAM_STBY_MASK (1 << 7)
+#define VIDEO_STBY_MASK (1 << 13)
+#define AUDIO_STBY_MASK (1 << 16)
+#define SD_STBY_MASK (1 << 19)
+
+#define REG_MODE_0_ALL_MASK (DIG_STBY_MASK | GEN1_STBY_MASK\
+ | PLL_STBY_MASK | IOHI_STBY_MASK)
+#define REG_MODE_1_ALL_MASK (CAM_STBY_MASK | VIDEO_STBY_MASK |\
+ AUDIO_STBY_MASK | SD_STBY_MASK | GEN3_STBY_MASK)
+
+/* switch mode setting */
+#define SW1MODE_LSB 0
+#define SW2MODE_LSB 10
+#define SW3MODE_LSB 0
+#define SW4MODE_LSB 8
+
+#define SWMODE_MASK 0xF
+#define SWMODE_AUTO 0x8
+
+/* CPU */
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+static struct regulator_consumer_supply sw4_consumers[] = {
+ {
+ /* sgtl5000 */
+ .supply = "VDDA",
+ .dev_name = "1-000a",
+ },
+};
+
+static struct regulator_consumer_supply vgen1_consumers[] = {
+ {
+ /* sgtl5000 */
+ .supply = "VDDIO",
+ .dev_name = "1-000a",
+ },
+};
+
+struct mc13892;
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = mV_to_uV(600),
+ .max_uV = mV_to_uV(1375),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 850000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw4_consumers),
+ .consumer_supplies = sw4_consumers,
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(1200),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ },
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .min_uV = mV_to_uV(2400),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .min_uV = mV_to_uV(2775),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ },
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = mV_to_uV(2300),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vsd_init = {
+ .constraints = {
+ .name = "VSD",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ }
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ .min_uV = mV_to_uV(3000),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(2900),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .name = "GPO1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo2_init = {
+ .constraints = {
+ .name = "GPO2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .name = "GPO3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo4_init = {
+ .constraints = {
+ .name = "GPO4",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static int mc13892_regulator_init(struct mc13892 *mc13892)
+{
+ unsigned int value, register_mask;
+ printk("Initializing regulators for mx50 rdp.\n");
+
+ /* enable standby controll for all regulators */
+ pmic_read_reg(REG_MODE_0, &value, 0xffffff);
+ value |= REG_MODE_0_ALL_MASK;
+ pmic_write_reg(REG_MODE_0, value, 0xffffff);
+
+ pmic_read_reg(REG_MODE_1, &value, 0xffffff);
+ value |= REG_MODE_1_ALL_MASK;
+ pmic_write_reg(REG_MODE_1, value, 0xffffff);
+
+ /* enable switch audo mode */
+ pmic_read_reg(REG_IDENTIFICATION, &value, 0xffffff);
+ /* only for mc13892 2.0A */
+ if ((value & 0x0000FFFF) == 0x45d0) {
+ pmic_read_reg(REG_SW_4, &value, 0xffffff);
+ register_mask = (SWMODE_MASK << SW1MODE_LSB) |
+ (SWMODE_MASK << SW2MODE_LSB);
+ value &= ~register_mask;
+ value |= (SWMODE_AUTO << SW1MODE_LSB) |
+ (SWMODE_AUTO << SW2MODE_LSB);
+ pmic_write_reg(REG_SW_4, value, 0xffffff);
+
+ pmic_read_reg(REG_SW_5, &value, 0xffffff);
+ register_mask = (SWMODE_MASK << SW3MODE_LSB) |
+ (SWMODE_MASK << SW4MODE_LSB);
+ value &= ~register_mask;
+ value |= (SWMODE_AUTO << SW3MODE_LSB) |
+ (SWMODE_AUTO << SW4MODE_LSB);
+ pmic_write_reg(REG_SW_5, value, 0xffffff);
+ }
+ /* Enable coin cell charger */
+ value = BITFVAL(COINCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V);
+ register_mask = BITFMASK(COINCHEN) | BITFMASK(VCOIN);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+
+#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE)
+ value = BITFVAL(DRM, 1);
+ register_mask = BITFMASK(DRM);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+#endif
+
+ mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init);
+ mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init);
+ mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init);
+ mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init);
+ mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init);
+ mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init);
+ mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init);
+ mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init);
+ mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init);
+ mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init);
+ mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init);
+ mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init);
+
+ regulator_has_full_constraints();
+
+ return 0;
+}
+
+static struct mc13892_platform_data mc13892_plat = {
+ .init = mc13892_regulator_init,
+};
+
+static struct spi_board_info __initdata mc13892_spi_device = {
+ .modalias = "pmic_spi",
+ .irq = IOMUX_TO_IRQ_V3(114),
+ .max_speed_hz = 6000000, /* max spi SCK clock speed in HZ */
+ .bus_num = 3,
+ .chip_select = 0,
+ .platform_data = &mc13892_plat,
+};
+
+
+int __init mx50_rdp_init_mc13892(void)
+{
+ return spi_register_board_info(&mc13892_spi_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx50_suspend.S b/arch/arm/mach-mx5/mx50_suspend.S
new file mode 100644
index 000000000000..4d9e1b49a23d
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_suspend.S
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/linkage.h>
+
+#define ARM_CTRL_DCACHE 1 << 2
+#define ARM_CTRL_ICACHE 1 << 12
+#define ARM_AUXCR_L2EN 1 << 1
+
+/*
+ * mx50_suspend
+ *
+ * Suspend the processor (eg, wait for interrupt).
+ * Set the DDR into Self Refresh
+ * IRQs are already disabled.
+ */
+ENTRY(mx50_suspend)
+ stmfd sp!, {r4,r5,r6,r7,r8, r9,r10,r11} @ Save registers
+
+ mov r6, r0 @save databahn address
+
+/* Before putting DDR into self-refresh, make sure
+ any LPM mode that the DDR might be in is exited.
+*/
+ /* If Databahn is in LPM4, exit that mode first. */
+ ldr r8,[r6, #0x50] @Store LPM mode in r8
+ mov r0, r8
+ bic r0, r0, #0x1F
+ str r0,[r6, #0x50]
+
+
+ /* Disable L1 caches */
+ mrc p15, 0, r0, c1, c0, 0 @ R0 = system control reg
+ bic r0, r0, #ARM_CTRL_ICACHE @ Disable ICache
+ bic r0, r0, #ARM_CTRL_DCACHE @ Disable DCache
+ mcr p15, 0, r0, c1, c0, 0 @ Update system control reg
+
+ mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR
+ ands r3, r0, #0x7000000 @ Isolate level of coherency
+ mov r3, r3, lsr #23 @ Cache level value (naturally aligned)
+ beq FinishedClean
+ mov r10, #0
+Loop1Clean:
+ add r2, r10, r10, lsr #1 @ Work out cache level
+ mov r1, r0, lsr r2 @ R0 bottom 3 bits = Cache Type
+ @ for this level
+ and r1, r1, #7 @ Get those 3 bits alone
+ cmp r1, #2
+ blt SkipClean @ No cache or only instruction cache
+ @ at this level
+ mcr p15, 2, r10, c0, c0, 0 @ Write the Cache Size selection register
+ mov r1, #0
+ .long 0xF57FF06F @ ISB
+ mrc p15, 1, r1, c0, c0, 0 @ Reads current Cache Size ID register
+ and r2, r1, #7 @ Extract the line length field
+ add r2, r2, #4 @ Add 4 for the line length offset
+ @ (log2 16 bytes)
+ ldr r4, =0x3FF
+ ands r4, r4, r1, lsr #3 @ R4 is the max number on the
+ @ way size (right aligned)
+ clz r5, r4 @ R5 is the bit position of the way
+ @ size increment
+ ldr r7, =0x00007FFF
+ ands r7, r7, r1, lsr #13 @ R7 is the max number of the index
+ @ size (right aligned)
+Loop2Clean:
+ mov r9, r4 @ R9 working copy of the max way size
+ @ (right aligned)
+Loop3Clean:
+ orr r11, r10, r9, lsl r5 @ Factor in the way number and cache
+ @ number into R11
+ orr r11, r11, r7, lsl r2 @ Factor in the index number
+ mcr p15, 0, r11, c7, c14, 2 @ Clean and invalidate by set/way
+ subs r9, r9, #1 @ Decrement the way number
+ bge Loop3Clean
+ subs r7, r7, #1 @ Decrement the index
+ bge Loop2Clean
+SkipClean:
+ add r10, r10, #2 @ Increment the cache number
+ cmp r3, r10
+ bgt Loop1Clean
+
+FinishedClean:
+
+ /* Disable L2 cache */
+ mrc p15, 0, r0, c1, c0, 1 @ R0 = auxiliary control reg
+ bic r0, r0, #ARM_AUXCR_L2EN @ Disable L2 cache
+ mcr p15, 0, r0, c1, c0, 1 @ Update aux control reg
+
+/* Wait for the databahn to idle
+ Meaning, no access to the databahn is
+ being made.
+*/
+EnterWFI:
+ ldr r0,[r6, #0x13c]
+ and r0, r0, #0x100
+ ldr r2, =0x100
+ cmp r0, r2
+ beq EnterWFI
+
+ /* Enter self-refresh mode */
+ ldr r0,[r6, #0x4c]
+ orr r0,r0,#0x1
+ str r0,[r6, #0x4c]
+
+LoopCKE0:
+ /* Wait for CKE = 0 */
+ ldr r0,[r6, #0xfc]
+ and r0, r0, #0x10000
+ ldr r2, =0x10000
+ cmp r0, r2
+ beq LoopCKE0
+
+ /* Stop controller */
+ ldr r0,[r6]
+ bic r0, r0, #0x1
+ str r0,[r6]
+
+ .long 0xe320f003 @ Opcode for WFI
+
+ /* Start controller */
+ ldr r0,[r6]
+ orr r0,r0,#0x1
+ str r0,[r6]
+
+LoopPHY:
+ /* Wait for PHY ready */
+ ldr r0,[r6, #0x264]
+ and r0, r0, #0xfffffffe
+ ldr r2, =0x0
+ cmp r0, r2
+ beq LoopPHY
+
+ /*Leave self-refresh mode */
+ ldr r0,[r6, #0x4c]
+ and r0,r0,#0xfffffffe
+ str r0,[r6, #0x4c]
+
+LoopCKE1:
+ /*Wait for CKE = 1 */
+ ldr r0,[r6, #0xfc]
+ and r0, r0, #0x10000
+ ldr r2, =0x10000
+ cmp r0, r2
+ bne LoopCKE1
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ Invalidate inst cache
+
+/* Invalidate data caches */
+ mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR
+ ands r3, r0, #0x7000000 @ Isolate level of coherency
+ mov r3, r3, lsr #23 @ Cache level value (naturally aligned)
+ beq FinishedInvalidate
+ mov r10, #0
+Loop1Invalidate:
+ add r2, r10, r10, lsr #1 @ Work out cache level
+ mov r1, r0, lsr r2 @ R0 bottom 3 bits = Cache
+ @ Type for this level
+ and r1, r1, #7 @ Get those 3 bits alone
+ cmp r1, #2
+ blt SkipInvalidate @ No cache or only instruction cache
+ @at this level
+ mcr p15, 2, r10, c0, c0, 0 @ Write the Cache Size selection register
+ mov r1, #0
+ .long 0xF57FF06F @ ISB
+ mrc p15, 1, r1, c0, c0, 0 @ Reads current Cache Size ID register
+ and r2, r1, #7 @ Extract the line length field
+ add r2, r2, #4 @ Add 4 for the line length offset
+ @(log2 16 bytes)
+ ldr r4, =0x3FF
+ ands r4, r4, r1, lsr #3 @ R4 is the max number on the way
+ @size (right aligned)
+ clz r5, r4 @ R5 is the bit position of the way
+ @ size increment
+ ldr r7, =0x00007FFF
+ ands r7, r7, r1, lsr #13 @ R7 is the max number of the
+ @ index size (right aligned)
+Loop2Invalidate:
+ mov r9, r4 @ R9 working copy of the max way
+ @ size (right aligned)
+Loop3Invalidate:
+ orr r11, r10, r9, lsl r5 @ Factor in the way number and cache
+ @ number into R11
+ orr r11, r11, r7, lsl r2 @ Factor in the index number
+ mcr p15, 0, r11, c7, c6, 2 @ Invalidate by set/way
+ subs r9, r9, #1 @ Decrement the way number
+ bge Loop3Invalidate
+ subs r7, r7, #1 @ Decrement the index
+ bge Loop2Invalidate
+SkipInvalidate:
+ add r10, r10, #2 @ Increment the cache number
+ cmp r3, r10
+ bgt Loop1Invalidate
+
+FinishedInvalidate:
+
+ /* Enable L2 cache */
+ mrc p15, 0, r0, c1, c0, 1 @ R0 = auxiliary control reg
+ orr r0, r0, #ARM_AUXCR_L2EN @ Enable L2 cache
+ mcr p15, 0, r0, c1, c0, 1 @ Update aux control reg
+
+ /* Enable L1 caches */
+ mrc p15, 0, r0, c1, c0, 0 @ R0 = system control reg
+ orr r0, r0, #ARM_CTRL_ICACHE @ Enable ICache
+ orr r0, r0, #ARM_CTRL_DCACHE @ Enable DCache
+ mcr p15, 0, r0, c1, c0, 0 @ Update system control reg
+
+ /* restore LPM mode. */
+ str r8, [r6, #0x50]
+
+ /* Restore registers */
+ ldmfd sp!, {r4,r5,r6,r7,r8,r9,r10,r11}
+ mov pc, lr
+
+ .type mx50_do_suspend, #object
+ENTRY(mx50_do_suspend)
+ .word mx50_suspend
+ .size mx50_suspend, . - mx50_suspend
diff --git a/arch/arm/mach-mx5/mx50_wfi.S b/arch/arm/mach-mx5/mx50_wfi.S
new file mode 100644
index 000000000000..3335b0f320a4
--- /dev/null
+++ b/arch/arm/mach-mx5/mx50_wfi.S
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * mx50_wait
+ *
+ * Idle the processor (eg, wait for interrupt).
+ * Make sure DDR is in self-refresh.
+ * IRQs are already disabled.
+ */
+ENTRY(mx50_wait)
+ stmfd sp!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} @ Save registers
+
+ mov r6, r0 @save CCM address
+ mov r5, r1 @save DataBahn address
+
+ /*
+ * Make sure the DDR is self-refresh, before setting the clock bits.
+ */
+
+ /* Step 2: Poll the CKE_STATUS bit. */
+LoopCKE0:
+ /* Wait for CKE = 0 */
+ ldr r0,[r5, #0xfc]
+ and r0, r0, #0x10000
+ ldr r2, =0x10000
+ cmp r0, r2
+ beq LoopCKE0
+
+ /* Check if Databahn is in SYNC or ASYNC mode. */
+ ldr r4, [r5, #0xdc]
+ and r4, r4, #0x30000
+ cmp r4, #0x30000
+ beq Sync_mode
+
+ /* Set the DDR_CLKGATE to 0x1. */
+ ldr r0, [r6, #0x98]
+ bic r0, r0, #0x80000000
+ str r0, [r6, #0x98]
+
+ .long 0xe320f003 @ Opcode for WFI
+
+ /* Set the DDR_CLKGATE to 0x3. */
+ ldr r0, [r6, #0x98]
+ orr r0, r0, #0xC0000000
+ str r0, [r6, #0x98]
+ b Wfi_Done
+
+Sync_mode:
+ /* Check if PLL1 is sourcing SYS_CLK. */
+ ldr r5, [r6, #0x90]
+ and r5, r0, #0x1
+ cmp r5, #0x1
+ beq pll1_source
+
+ /* Set the SYS_XTAL_CLKGATE to 0x1. */
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x80000000
+ str r0, [r6, #0x94]
+
+ /* Set the SYS_XTAL_DIV to 0xF (1.6MHz) to reduce power.
+ * since this clock is not gated when ARM is in WFI.
+ */
+
+ ldr r0, [r6, #0x94]
+ orr r0, r0, #0x3c0
+ str r0, [r6, #0x94]
+
+ b do_wfi
+pll1_source:
+ /* Set the SYS_PLL_CLKGATE to 0x1. */
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x40000000
+ str r0, [r6, #0x94]
+
+do_wfi:
+ .long 0xe320f003 @ Opcode for WFI
+
+ cmp r5, #1
+ beq pll1_source1
+ /* Set the SYS_XTAL_DIV to 24MHz.*/
+ ldr r0, [r6, #0x94]
+ bic r0, r0, #0x3c0
+ orr r0, r0, #0x40
+ str r0, [r6, #0x94]
+
+ /* Set the SYS_XTAL_CLKGATE to 0x3. */
+ ldr r0, [r6, #0x94]
+ orr r0, r0, #0xC0000000
+ str r0, [r6, #0x94]
+ b Wfi_Done
+
+pll1_source1:
+ /* Set the SYS_PLL_CLKGATE to 0x3. */
+ ldr r0, [r6, #0x94]
+ orr r0, r0, #0x30000000
+ str r0, [r6, #0x94]
+
+Wfi_Done:
+ /* Restore registers */
+ ldmfd sp!, {r3,r4,r5,r6,r7,r8,r9,r10,r11}
+ mov pc, lr
+
+ .type mx50_do_wait, #object
+ENTRY(mx50_do_wait)
+ .word mx50_wait
+ .size mx50_wait, . - mx50_wait
diff --git a/arch/arm/mach-mx5/mx51_3stack.c b/arch/arm/mach-mx5/mx51_3stack.c
new file mode 100644
index 000000000000..3188cc77bf45
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_3stack.c
@@ -0,0 +1,1078 @@
+/*
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/ata.h>
+#include <linux/pmic_external.h>
+#include <linux/ipu.h>
+#include <linux/pwm_backlight.h>
+#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach/flash.h>
+#endif
+
+#include <linux/regulator/consumer.h>
+#include <mach/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/keypad.h>
+#include <mach/common.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/i2c.h>
+
+#include "devices.h"
+#include "iomux.h"
+#include "mx51_pins.h"
+#include "crm_regs.h"
+#include "usb.h"
+
+/*!
+ * @file mach-mx51/mx51_3stack.c
+ *
+ * @brief This file contains the board specific initialization routines.
+ *
+ * @ingroup MSL_MX51
+ */
+#define DEBUG_BOARD_BASE_ADDRESS(n) (n)
+/* LAN9217 ethernet base address */
+#define LAN9217_BASE_ADDR(n) (DEBUG_BOARD_BASE_ADDRESS(n))
+
+#define BOARD_IO_ADDR(n) (DEBUG_BOARD_BASE_ADDRESS(n) + 0x20000)
+/* LED switchs */
+#define LED_SWITCH_REG 0x00
+/* buttons */
+#define SWITCH_BUTTONS_REG 0x08
+/* status, interrupt */
+#define INTR_STATUS_REG 0x10
+#define INTR_MASK_REG 0x38
+#define INTR_RESET_REG 0x20
+/* magic word for debug CPLD */
+#define MAGIC_NUMBER1_REG 0x40
+#define MAGIC_NUMBER2_REG 0x48
+/* CPLD code version */
+#define CPLD_CODE_VER_REG 0x50
+/* magic word for debug CPLD */
+#define MAGIC_NUMBER3_REG 0x58
+/* module reset register*/
+#define MODULE_RESET_REG 0x60
+/* CPU ID and Personality ID */
+#define MCU_BOARD_ID_REG 0x68
+
+/* interrupts like external uart , external ethernet etc*/
+#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX51_PIN_GPIO1_6)
+
+#define EXPIO_INT_ENET (MXC_BOARD_IRQ_START + 0)
+#define EXPIO_INT_XUART_A (MXC_BOARD_IRQ_START + 1)
+#define EXPIO_INT_XUART_B (MXC_BOARD_IRQ_START + 2)
+#define EXPIO_INT_BUTTON_A (MXC_BOARD_IRQ_START + 3)
+#define EXPIO_INT_BUTTON_B (MXC_BOARD_IRQ_START + 4)
+
+#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_BOARD_IRQ_START)
+
+/*! This is System IRQ used by LAN9217 */
+#define LAN9217_IRQ EXPIO_INT_ENET
+
+extern int __init mx51_3stack_init_mc13892(void);
+extern void __init mx51_3stack_io_init(void);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+static int num_cpu_wp = 3;
+static bool debug_board_present;
+
+/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */
+static struct cpu_wp cpu_wp_auto[] = {
+ {
+ .pll_rate = 1000000000,
+ .cpu_rate = 1000000000,
+ .pdf = 0,
+ .mfi = 10,
+ .mfd = 11,
+ .mfn = 5,
+ .cpu_podf = 0,
+ .cpu_voltage = 1175000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1100000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 166250000,
+ .pdf = 4,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 4,
+ .cpu_voltage = 850000,},
+};
+
+struct cpu_wp *mx51_3stack_get_cpu_wp(int *wp)
+{
+ *wp = num_cpu_wp;
+ return cpu_wp_auto;
+}
+
+void mx51_3stack_set_num_cpu_wp(int num)
+{
+ num_cpu_wp = num;
+ return;
+}
+
+static struct mxc_w1_config mxc_w1_data = {
+ .search_rom_accelerator = 1,
+};
+
+static u16 keymapping[24] = {
+ KEY_1, KEY_2, KEY_3, KEY_F1, KEY_UP, KEY_F2,
+ KEY_4, KEY_5, KEY_6, KEY_LEFT, KEY_SELECT, KEY_RIGHT,
+ KEY_7, KEY_8, KEY_9, KEY_F3, KEY_DOWN, KEY_F4,
+ KEY_0, KEY_OK, KEY_ESC, KEY_ENTER, KEY_MENU, KEY_BACK,
+};
+
+static struct keypad_data keypad_plat_data = {
+ .rowmax = 4,
+ .colmax = 6,
+ .learning = 0,
+ .delay = 2,
+ .matrix = keymapping,
+};
+
+static struct platform_pwm_backlight_data mxc_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 78770,
+};
+
+extern void mx5_ipu_reset(void);
+static struct mxc_ipu_config mxc_ipu_data = {
+ .rev = 2,
+ .reset = mx5_ipu_reset,
+};
+
+extern void mx5_vpu_reset(void);
+static struct mxc_vpu_platform_data mxc_vpu_data = {
+ .reset = mx5_vpu_reset,
+};
+
+/* workaround for ecspi chipselect pin may not keep correct level when idle */
+static void mx51_3ds_gpio_spi_chipselect_active(int cspi_mode, int status,
+ int chipselect)
+{
+ u32 gpio;
+
+ switch (cspi_mode) {
+ case 1:
+ switch (chipselect) {
+ case 0x1:
+ mxc_request_iomux(MX51_PIN_CSPI1_SS0,
+ IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX51_PIN_CSPI1_SS0,
+ PAD_CTL_HYS_ENABLE |
+ PAD_CTL_PKE_ENABLE |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST);
+ break;
+ case 0x2:
+ gpio = IOMUX_TO_GPIO(MX51_PIN_CSPI1_SS0);
+ mxc_request_iomux(MX51_PIN_CSPI1_SS0,
+ IOMUX_CONFIG_GPIO);
+ gpio_request(gpio, "cspi1_ss0");
+ gpio_direction_output(gpio, 0);
+ gpio_set_value(gpio, 1 & (~status));
+ break;
+ default:
+ break;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+static void mx51_3ds_gpio_spi_chipselect_inactive(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ switch (chipselect) {
+ case 0x1:
+ mxc_free_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX51_PIN_CSPI1_SS0,
+ IOMUX_CONFIG_GPIO);
+ mxc_free_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_GPIO);
+ break;
+ case 0x2:
+ mxc_free_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_GPIO);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+ .chipselect_active = mx51_3ds_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx51_3ds_gpio_spi_chipselect_inactive,
+};
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+static struct mxc_i2c_platform_data mxci2c_hs_data = {
+ .i2c_clk = 400000,
+};
+
+static struct tve_platform_data tve_data = {
+ .dac_reg = "VVIDEO",
+ .dig_reg = "VDIG",
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "SW1",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+ .num_wp = 3,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "SW1",
+ .lp_reg_id = "SW2",
+};
+
+static struct mxc_dvfsper_data dvfs_per_data = {
+ .reg_id = "SW2",
+ .clk_id = "gpc_dvfs_clk",
+ .gpc_cntr_reg_addr = MXC_GPC_CNTR,
+ .gpc_vcr_reg_addr = MXC_GPC_VCR,
+ .gpc_adu = 0x0,
+ .vai_mask = MXC_DVFSPMCR0_FSVAI_MASK,
+ .vai_offset = MXC_DVFSPMCR0_FSVAI_OFFSET,
+ .dvfs_enable_bit = MXC_DVFSPMCR0_DVFEN,
+ .irq_mask = MXC_DVFSPMCR0_FSVAIM,
+ .div3_offset = 0,
+ .div3_mask = 0x7,
+ .div3_div = 2,
+ .lp_high = 1250000,
+ .lp_low = 1250000,
+};
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 0, /* spdif_ext_clk source for 44.1KHz */
+ .spdif_clk_48000 = 7, /* audio osc source */
+ .spdif_clkid = 0,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+
+/* NAND Flash Partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+
+static struct mtd_partition nand_flash_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 3 * 1024 * 1024},
+ {
+ .name = "nand.kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 5 * 1024 * 1024},
+ {
+ .name = "nand.rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024 * 1024},
+ {
+ .name = "nand.userfs1",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024 * 1024},
+ {
+ .name = "nand.userfs2",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL},
+};
+
+#endif
+
+extern void gpio_nand_active(void);
+extern void gpio_nand_inactive(void);
+
+static int nand_init(void)
+{
+ /* Configure the pins */
+ gpio_nand_active();
+ return 0;
+}
+
+static void nand_exit(void)
+{
+ /* Free the pins */
+ gpio_nand_inactive();
+}
+
+static struct flash_platform_data mxc_nand_data = {
+ #ifdef CONFIG_MTD_PARTITIONS
+ .parts = nand_flash_partitions,
+ .nr_parts = ARRAY_SIZE(nand_flash_partitions),
+ #endif
+ .width = 1,
+ .init = nand_init,
+ .exit = nand_exit,
+};
+
+/* i.MX MTD NAND Flash Controller */
+
+#if defined(CONFIG_MTD_NAND_IMX_NFC) || defined(CONFIG_MTD_NAND_IMX_NFC_MODULE)
+
+/*
+ * Platform-specific information about this device. Some of the details depend
+ * on the SoC. See imx_init_nfc() below for code that fills in the rest.
+ */
+
+static struct imx_nfc_platform_data imx_nfc_platform_data = {
+ .nfc_major_version = 3,
+ .nfc_minor_version = 2,
+ .force_ce = false,
+ .target_cycle_in_ns = 30,
+ .clock_name = "nfc_clk",
+ .set_page_size = 0,
+ .interleave = false,
+ #ifdef CONFIG_MTD_PARTITIONS
+ .partitions = nand_flash_partitions,
+ .partition_count = ARRAY_SIZE(nand_flash_partitions),
+ #endif
+};
+
+#endif /* i.MX MTD NAND Flash Controller */
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB666,
+ },
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_YUV444,
+ },
+};
+
+static void lcd_reset_to2(void)
+{
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0);
+ ipu_reset_disp_panel();
+
+ return;
+}
+
+static void lcd_reset(void)
+{
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 0);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), "ser_rs");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 0);
+ /* do reset */
+ msleep(10); /* tRES >= 100us */
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_RS), 1);
+ msleep(60);
+}
+
+static struct mxc_lcd_platform_data lcd_data = {
+ .core_reg = "VIOHI",
+ .io_reg = "SW4",
+ .reset = lcd_reset,
+};
+
+static struct platform_device mxc_lcd_device = {
+ .name = "lcd_spi",
+};
+
+static void wvga_reset(void)
+{
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 1);
+}
+
+static struct mxc_lcd_platform_data lcd_wvga_data = {
+ .reset = wvga_reset,
+};
+
+static struct platform_device lcd_wvga_device = {
+ .name = "lcd_claa",
+};
+
+static struct platform_device mxcbl_device = {
+ .name = "mxc_mc13892_bl",
+};
+
+static void si4702_reset(void)
+{
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), 0);
+ msleep(100);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), 1);
+ msleep(100);
+}
+
+static void si4702_clock_ctl(int flag)
+{
+}
+
+static void si4702_gpio_get(void)
+{
+ /* reset pin */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), "eim_dtack");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_DTACK), 0);
+}
+
+static void si4702_gpio_put(void)
+{
+}
+
+static struct mxc_fm_platform_data si4702_data = {
+ .reg_vio = "SW4",
+ .reg_vdd = "VIOHI",
+ .gpio_get = si4702_gpio_get,
+ .gpio_put = si4702_gpio_put,
+ .reset = si4702_reset,
+ .clock_ctl = si4702_clock_ctl,
+ .sksnr = 0,
+ .skcnt = 0,
+ .band = 0,
+ .space = 100,
+ .seekth = 0xa,
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "wm8903-i2c",
+ .addr = 0x1a,
+ },
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "tsc2007",
+ .addr = 0x48,
+ .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_5),
+ },
+ {
+ .type = "si4702",
+ .addr = 0x10,
+ .platform_data = (void *)&si4702_data,
+ },
+};
+
+static struct mxc_camera_platform_data camera_data = {
+ .io_regulator = "SW4",
+ .analog_regulator = "VIOHI",
+ .mclk = 24000000,
+ .csi = 0,
+};
+static struct mxc_lightsensor_platform_data ls_data = {
+ .vdd_reg = NULL,
+ .rext = 100,
+};
+
+static struct i2c_board_info mxc_i2c_hs_board_info[] __initdata = {
+ {
+ .type = "ov3640",
+ .addr = 0x3C,
+ .platform_data = (void *)&camera_data,
+ },
+ {
+ .type = "isl29003",
+ .addr = 0x44,
+ .platform_data = &ls_data,
+ },
+};
+
+static struct resource smsc911x_resources[] = {
+ {
+ .start = CS5_BASE_ADDR,
+ .end = CS5_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = LAN9217_IRQ,
+ .end = LAN9217_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct smsc911x_platform_config smsc911x_config = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .flags = SMSC911X_USE_32BIT | SMSC911X_FORCE_INTERNAL_PHY,
+};
+
+static struct platform_device smsc_lan9217_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+};
+
+static struct mxc_sim_platform_data sim_data = {
+ .clk_rate = 4000000,
+ .clock_sim = "sim_clk",
+ .power_sim = NULL,
+ .init = NULL,
+ .exit = NULL,
+ .detect = 0,
+};
+
+/*!
+ * Get WP pin value to detect write protection
+ */
+static int sdhc_write_protect(struct device *dev)
+{
+ unsigned short rc = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ rc = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1));
+ else
+ rc = 0;
+ return rc;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret;
+
+ if (to_platform_device(dev)->id == 0) {
+ ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0));
+ return ret;
+ } else { /* config the det pin for SDHC2 */
+ return 0;
+ }
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_32_33,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 150000,
+ .max_clk = 52000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
+ MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 150000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static u32 brd_io;
+static void expio_ack_irq(u32 irq);
+
+static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ u32 imr_val;
+ u32 int_valid;
+ u32 expio_irq;
+
+ desc->chip->mask(irq); /* irq = gpio irq number */
+
+ imr_val = __raw_readw(brd_io + INTR_MASK_REG);
+ int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val;
+
+ if (unlikely(!int_valid))
+ goto out;
+
+ expio_irq = MXC_BOARD_IRQ_START;
+ for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
+ struct irq_desc *d;
+ if ((int_valid & 1) == 0)
+ continue;
+ d = irq_desc + expio_irq;
+ if (unlikely(!(d->handle_irq))) {
+ printk(KERN_ERR "\nEXPIO irq: %d unhandled\n",
+ expio_irq);
+ BUG(); /* oops */
+ }
+ d->handle_irq(expio_irq, d);
+ }
+
+ out:
+ desc->chip->ack(irq);
+ desc->chip->unmask(irq);
+}
+
+/*
+ * Disable an expio pin's interrupt by setting the bit in the imr.
+ * @param irq an expio virtual irq number
+ */
+static void expio_mask_irq(u32 irq)
+{
+ u16 reg;
+ u32 expio = MXC_IRQ_TO_EXPIO(irq);
+ /* mask the interrupt */
+ reg = __raw_readw(brd_io + INTR_MASK_REG);
+ reg |= (1 << expio);
+ __raw_writew(reg, brd_io + INTR_MASK_REG);
+}
+
+/*
+ * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
+ * @param irq an expanded io virtual irq number
+ */
+static void expio_ack_irq(u32 irq)
+{
+ u32 expio = MXC_IRQ_TO_EXPIO(irq);
+ /* clear the interrupt status */
+ __raw_writew(1 << expio, brd_io + INTR_RESET_REG);
+ __raw_writew(0, brd_io + INTR_RESET_REG);
+ /* mask the interrupt */
+ expio_mask_irq(irq);
+}
+
+/*
+ * Enable a expio pin's interrupt by clearing the bit in the imr.
+ * @param irq a expio virtual irq number
+ */
+static void expio_unmask_irq(u32 irq)
+{
+ u16 reg;
+ u32 expio = MXC_IRQ_TO_EXPIO(irq);
+ /* unmask the interrupt */
+ reg = __raw_readw(brd_io + INTR_MASK_REG);
+ reg &= ~(1 << expio);
+ __raw_writew(reg, brd_io + INTR_MASK_REG);
+}
+
+static struct irq_chip expio_irq_chip = {
+ .ack = expio_ack_irq,
+ .mask = expio_mask_irq,
+ .unmask = expio_unmask_irq,
+};
+
+static int __init mxc_expio_init(void)
+{
+ int i;
+
+ brd_io = (u32) ioremap(BOARD_IO_ADDR(CS5_BASE_ADDR), SZ_4K);
+ if (brd_io == 0)
+ return -ENOMEM;
+
+ if ((__raw_readw(brd_io + MAGIC_NUMBER1_REG) != 0xAAAA) ||
+ (__raw_readw(brd_io + MAGIC_NUMBER2_REG) != 0x5555) ||
+ (__raw_readw(brd_io + MAGIC_NUMBER3_REG) != 0xCAFE)) {
+ pr_info("3-Stack Debug board not detected \n");
+ return -ENODEV;
+ } else {
+ debug_board_present = true;
+ }
+
+ pr_info("3-Stack Debug board detected, rev = 0x%04X\n",
+ readw(brd_io + CPLD_CODE_VER_REG));
+
+ /*
+ * Configure INT line as GPIO input
+ */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6), "gpio1_6");
+ gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_6));
+
+ /* disable the interrupt and clear the status */
+ __raw_writew(0, brd_io + INTR_MASK_REG);
+ __raw_writew(0xFFFF, brd_io + INTR_RESET_REG);
+ __raw_writew(0, brd_io + INTR_RESET_REG);
+ __raw_writew(0x1F, brd_io + INTR_MASK_REG);
+ for (i = MXC_BOARD_IRQ_START; i < (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS);
+ i++) {
+ set_irq_chip(i, &expio_irq_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+ set_irq_type(EXPIO_PARENT_INT, IRQF_TRIGGER_LOW);
+ set_irq_chained_handler(EXPIO_PARENT_INT, mxc_expio_irq_handler);
+
+ return 0;
+}
+
+extern void gpio_ata_active(void);
+extern void gpio_ata_inactive(void);
+
+static int ata_init(struct platform_device *pdev)
+{
+ /* Configure the pins */
+ gpio_ata_active();
+ return 0;
+}
+
+static void ata_exit(void)
+{
+ /* Free the pins */
+ gpio_ata_inactive();
+}
+
+static struct fsl_ata_platform_data ata_data = {
+ .udma_mask = ATA_UDMA3,
+ .mwdma_mask = ATA_MWDMA2,
+ .pio_mask = ATA_PIO4,
+ .fifo_alarm = MXC_IDE_DMA_WATERMARK / 2,
+ .max_sg = MXC_IDE_DMA_BD_NR,
+ .init = ata_init,
+ .exit = ata_exit,
+ .core_reg = NULL,
+ .io_reg = NULL,
+};
+
+static struct platform_device mxc_wm8903_device = {
+ .name = "imx-3stack-wm8903",
+ .id = 0,
+};
+
+static struct mxc_audio_platform_data wm8903_data;
+
+static void __init mxc_init_wm8903(void)
+{
+ wm8903_data.ssi_clk[0] = clk_get(NULL, "ssi_clk.0");
+ clk_put(wm8903_data.ssi_clk[0]);
+
+ wm8903_data.ssi_clk[1] = clk_get(NULL, "ssi_clk.1");
+ clk_put(wm8903_data.ssi_clk[1]);
+
+ wm8903_data.ssi_num = 1;
+ wm8903_data.src_port = 2;
+ wm8903_data.ext_port = 3;
+
+ (void)platform_device_register(&mxc_wm8903_device);
+}
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+int headphone_det_status(void)
+{
+ return gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A26));
+}
+
+static struct mxc_audio_platform_data sgtl5000_data;
+
+static int mxc_sgtl5000_plat_init(void)
+{
+ struct regulator *reg;
+ reg = regulator_get(&mxc_sgtl5000_device.dev, "GPO2");
+ if (IS_ERR(reg))
+ return -EINVAL;
+ sgtl5000_data.priv = reg;
+ return 0;
+}
+
+static int mxc_sgtl5000_plat_finit(void)
+{
+ struct regulator *reg;
+ reg = sgtl5000_data.priv;
+ if (reg) {
+ regulator_put(reg);
+ sgtl5000_data.priv = NULL;
+ }
+ return 0;
+}
+
+static int mxc_sgtl5000_amp_enable(int enable)
+{
+ struct regulator *reg;
+ reg = sgtl5000_data.priv;
+
+ if (!reg)
+ return -EINVAL;
+ if (enable)
+ regulator_enable(reg);
+ else
+ regulator_disable(reg);
+ return 0;
+}
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_irq = IOMUX_TO_IRQ(MX51_PIN_EIM_A26),
+ .hp_status = headphone_det_status,
+ .amp_enable = mxc_sgtl5000_amp_enable,
+ .sysclk = 12000000,
+ .init = mxc_sgtl5000_plat_init,
+ .finit = mxc_sgtl5000_plat_finit,
+};
+
+static void bt_reset(void)
+{
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), 1);
+}
+
+static struct mxc_bt_platform_data mxc_bt_data = {
+ .bt_vdd = NULL,
+ .bt_vdd_parent = NULL,
+ .bt_vusb = "SW4",
+ .bt_vusb_parent = NULL,
+ .bt_reset = bt_reset,
+};
+
+static struct platform_device mxc_bt_device = {
+ .name = "mxc_bt",
+ .id = 0,
+};
+
+static void mxc_unifi_hardreset(int pin_level)
+{
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), pin_level & 0x01);
+}
+
+static struct mxc_unifi_platform_data unifi_data = {
+ .hardreset = mxc_unifi_hardreset,
+ .reg_vdd_vpa = "VSD",
+ .reg_1v5_dd = "VGEN1",
+ .host_id = 1,
+};
+
+struct mxc_unifi_platform_data *get_unifi_plat_data(void)
+{
+ return &unifi_data;
+}
+EXPORT_SYMBOL(get_unifi_plat_data);
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ mxc_set_cpu_type(MXC_CPU_MX51);
+
+ get_cpu_wp = mx51_3stack_get_cpu_wp;
+ set_num_cpu_wp = mx51_3stack_set_num_cpu_wp;
+}
+
+static struct mxc_gps_platform_data gps_data = {
+ .core_reg = "VIOHI",
+ .analog_reg = "SW4",
+};
+
+static struct platform_device mxc_gps_device = {
+ .name = "gps_ioctrl",
+ .id = -1,
+};
+
+int gpio_gps_access(int para)
+{
+ iomux_pin_name_t pin;
+ pin = (para & 0x1) ? MX51_PIN_EIM_CS2 : MX51_PIN_EIM_CRE;
+
+ if (para & 0x4) /* Read GPIO */
+ return gpio_get_value(IOMUX_TO_GPIO(pin));
+ else if (para & 0x2) /* Write GPIO */
+ gpio_set_value(IOMUX_TO_GPIO(pin), 1);
+ else
+ gpio_set_value(IOMUX_TO_GPIO(pin), 0);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_gps_access);
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ int err;
+
+ mxc_ipu_data.di_clk[0] = clk_get(NULL, "ipu_di0_clk");
+ mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk");
+ mxc_ipu_data.csi_clk[0] = clk_get(NULL, "csi_mclk1");
+ mxc_ipu_data.csi_clk[1] = clk_get(NULL, "csi_mclk2");
+
+ mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk");
+ clk_put(mxc_spdif_data.spdif_core_clk);
+
+ mxc_cpu_common_init();
+ mx51_3stack_io_init();
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+ mxc_register_device(&mxci2c_hs_device, &mxci2c_hs_data);
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_w1_master_device, &mxc_w1_data);
+ mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
+ mxc_register_device(&mxc_tve_device, &tve_data);
+ mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
+ mxc_register_device(&gpu_device, NULL);
+ mxc_register_device(&mxcscc_device, NULL);
+ mxc_register_device(&mx51_lpmode_device, NULL);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+ mxc_register_device(&sdram_autogating_device, NULL);
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&mxc_dvfs_per_device, &dvfs_per_data);
+ mxc_register_device(&mxc_iim_device, NULL);
+ mxc_register_device(&mxc_pwm1_device, NULL);
+ mxc_register_device(&mxc_pwm1_backlight_device,
+ &mxc_pwm_backlight_data);
+ mxc_register_device(&mxc_keypad_device, &keypad_plat_data);
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_0);
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc2_device, &mmc2_data);
+ mxc_register_device(&mxc_sim_device, &sim_data);
+ mxc_register_device(&pata_fsl_device, &ata_data);
+ mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
+
+ mxc_expio_init();
+ if (debug_board_present)
+ mxc_register_device(&smsc_lan9217_device, &smsc911x_config);
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) > 0)
+ lcd_data.reset = lcd_reset_to2;
+
+ mxc_register_device(&mxc_lcd_device, &lcd_data);
+ mxc_register_device(&lcd_wvga_device, &lcd_wvga_data);
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+ mxc_register_device(&mxc_fb_devices[2], NULL);
+ mxc_register_device(&mxcbl_device, NULL);
+
+#if defined(CONFIG_MTD_NAND_IMX_NFC) || defined(CONFIG_MTD_NAND_IMX_NFC_MODULE)
+ mxc_register_device(&imx_nfc_device, &imx_nfc_platform_data);
+#else
+ mxc_register_device(&mxc_nandv2_mtd_device, &mxc_nand_data);
+#endif
+ mx51_3stack_init_mc13892();
+
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ i2c_register_board_info(3, mxc_i2c_hs_board_info,
+ ARRAY_SIZE(mxc_i2c_hs_board_info));
+
+ mxc_init_wm8903();
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+ mxc_register_device(&mxc_bt_device, &mxc_bt_data);
+ mxc_register_device(&mxc_gps_device, &gps_data);
+ mxc_register_device(&mxc_v4l2_device, NULL);
+ mxc_register_device(&mxc_v4l2out_device, NULL);
+
+ mx5_usb_dr_init();
+ mx5_usbh1_init();
+
+ /* Setup Touchscreen interrupt */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5), "gpio1_5");
+ gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_5));
+
+ err = mxc_request_iomux(MX51_PIN_EIM_D19, IOMUX_CONFIG_GPIO);
+ if (err)
+ printk(KERN_ERR "Error: bt reset request gpio failed!\n");
+ else {
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), "eim_d19");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D19), 0);
+ }
+}
+
+static void __init mx51_3stack_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ /* Change the CPU voltages for TO2*/
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) <= 1) {
+ cpu_wp_auto[0].cpu_voltage = 1175000;
+ cpu_wp_auto[1].cpu_voltage = 1100000;
+ cpu_wp_auto[2].cpu_voltage = 1000000;
+ }
+
+ mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+
+ uart_clk = clk_get(NULL, "uart_clk.0");
+ early_console_setup(UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx51_3stack_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX51_3STACK data structure.
+ */
+/* *INDENT-OFF* */
+MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx51_3stack_gpio.c b/arch/arm/mach-mx5/mx51_3stack_gpio.c
new file mode 100644
index 000000000000..b0fca773eaaa
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_3stack_gpio.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/gpio.h>
+
+#include "iomux.h"
+#include "mx51_pins.h"
+
+/*!
+ * @file mach-mx5/mx51_3stack_gpio.c
+ *
+ * @brief This file contains all the GPIO setup functions for the board.
+ *
+ * @ingroup GPIO
+ */
+#define ATA_PAD_CONFIG (PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH)
+
+static struct mxc_iomux_pin_cfg __initdata mxc_iomux_pins[] = {
+ /* CSI0 */
+ {
+ MX51_PIN_CSI1_D8, IOMUX_CONFIG_ALT3,
+ PAD_CTL_PKE_ENABLE,
+ MUX_IN_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT,
+ INPUT_CTL_PATH1,
+ },
+ {
+ MX51_PIN_CSI1_D9, IOMUX_CONFIG_ALT3,
+ PAD_CTL_PKE_ENABLE,
+ },
+ {
+ MX51_PIN_CSI1_D10, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D11, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D12, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D13, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D14, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D15, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D16, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D17, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D18, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_D19, IOMUX_CONFIG_ALT0, PAD_CTL_HYS_NONE,
+ },
+ {
+ MX51_PIN_CSI1_VSYNC, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_SRE_SLOW),
+ },
+ {
+ MX51_PIN_CSI1_HSYNC, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_SRE_SLOW),
+ },
+ {
+ MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT5 | IOMUX_CONFIG_SION,
+ (PAD_CTL_SRE_SLOW | PAD_CTL_DRV_MEDIUM | PAD_CTL_100K_PU |
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DRV_VOT_HIGH),
+ MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT,
+ INPUT_CTL_PATH0,
+ },
+ { /* SPI1 */
+ MX51_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_OWIRE_LINE, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE |
+ PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP2_DAT15, IOMUX_CONFIG_ALT5,
+ },
+ {
+ MX51_PIN_DI_GP2, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_DI_GP3, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_COL0, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_COL1, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_COL2, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_COL3, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_COL4, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_COL5, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_ROW0, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_ROW1, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_ROW2, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_KEY_ROW3, IOMUX_CONFIG_ALT0,
+ },
+ { /* AUD3_TXD */
+ MX51_PIN_AUD3_BB_TXD, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH |
+ PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU |
+ PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW),
+ },
+ { /* AUD3_RXD */
+ MX51_PIN_AUD3_BB_RXD, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH |
+ PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU |
+ PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW),
+ },
+ { /* AUD3_CLK */
+ MX51_PIN_AUD3_BB_CK, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH |
+ PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU |
+ PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW),
+ },
+ { /* AUD3_FS */
+ MX51_PIN_AUD3_BB_FS, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH |
+ PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_100K_PU |
+ PAD_CTL_HYS_NONE | PAD_CTL_DDR_INPUT_CMOS | PAD_CTL_DRV_VOT_LOW),
+ },
+ {
+ MX51_PIN_EIM_D16, IOMUX_CONFIG_ALT1,
+ (PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_EIM_A27, IOMUX_CONFIG_ALT2,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ {
+ MX51_PIN_EIM_EB2, IOMUX_CONFIG_ALT1,
+ PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_100K_PD,
+ },
+ {
+ MX51_PIN_EIM_DTACK, IOMUX_CONFIG_GPIO,
+ (PAD_CTL_PKE_ENABLE | PAD_CTL_100K_PU),
+ },
+ {
+ MX51_PIN_EIM_CS2, IOMUX_CONFIG_GPIO,
+ (PAD_CTL_DRV_HIGH | PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_EIM_CRE, IOMUX_CONFIG_GPIO,
+ (PAD_CTL_DRV_HIGH | PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DI_GP4, IOMUX_CONFIG_ALT2,
+ },
+ {
+ MX51_PIN_DISPB2_SER_DIN, IOMUX_CONFIG_GPIO,
+ 0,
+ MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT,
+ INPUT_CTL_PATH1,
+ },
+ {
+ MX51_PIN_DISPB2_SER_RS, IOMUX_CONFIG_GPIO,
+ },
+ {
+ MX51_PIN_DISPB2_SER_DIO, IOMUX_CONFIG_GPIO,
+ },
+ { /* TO2 */
+ MX51_PIN_DI1_D1_CS, IOMUX_CONFIG_ALT4,
+ },
+ { /* TO2 */
+ MX51_PIN_DI1_D0_CS, IOMUX_CONFIG_ALT1,
+ },
+ { /* TO2 */
+ MX51_PIN_DI1_PIN11, IOMUX_CONFIG_ALT1,
+ },
+ { /* TO2 */
+ MX51_PIN_DI1_PIN12, IOMUX_CONFIG_ALT1,
+ },
+ { /* TO2 */
+ MX51_PIN_DI1_PIN13, IOMUX_CONFIG_ALT1,
+ },
+#ifdef CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL
+ {
+ MX51_PIN_DISP1_DAT0, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT1, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT2, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT3, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT4, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT5, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT6, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT7, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT8, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT9, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT10, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT11, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT12, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT13, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT14, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT15, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT16, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT17, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT18, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT19, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT20, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT21, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT22, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_DISP1_DAT23, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_DRV_LOW | PAD_CTL_SRE_FAST),
+ },
+#endif
+ {
+ MX51_PIN_I2C1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ 0x1E4,
+ },
+ {
+ MX51_PIN_I2C1_DAT, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ 0x1E4,
+ },
+ {
+ MX51_PIN_GPIO1_6, IOMUX_CONFIG_GPIO,
+ },
+ {
+ MX51_PIN_GPIO1_7, IOMUX_CONFIG_ALT2,
+ (PAD_CTL_DRV_HIGH | PAD_CTL_PUE_PULL |
+ PAD_CTL_100K_PU | PAD_CTL_PKE_ENABLE |
+ PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_GPIO1_2, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION,
+ (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE),
+ MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, INPUT_CTL_PATH3,
+ },
+ {
+ MX51_PIN_GPIO1_3, IOMUX_CONFIG_ALT2 | IOMUX_CONFIG_SION,
+ (PAD_CTL_SRE_FAST | PAD_CTL_ODE_OPENDRAIN_ENABLE | PAD_CTL_DRV_HIGH |
+ PAD_CTL_100K_PU | PAD_CTL_HYS_ENABLE),
+ MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, INPUT_CTL_PATH3,
+ },
+ {
+ MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_CLK */
+ MX51_PIN_USBH1_CLK, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS),
+ },
+ { /* USBH1_DIR */
+ MX51_PIN_USBH1_DIR, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS),
+ },
+ { /* USBH1_NXT */
+ MX51_PIN_USBH1_NXT, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS),
+ },
+ { /* USBH1_DATA0 */
+ MX51_PIN_USBH1_DATA0, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA1 */
+ MX51_PIN_USBH1_DATA1, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA2 */
+ MX51_PIN_USBH1_DATA2, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA3 */
+ MX51_PIN_USBH1_DATA3, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA4 */
+ MX51_PIN_USBH1_DATA4, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA5 */
+ MX51_PIN_USBH1_DATA5, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA6 */
+ MX51_PIN_USBH1_DATA6, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USBH1_DATA7 */
+ MX51_PIN_USBH1_DATA7, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_100K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE | PAD_CTL_HYS_ENABLE),
+ },
+ { /* USB1_OC */
+ MX51_PIN_GPIO1_9, IOMUX_CONFIG_ALT1,
+ (PAD_CTL_SRE_SLOW | PAD_CTL_DRV_LOW | PAD_CTL_ODE_OPENDRAIN_NONE |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE |
+ PAD_CTL_HYS_ENABLE),
+ },
+ { /* USB1_PWR */
+ MX51_PIN_GPIO1_8, IOMUX_CONFIG_ALT1,
+ (PAD_CTL_SRE_FAST | PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE |
+ PAD_CTL_PKE_NONE | PAD_CTL_HYS_ENABLE),
+ },
+ {
+ MX51_PIN_SD1_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD1_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD1_DATA0, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD1_DATA1, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD1_DATA2, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD1_DATA3, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_GPIO1_0, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU),
+ },
+ {
+ MX51_PIN_GPIO1_1, IOMUX_CONFIG_GPIO | IOMUX_CONFIG_SION,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PU),
+ },
+ {
+ MX51_PIN_SD2_CMD, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_CLK, IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA0, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA1, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA2, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_SD2_DATA3, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT,
+ INPUT_CTL_PATH0,
+ },
+ {
+ MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_UART1_RTS, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_DRV_HIGH),
+ MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT,
+ INPUT_CTL_PATH0,
+ },
+ {
+ MX51_PIN_UART1_CTS, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_DRV_HIGH),
+ },
+ {
+ MX51_PIN_UART2_RXD, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT,
+ INPUT_CTL_PATH2,
+ },
+ {
+ MX51_PIN_UART2_TXD, IOMUX_CONFIG_ALT0,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_EIM_D26, IOMUX_CONFIG_ALT4,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ MUX_IN_UART2_IPP_UART_RTS_B_SELECT_INPUT,
+ INPUT_CTL_PATH3,
+ },
+ {
+ MX51_PIN_EIM_D25, IOMUX_CONFIG_ALT4,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_UART3_RXD, IOMUX_CONFIG_ALT1,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT,
+ INPUT_CTL_PATH4,
+ },
+ {
+ MX51_PIN_UART3_TXD, IOMUX_CONFIG_ALT1,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ },
+ {
+ MX51_PIN_EIM_D27, IOMUX_CONFIG_ALT3,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ MUX_IN_UART3_IPP_UART_RTS_B_SELECT_INPUT,
+ INPUT_CTL_PATH3,
+ },
+ {
+ MX51_PIN_EIM_D24, IOMUX_CONFIG_ALT3,
+ (PAD_CTL_HYS_NONE | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_HIGH | PAD_CTL_SRE_FAST),
+ },
+};
+
+static struct mxc_iomux_pin_cfg __initdata ata_iomux_pins[] = {
+ {
+ MX51_PIN_NANDF_ALE, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_RE_B, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_WE_B, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_CLE, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_RB0, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_WP_B, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ /* TO 2.0 */
+ {
+ MX51_PIN_GPIO_NAND, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ /* TO 1.0 */
+ {
+ MX51_PIN_NANDF_RB5, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_RB1, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D0, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D1, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D2, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D3, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D4, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D5, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D6, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D7, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D8, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D9, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D10, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D11, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D12, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D13, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D14, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+ {
+ MX51_PIN_NANDF_D15, IOMUX_CONFIG_ALT1,
+ ATA_PAD_CONFIG,
+ },
+};
+
+static struct mxc_iomux_pin_cfg __initdata nand_iomux_pins[] = {
+ {
+ MX51_PIN_NANDF_CS0, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS1, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT0,
+ },
+ {
+ MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT0,
+ },
+ /* TO2 */
+ {
+ MX51_PIN_GPIO_NAND, IOMUX_CONFIG_ALT0,
+ },
+ /* TO1 */
+ {
+ MX51_PIN_NANDF_RB5, IOMUX_CONFIG_ALT0,
+ },
+};
+
+static struct mxc_iomux_pin_cfg __initdata sim_iomux_pins[] = {
+ {
+ MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT6,
+ PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH |
+ PAD_CTL_HYS_NONE | PAD_CTL_47K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE,
+ },
+ {
+ MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT6,
+ PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH |
+ PAD_CTL_HYS_NONE | PAD_CTL_47K_PU |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE,
+ },
+ {
+ MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT6,
+ PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH |
+ PAD_CTL_HYS_NONE | PAD_CTL_100K_PD |
+ PAD_CTL_PUE_PULL | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE,
+ },
+ {
+ MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT6,
+ PAD_CTL_DRV_HIGH | PAD_CTL_DRV_VOT_HIGH |
+ PAD_CTL_HYS_NONE | PAD_CTL_22K_PU |
+ PAD_CTL_PUE_PULL | PAD_CTL_ODE_OPENDRAIN_NONE | PAD_CTL_PKE_ENABLE,
+ },
+};
+
+static int __initdata enable_ata = { 0 };
+static int __init ata_setup(char *__unused)
+{
+ enable_ata = 1;
+ return 1;
+}
+
+__setup("ata", ata_setup);
+
+static int __initdata enable_sim = { 0 };
+static int __init sim_setup(char *__unused)
+{
+ enable_sim = 1;
+ return 1;
+}
+
+__setup("sim", sim_setup);
+
+void __init mx51_3stack_io_init(void)
+{
+ int i, num;
+ struct mxc_iomux_pin_cfg *pin_ptr;
+
+ for (i = 0; i < ARRAY_SIZE(mxc_iomux_pins); i++) {
+ mxc_request_iomux(mxc_iomux_pins[i].pin,
+ mxc_iomux_pins[i].mux_mode);
+ if (mxc_iomux_pins[i].pad_cfg)
+ mxc_iomux_set_pad(mxc_iomux_pins[i].pin,
+ mxc_iomux_pins[i].pad_cfg);
+ if (mxc_iomux_pins[i].in_select)
+ mxc_iomux_set_input(mxc_iomux_pins[i].in_select,
+ mxc_iomux_pins[i].in_mode);
+ }
+
+ if (enable_ata) {
+ pin_ptr = ata_iomux_pins;
+ num = ARRAY_SIZE(ata_iomux_pins);
+ } else if (enable_sim) {
+ pin_ptr = sim_iomux_pins;
+ num = ARRAY_SIZE(sim_iomux_pins);
+ } else {
+ pin_ptr = nand_iomux_pins;
+ num = ARRAY_SIZE(nand_iomux_pins);
+ }
+
+ for (i = 0; i < num; i++) {
+ mxc_request_iomux(pin_ptr[i].pin, pin_ptr[i].mux_mode);
+ if (pin_ptr[i].pad_cfg)
+ mxc_iomux_set_pad(pin_ptr[i].pin, pin_ptr[i].pad_cfg);
+ if (pin_ptr[i].in_select)
+ mxc_iomux_set_input(pin_ptr[i].in_select,
+ pin_ptr[i].in_mode);
+ }
+
+ /* TO3 doesn't need pad to drive CSI_DATA_EN[0] high */
+ if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0)
+ mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT0);
+
+ /* Camera low power */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI1_D8), "csi1_d8");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI1_D8), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI1_D8), 0);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_EB2), "eim_eb2");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_EB2), 0); /* TO1 */
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_EB2), 0); /* TO1 */
+
+ /* Camera reset */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_CSI1_D9), "csi1_d9");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_CSI1_D9), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI1_D9), 1);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), "di1_d1_cs");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0), "gpio1_0");
+ gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); /* SD1 CD */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1), "gpio1_1");
+ gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_1)); /* SD1 WP */
+
+ /* EIM_D16 */
+ /* osc_en is shared by SPDIF */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D16), "eim_d16");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D16), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D16), 1);
+
+ /* LCD related gpio */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), "di1_d1_cs");
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), "dispb2_ser_di0");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0);
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 0);
+
+ /* GPS related gpio */
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_CS2), "eim_cs2");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_CS2), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CS2), 0);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), "eim_cre");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_CRE), 1);
+}
diff --git a/arch/arm/mach-mx5/mx51_3stack_pmic_mc13892.c b/arch/arm/mach-mx5/mx51_3stack_pmic_mc13892.c
new file mode 100644
index 000000000000..7f2136d44152
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_3stack_pmic_mc13892.c
@@ -0,0 +1,370 @@
+/*
+ * mx51-3stack-pmic-mc13892.c -- i.MX51 3STACK Driver for Atlas MC13892 PMIC
+ */
+ /*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+ /*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/pmic_external.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13892/core.h>
+#include <mach/irqs.h>
+#include "iomux.h"
+#include "mx51_pins.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)
+
+#define STANDBYSECINV_LSH 11
+#define STANDBYSECINV_WID 1
+
+/* Coin cell charger enable */
+#define COINCHEN_LSH 23
+#define COINCHEN_WID 1
+/* Coin cell charger voltage setting */
+#define VCOIN_LSH 20
+#define VCOIN_WID 3
+
+/* Coin Charger voltage */
+#define VCOIN_2_5V 0x0
+#define VCOIN_2_7V 0x1
+#define VCOIN_2_8V 0x2
+#define VCOIN_2_9V 0x3
+#define VCOIN_3_0V 0x4
+#define VCOIN_3_1V 0x5
+#define VCOIN_3_2V 0x6
+#define VCOIN_3_3V 0x7
+
+/* Keeps VSRTC and CLK32KMCU on for all states */
+#define DRM_LSH 4
+#define DRM_WID 1
+
+/* CPU */
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+struct mc13892;
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = mV_to_uV(600),
+ .max_uV = mV_to_uV(1375),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 850000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .min_uV = mV_to_uV(2400),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = mV_to_uV(2300),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vsd_init = {
+ .constraints = {
+ .name = "VSD",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ }
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(2900),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .name = "GPO1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo2_init = {
+ .constraints = {
+ .name = "GPO2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .name = "GPO3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo4_init = {
+ .constraints = {
+ .name = "GPO4",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+/*!
+ * the event handler for power on event
+ */
+static void power_on_evt_handler(void)
+{
+ pr_info("pwr on event1 is received \n");
+}
+
+static int mc13892_regulator_init(struct mc13892 *mc13892)
+{
+ unsigned int value;
+ pmic_event_callback_t power_key_event;
+ int register_mask;
+
+ printk("Initializing regulators for 3-stack.\n");
+ if (mxc_cpu_is_rev(CHIP_REV_2_0) < 0)
+ sw2_init.constraints.state_mem.uV = 1100000;
+ else if (mxc_cpu_is_rev(CHIP_REV_2_0) == 1) {
+ sw2_init.constraints.state_mem.uV = 1250000;
+ sw1_init.constraints.state_mem.uV = 1000000;
+ }
+
+ /* subscribe PWRON1 event to enable ON_OFF key */
+ power_key_event.param = NULL;
+ power_key_event.func = (void *)power_on_evt_handler;
+ pmic_event_subscribe(EVENT_PWRONI, power_key_event);
+
+ /* Bit 4 DRM: keep VSRTC and CLK32KMCU on for all states */
+#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE)
+ value = BITFVAL(DRM, 1);
+ register_mask = BITFMASK(DRM);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+#endif
+ /* Set the STANDBYSECINV bit, so that STANDBY pin is
+ * interpreted as active low.
+ */
+ value = BITFVAL(STANDBYSECINV, 1);
+ register_mask = BITFMASK(STANDBYSECINV);
+ pmic_write_reg(REG_POWER_CTL2, value, register_mask);
+
+ /* Enable coin cell charger */
+ value = BITFVAL(COINCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V);
+ register_mask = BITFMASK(COINCHEN) | BITFMASK(VCOIN);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+
+ mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init);
+ mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init);
+ mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init);
+ mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init);
+ mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init);
+ mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init);
+ mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init);
+ mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init);
+ mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init);
+ mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init);
+ mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init);
+ mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init);
+
+ return 0;
+}
+
+static struct mc13892_platform_data mc13892_plat = {
+ .init = mc13892_regulator_init,
+};
+
+static struct i2c_board_info __initdata mc13892_i2c_device = {
+ I2C_BOARD_INFO("mc13892", 0x08),
+ .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_5),
+ .platform_data = &mc13892_plat,
+};
+
+int __init mx51_3stack_init_mc13892(void)
+{
+ return i2c_register_board_info(1, &mc13892_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx51_babbage.c b/arch/arm/mach-mx5/mx51_babbage.c
new file mode 100644
index 000000000000..b6edc8078aab
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_babbage.c
@@ -0,0 +1,1325 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/powerkey.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/keypad.h>
+#include <asm/mach/flash.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/mxc_edid.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_iim.h>
+
+#include "devices.h"
+#include "crm_regs.h"
+#include "usb.h"
+
+/*!
+ * @file mach-mx51/mx51_babbage.c
+ *
+ * @brief This file contains the board specific initialization routines.
+ *
+ * @ingroup MSL_MX51
+ */
+
+#define BABBAGE_SD1_CD (0*32 + 0) /* GPIO_1_0 */
+#define BABBAGE_SD1_WP (0*32 + 1) /* GPIO_1_1 */
+#define BABBAGE_SD2_CD_2_0 (0*32 + 4) /* GPIO_1_4 */
+#define BABBAGE_SD2_WP (0*32 + 5) /* GPIO_1_5 */
+#define BABBAGE_SD2_CD_2_5 (0*32 + 6) /* GPIO_1_6 */
+#define BABBAGE_USBH1_HUB_RST (0*32 + 7) /* GPIO_1_7 */
+#define BABBAGE_PMIC_INT (0*32 + 8) /* GPIO_1_8 */
+
+#define BABBAGE_USB_CLK_EN_B (1*32 + 1) /* GPIO_2_1 */
+#define BABBAGE_OSC_EN_B (1*32 + 2) /* GPIO_2_2 */
+#define BABBAGE_PHY_RESET (1*32 + 5) /* GPIO_2_5 */
+#define BABBAGE_CAM_RESET (1*32 + 7) /* GPIO_2_7 */
+#define BABBAGE_FM_PWR (1*32 + 12) /* GPIO_2_12 */
+#define BABBAGE_VGA_RESET (1*32 + 13) /* GPIO_2_13 */
+#define BABBAGE_FEC_PHY_RESET (1*32 + 14) /* GPIO_2_14 */
+#define BABBAGE_FM_RESET (1*32 + 15) /* GPIO_2_15 */
+#define BABBAGE_AUDAMP_STBY (1*32 + 17) /* GPIO_2_17 */
+#define BABBAGE_POWER_KEY (1*32 + 21) /* GPIO_2_21 */
+
+#define BABBAGE_26M_OSC_EN (2*32 + 1) /* GPIO_3_1 */
+#define BABBAGE_LVDS_POWER_DOWN (2*32 + 3) /* GPIO_3_3 */
+#define BABBAGE_DISP_BRIGHTNESS_CTL (2*32 + 4) /* GPIO_3_4 */
+#define BABBAGE_DVI_RESET (2*32 + 5) /* GPIO_3_5 */
+#define BABBAGE_DVI_POWER (2*32 + 6) /* GPIO_3_6 */
+#define BABBAGE_HEADPHONE_DET (2*32 + 26) /* GPIO_3_26 */
+#define BABBAGE_DVI_DET (2*32 + 28) /* GPIO_3_28 */
+
+#define BABBAGE_LCD_3V3_ON (3*32 + 9) /* GPIO_4_9 */
+#define BABBAGE_LCD_5V_ON (3*32 + 10) /* GPIO_4_10 */
+#define BABBAGE_CAM_LOW_POWER (3*32 + 10) /* GPIO_4_12 */
+#define BABBAGE_DVI_I2C_EN (3*32 + 14) /* GPIO_4_14 */
+#define BABBAGE_CSP1_SS0_GPIO (3*32 + 24) /* GPIO_4_24 */
+#define BABBAGE_AUDIO_CLK_EN (3*32 + 26) /* GPIO_4_26 */
+
+extern int __init mx51_babbage_init_mc13892(void);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+static int num_cpu_wp = 3;
+
+static struct pad_desc mx51babbage_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ MX51_PAD_UART1_RTS__UART1_RTS,
+ MX51_PAD_UART1_CTS__UART1_CTS,
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+
+ /* USB HOST1 */
+ MX51_PAD_USBH1_STP__USBH1_STP,
+ MX51_PAD_USBH1_CLK__USBH1_CLK,
+ MX51_PAD_USBH1_DIR__USBH1_DIR,
+ MX51_PAD_USBH1_NXT__USBH1_NXT,
+ MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+ MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+ MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+ MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+ MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+ MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+ MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+ MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+ MX51_PAD_GPIO_1_0__GPIO_1_0,
+ MX51_PAD_GPIO_1_1__GPIO_1_1,
+ MX51_PAD_GPIO_1_4__GPIO_1_4,
+ MX51_PAD_GPIO_1_5__GPIO_1_5,
+ MX51_PAD_GPIO_1_6__GPIO_1_6,
+ MX51_PAD_GPIO_1_7__GPIO_1_7,
+ MX51_PAD_GPIO_1_8__GPIO_1_8,
+ MX51_PAD_UART3_RXD__GPIO_1_22,
+
+ MX51_PAD_EIM_D17__GPIO_2_1,
+ MX51_PAD_EIM_D18__GPIO_2_2,
+ MX51_PAD_EIM_D21__GPIO_2_5,
+ MX51_PAD_EIM_D23__GPIO_2_7,
+ MX51_PAD_EIM_A16__GPIO_2_10,
+ MX51_PAD_EIM_A17__GPIO_2_11,
+ MX51_PAD_EIM_A18__GPIO_2_12,
+ MX51_PAD_EIM_A19__GPIO_2_13,
+ MX51_PAD_EIM_A20__GPIO_2_14,
+ MX51_PAD_EIM_A21__GPIO_2_15,
+ MX51_PAD_EIM_A22__GPIO_2_16,
+ MX51_PAD_EIM_A23__GPIO_2_17,
+ MX51_PAD_EIM_A27__GPIO_2_21,
+ MX51_PAD_EIM_DTACK__GPIO_2_31,
+
+ MX51_PAD_EIM_LBA__GPIO_3_1,
+ MX51_PAD_DI1_D0_CS__GPIO_3_3,
+ MX51_PAD_DISPB2_SER_DIN__GPIO_3_5,
+ MX51_PAD_DISPB2_SER_DIO__GPIO_3_6,
+ MX51_PAD_NANDF_CS0__GPIO_3_16,
+ MX51_PAD_NANDF_CS1__GPIO_3_17,
+ MX51_PAD_NANDF_D14__GPIO_3_26,
+ MX51_PAD_NANDF_D12__GPIO_3_28,
+
+ MX51_PAD_CSI2_D12__GPIO_4_9,
+ MX51_PAD_CSI2_D13__GPIO_4_10,
+ MX51_PAD_CSI2_D19__GPIO_4_12,
+ MX51_PAD_CSI2_HSYNC__GPIO_4_14,
+ MX51_PAD_CSPI1_RDY__GPIO_4_26,
+
+ MX51_PAD_EIM_EB2__FEC_MDIO,
+ MX51_PAD_EIM_EB3__FEC_RDAT1,
+ MX51_PAD_EIM_CS2__FEC_RDAT2,
+ MX51_PAD_EIM_CS3__FEC_RDAT3,
+ MX51_PAD_EIM_CS4__FEC_RX_ER,
+ MX51_PAD_EIM_CS5__FEC_CRS,
+ MX51_PAD_NANDF_RB2__FEC_COL,
+ MX51_PAD_NANDF_RB3__FEC_RXCLK,
+ MX51_PAD_NANDF_RB6__FEC_RDAT0,
+ MX51_PAD_NANDF_RB7__FEC_TDAT0,
+ MX51_PAD_NANDF_CS2__FEC_TX_ER,
+ MX51_PAD_NANDF_CS3__FEC_MDC,
+ MX51_PAD_NANDF_CS4__FEC_TDAT1,
+ MX51_PAD_NANDF_CS5__FEC_TDAT2,
+ MX51_PAD_NANDF_CS6__FEC_TDAT3,
+ MX51_PAD_NANDF_CS7__FEC_TX_EN,
+ MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+ MX51_PAD_GPIO_NAND__PATA_INTRQ,
+
+ MX51_PAD_DI_GP4__DI2_PIN15,
+#ifdef CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL
+ MX51_PAD_DISP1_DAT22__DISP2_DAT16,
+ MX51_PAD_DISP1_DAT23__DISP2_DAT17,
+
+ MX51_PAD_DI1_D1_CS__GPIO_3_4,
+#endif
+ MX51_PAD_I2C1_CLK__HSI2C_CLK,
+ MX51_PAD_I2C1_DAT__HSI2C_DAT,
+ MX51_PAD_EIM_D16__I2C1_SDA,
+ MX51_PAD_EIM_D19__I2C1_SCL,
+
+ MX51_PAD_GPIO_1_2__PWM_PWMO,
+
+ MX51_PAD_KEY_COL5__I2C2_SDA,
+ MX51_PAD_KEY_COL4__I2C2_SCL,
+
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+ MX51_PAD_SD2_CMD__SD2_CMD,
+ MX51_PAD_SD2_CLK__SD2_CLK,
+ MX51_PAD_SD2_DATA0__SD2_DATA0,
+ MX51_PAD_SD2_DATA1__SD2_DATA1,
+ MX51_PAD_SD2_DATA2__SD2_DATA2,
+ MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+ MX51_PAD_AUD3_BB_TXD__AUD3_BB_TXD,
+ MX51_PAD_AUD3_BB_RXD__AUD3_BB_RXD,
+ MX51_PAD_AUD3_BB_CK__AUD3_BB_CK,
+ MX51_PAD_AUD3_BB_FS__AUD3_BB_FS,
+
+ MX51_PAD_CSPI1_SS1__CSPI1_SS1,
+
+ MX51_PAD_DI_GP3__CSI1_DATA_EN,
+ MX51_PAD_CSI1_D10__CSI1_D10,
+ MX51_PAD_CSI1_D11__CSI1_D11,
+ MX51_PAD_CSI1_D12__CSI1_D12,
+ MX51_PAD_CSI1_D13__CSI1_D13,
+ MX51_PAD_CSI1_D14__CSI1_D14,
+ MX51_PAD_CSI1_D15__CSI1_D15,
+ MX51_PAD_CSI1_D16__CSI1_D16,
+ MX51_PAD_CSI1_D17__CSI1_D17,
+ MX51_PAD_CSI1_D18__CSI1_D18,
+ MX51_PAD_CSI1_D19__CSI1_D19,
+ MX51_PAD_CSI1_VSYNC__CSI1_VSYNC,
+ MX51_PAD_CSI1_HSYNC__CSI1_HSYNC,
+
+ MX51_PAD_OWIRE_LINE__SPDIF_OUT1,
+};
+
+/* working point(wp): 0 - 800MHz; 1 - 166.25MHz; */
+static struct cpu_wp cpu_wp_auto[] = {
+ {
+ .pll_rate = 1000000000,
+ .cpu_rate = 1000000000,
+ .pdf = 0,
+ .mfi = 10,
+ .mfd = 11,
+ .mfn = 5,
+ .cpu_podf = 0,
+ .cpu_voltage = 1175000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1100000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 166250000,
+ .pdf = 4,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 4,
+ .cpu_voltage = 850000,},
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /*MITSUBISHI LVDS panel */
+ "XGA", 60, 1024, 768, 15385,
+ 220, 40,
+ 21, 7,
+ 60, 10,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+struct cpu_wp *mx51_babbage_get_cpu_wp(int *wp)
+{
+ *wp = num_cpu_wp;
+ return cpu_wp_auto;
+}
+
+void mx51_babbage_set_num_cpu_wp(int num)
+{
+ num_cpu_wp = num;
+ return;
+}
+
+static struct mxc_w1_config mxc_w1_data = {
+ .search_rom_accelerator = 1,
+};
+
+static u16 keymapping[16] = {
+ KEY_UP, KEY_DOWN, KEY_MENU, KEY_BACK,
+ KEY_RIGHT, KEY_LEFT, KEY_SELECT, KEY_ENTER,
+ KEY_F1, KEY_F3, KEY_1, KEY_3,
+ KEY_F2, KEY_F4, KEY_2, KEY_4,
+};
+
+static struct keypad_data keypad_plat_data = {
+ .rowmax = 4,
+ .colmax = 4,
+ .learning = 0,
+ .delay = 2,
+ .matrix = keymapping,
+};
+
+static struct platform_pwm_backlight_data mxc_pwm_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 78770,
+};
+
+extern void mx5_ipu_reset(void);
+static struct mxc_ipu_config mxc_ipu_data = {
+ .rev = 2,
+ .reset = mx5_ipu_reset,
+};
+
+extern void mx5_vpu_reset(void);
+static struct mxc_vpu_platform_data mxc_vpu_data = {
+ .reset = mx5_vpu_reset,
+};
+
+/* workaround for ecspi chipselect pin may not keep correct level when idle */
+static void mx51_babbage_gpio_spi_chipselect_active(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ switch (chipselect) {
+ case 0x1:
+ {
+ struct pad_desc cspi1_ss0 = MX51_PAD_CSPI1_SS0__CSPI1_SS0;
+
+ mxc_iomux_v3_setup_pad(&cspi1_ss0);
+ break;
+ }
+ case 0x2:
+ {
+ struct pad_desc cspi1_ss0_gpio = MX51_PAD_CSPI1_SS0__GPIO_4_24;
+
+ mxc_iomux_v3_setup_pad(&cspi1_ss0_gpio);
+ gpio_request(BABBAGE_CSP1_SS0_GPIO, "cspi1-gpio");
+ gpio_direction_output(BABBAGE_CSP1_SS0_GPIO, 0);
+ gpio_set_value(BABBAGE_CSP1_SS0_GPIO, 1 & (~status));
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+static void mx51_babbage_gpio_spi_chipselect_inactive(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ switch (chipselect) {
+ case 0x1:
+ break;
+ case 0x2:
+ gpio_free(BABBAGE_CSP1_SS0_GPIO);
+ break;
+
+ default:
+ break;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+ .chipselect_active = mx51_babbage_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx51_babbage_gpio_spi_chipselect_inactive,
+};
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+static struct mxc_i2c_platform_data mxci2c_hs_data = {
+ .i2c_clk = 400000,
+};
+
+static struct tve_platform_data tve_data = {
+ .dac_reg = "VVIDEO",
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "SW1",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+ .num_wp = 3,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "SW1",
+ .lp_reg_id = "SW2",
+};
+
+static struct mxc_dvfsper_data dvfs_per_data = {
+ .reg_id = "SW2",
+ .clk_id = "gpc_dvfs_clk",
+ .gpc_cntr_reg_addr = MXC_GPC_CNTR,
+ .gpc_vcr_reg_addr = MXC_GPC_VCR,
+ .gpc_adu = 0x0,
+ .vai_mask = MXC_DVFSPMCR0_FSVAI_MASK,
+ .vai_offset = MXC_DVFSPMCR0_FSVAI_OFFSET,
+ .dvfs_enable_bit = MXC_DVFSPMCR0_DVFEN,
+ .irq_mask = MXC_DVFSPMCR0_FSVAIM,
+ .div3_offset = 0,
+ .div3_mask = 0x7,
+ .div3_div = 2,
+ .lp_high = 1250000,
+ .lp_low = 1250000,
+};
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 0, /* spdif_ext_clk source for 44.1KHz */
+ .spdif_clk_48000 = 7, /* audio osc source */
+ .spdif_clkid = 0,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static struct resource mxcfb_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB24,
+ .mode_str = "1024x768M-16@60",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "800x480M@55",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+static void mxc_iim_enable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+ /* Enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg |= 0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static void mxc_iim_disable_fuse(void)
+{
+ u32 reg;
+
+ /* Disable fuse blown */
+ if (!ccm_base)
+ return;
+
+ reg = readl(ccm_base + 0x64);
+ reg &= ~0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static struct mxc_iim_data iim_data = {
+ .bank_start = MXC_IIM_MX51_BANK_START_ADDR,
+ .bank_end = MXC_IIM_MX51_BANK_END_ADDR,
+ .enable_fuse = mxc_iim_enable_fuse,
+ .disable_fuse = mxc_iim_disable_fuse,
+};
+
+extern int primary_di;
+static int __init mxc_init_fb(void)
+{
+ if (!machine_is_mx51_babbage())
+ return 0;
+
+ /* DI0-LVDS */
+ gpio_set_value(BABBAGE_LVDS_POWER_DOWN, 0);
+ msleep(1);
+ gpio_set_value(BABBAGE_LVDS_POWER_DOWN, 1);
+ gpio_set_value(BABBAGE_LCD_3V3_ON, 1);
+ gpio_set_value(BABBAGE_LCD_5V_ON, 1);
+
+ /* DVI Detect */
+ gpio_request(BABBAGE_DVI_DET, "dvi-detect");
+ gpio_direction_input(BABBAGE_DVI_DET);
+ /* DVI Reset - Assert for i2c disabled mode */
+ gpio_request(BABBAGE_DVI_RESET, "dvi-reset");
+ gpio_direction_output(BABBAGE_DVI_RESET, 0);
+ /* DVI Power-down */
+ gpio_request(BABBAGE_DVI_POWER, "dvi-power");
+ gpio_direction_output(BABBAGE_DVI_POWER, 1);
+
+ /* WVGA Reset */
+ gpio_set_value(BABBAGE_DISP_BRIGHTNESS_CTL, 1);
+
+ if (primary_di) {
+ printk(KERN_INFO "DI1 is primary\n");
+
+ /* DI1 -> DP-BG channel: */
+ mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[1].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+
+ /* DI0 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+ } else {
+ printk(KERN_INFO "DI0 is primary\n");
+
+ /* DI0 -> DP-BG channel: */
+ mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[0].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+
+ /* DI1 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+ }
+
+ /*
+ * DI0/1 DP-FG channel:
+ */
+ mxc_register_device(&mxc_fb_devices[2], NULL);
+
+ return 0;
+}
+device_initcall(mxc_init_fb);
+
+static int handle_edid(int *pixclk)
+{
+#if 0
+ int err = 0;
+ int dvi = 0;
+ int fb0 = 0;
+ int fb1 = 1;
+ struct fb_var_screeninfo screeninfo;
+ struct i2c_adapter *adp;
+
+ memset(&screeninfo, 0, sizeof(screeninfo));
+
+ adp = i2c_get_adapter(1);
+
+ if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) {
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 1);
+ msleep(1);
+ }
+ err = read_edid(adp, &screeninfo, &dvi);
+ if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0)
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 0);
+
+ if (!err) {
+ printk(KERN_INFO " EDID read\n");
+ if (!dvi) {
+ enable_vga = 1;
+ fb0 = 1; /* fb0 will be VGA */
+ fb1 = 0; /* fb1 will be DVI or TV */
+ }
+
+ /* Handle TV modes */
+ /* This logic is fairly complex yet still doesn't handle all
+ possibilities. Once a customer knows the platform
+ configuration, this should be simplified to what is desired.
+ */
+ if (screeninfo.xres == 1920 && screeninfo.yres != 1200) {
+ /* MX51 can't handle clock speeds for anything larger.*/
+ if (!enable_tv)
+ enable_tv = 1;
+ if (enable_vga || enable_wvga || enable_tv == 2)
+ enable_tv = 2;
+ fb_data[0].mode = &(video_modes[0]);
+ if (!enable_wvga)
+ fb_data[1].mode_str = "800x600M-16@60";
+ } else if (screeninfo.xres > 1280 && screeninfo.yres > 1024) {
+ if (!enable_wvga) {
+ fb_data[fb0].mode_str = "1280x1024M-16@60";
+ fb_data[fb1].mode_str = NULL;
+ } else {
+ /* WVGA is preset so the DVI can't be > this. */
+ fb_data[0].mode_str = "1024x768M-16@60";
+ }
+ } else if (screeninfo.xres > 0 && screeninfo.yres > 0) {
+ if (!enable_wvga) {
+ fb_data[fb0].mode =
+ kzalloc(sizeof(struct fb_videomode),
+ GFP_KERNEL);
+ fb_var_to_videomode(fb_data[fb0].mode,
+ &screeninfo);
+ fb_data[fb0].mode_str = NULL;
+ if (screeninfo.xres >= 1280 &&
+ screeninfo.yres > 720)
+ fb_data[fb1].mode_str = NULL;
+ else if (screeninfo.xres > 1024 &&
+ screeninfo.yres > 768)
+ fb_data[fb1].mode_str =
+ "800x600M-16@60";
+ else if (screeninfo.xres > 800 &&
+ screeninfo.yres > 600)
+ fb_data[fb1].mode_str =
+ "1024x768M-16@60";
+ } else {
+ /* A WVGA panel was specified and an EDID was
+ read thus there is a DVI monitor attached. */
+ if (screeninfo.xres >= 1024)
+ fb_data[0].mode_str = "1024x768M-16@60";
+ else if (screeninfo.xres >= 800)
+ fb_data[0].mode_str = "800x600M-16@60";
+ else
+ fb_data[0].mode_str = "640x480M-16@60";
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+static void dvi_reset(void)
+{
+ gpio_direction_output(BABBAGE_DVI_RESET, 0);
+ gpio_set_value(BABBAGE_DVI_RESET, 0);
+ msleep(50);
+
+ /* do reset */
+ gpio_set_value(BABBAGE_DVI_RESET, 1);
+ msleep(20); /* tRES >= 50us */
+
+ gpio_set_value(BABBAGE_DVI_RESET, 0);
+}
+
+static struct mxc_lcd_platform_data dvi_data = {
+ .core_reg = "VGEN1",
+ .io_reg = "VGEN3",
+ .reset = dvi_reset,
+};
+
+static void vga_reset(void)
+{
+
+ gpio_set_value(BABBAGE_VGA_RESET, 0);
+ msleep(50);
+ /* do reset */
+ gpio_set_value(BABBAGE_VGA_RESET, 1);
+ msleep(10); /* tRES >= 50us */
+ gpio_set_value(BABBAGE_VGA_RESET, 0);
+}
+
+static struct mxc_lcd_platform_data vga_data = {
+ .core_reg = "VCAM",
+ .io_reg = "VGEN3",
+ .analog_reg = "VAUDIO",
+ .reset = vga_reset,
+};
+
+static void si4702_reset(void)
+{
+ return;
+
+ gpio_set_value(BABBAGE_FM_RESET, 0);
+ msleep(100);
+ gpio_set_value(BABBAGE_FM_RESET, 1);
+ msleep(100);
+}
+
+static void si4702_clock_ctl(int flag)
+{
+ gpio_set_value(BABBAGE_FM_PWR, flag);
+ msleep(100);
+}
+
+static void si4702_gpio_get(void)
+{
+ gpio_request(BABBAGE_FM_PWR, "fm-power");
+ gpio_direction_output(BABBAGE_FM_PWR, 0);
+}
+
+static void si4702_gpio_put(void)
+{
+}
+
+static struct mxc_fm_platform_data si4702_data = {
+ .reg_vio = "SW4",
+ .reg_vdd = "VIOHI",
+ .gpio_get = si4702_gpio_get,
+ .gpio_put = si4702_gpio_put,
+ .reset = si4702_reset,
+ .clock_ctl = si4702_clock_ctl,
+};
+
+static struct mxc_camera_platform_data camera_data = {
+ .io_regulator = "SW4",
+ .analog_regulator = "VIOHI",
+ .mclk = 24000000,
+ .csi = 0,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ .type = "ov3640",
+ .addr = 0x3C,
+ .platform_data = (void *)&camera_data,
+ },
+};
+
+static struct mxc_lightsensor_platform_data ls_data = {
+ .vdd_reg = "VIOHI",
+ .rext = 100,
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "isl29003",
+ .addr = 0x44,
+ .platform_data = &ls_data,
+ },
+};
+
+static struct i2c_board_info mxc_i2c_hs_board_info[] __initdata = {
+ {
+ .type = "sii9022",
+ .addr = 0x39,
+ .platform_data = &dvi_data,
+ },
+ {
+ .type = "ch7026",
+ .addr = 0x75,
+ .platform_data = &vga_data,
+ },
+ {
+ .type = "si4702",
+ .addr = 0x10,
+ .platform_data = (void *)&si4702_data,
+ },
+};
+
+static struct mtd_partition mxc_spi_nor_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x00040000,},
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,},
+
+};
+
+static struct mtd_partition mxc_dataflash_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x000100000,},
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,},
+};
+
+static struct flash_platform_data mxc_spi_flash_data[] = {
+ {
+ .name = "mxc_spi_nor",
+ .parts = mxc_spi_nor_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_spi_nor_partitions),
+ .type = "sst25vf016b",},
+ {
+ .name = "mxc_dataflash",
+ .parts = mxc_dataflash_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_dataflash_partitions),
+ .type = "at45db321d",}
+};
+
+static struct spi_board_info mxc_spi_nor_device[] __initdata = {
+ {
+ .modalias = "mxc_spi_nor",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .platform_data = &mxc_spi_flash_data[0],
+ },
+};
+
+static struct spi_board_info mxc_dataflash_device[] __initdata = {
+ {
+ .modalias = "mxc_dataflash",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .platform_data = &mxc_spi_flash_data[1],},
+};
+
+static int sdhc_write_protect(struct device *dev)
+{
+ unsigned short rc = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ rc = gpio_get_value(BABBAGE_SD1_WP);
+ else
+ rc = gpio_get_value(BABBAGE_SD2_WP);
+
+ return rc;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret;
+
+ if (to_platform_device(dev)->id == 0) {
+ ret = gpio_get_value(BABBAGE_SD1_CD);
+ return ret;
+ } else { /* config the det pin for SDHC2 */
+ if (board_is_rev(BOARD_REV_2))
+ /* BB2.5 */
+ ret = gpio_get_value(BABBAGE_SD2_CD_2_5);
+ else
+ /* BB2.0 */
+ ret = gpio_get_value(BABBAGE_SD2_CD_2_0);
+ return ret;
+ }
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
+ MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 150000,
+ .max_clk = 52000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
+ MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 150000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static int mxc_sgtl5000_amp_enable(int enable)
+{
+ gpio_set_value(BABBAGE_AUDAMP_STBY, enable ? 1 : 0);
+ return 0;
+}
+
+static int mxc_sgtl5000_clock_enable(int enable)
+{
+ gpio_set_value(BABBAGE_AUDIO_CLK_EN, !enable);
+ return 0;
+}
+
+static int headphone_det_status(void)
+{
+ return (gpio_get_value(BABBAGE_HEADPHONE_DET) == 0);
+}
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 3,
+ .hp_irq = IOMUX_TO_IRQ_V3(BABBAGE_HEADPHONE_DET),
+ .hp_status = headphone_det_status,
+ .amp_enable = mxc_sgtl5000_amp_enable,
+ .clock_enable = mxc_sgtl5000_clock_enable,
+ .sysclk = 12288000,
+};
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+static int __initdata enable_w1 = { 0 };
+static int __init w1_setup(char *__unused)
+{
+ enable_w1 = 1;
+ return cpu_is_mx51();
+}
+
+__setup("w1", w1_setup);
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ char *str;
+ struct tag *t;
+ struct tag *mem_tag = 0;
+ int total_mem = SZ_512M;
+ int left_mem = 0;
+ int gpu_mem = SZ_64M;
+ int fb_mem = SZ_32M;
+
+ mxc_set_cpu_type(MXC_CPU_MX51);
+
+ get_cpu_wp = mx51_babbage_get_cpu_wp;
+ set_num_cpu_wp = mx51_babbage_set_num_cpu_wp;
+
+ for_each_tag(mem_tag, tags) {
+ if (mem_tag->hdr.tag == ATAG_MEM) {
+ total_mem = mem_tag->u.mem.size;
+ left_mem = total_mem - gpu_mem - fb_mem;
+ break;
+ }
+ }
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "mem=");
+ if (str != NULL) {
+ str += 4;
+ left_mem = memparse(str, &str);
+ if (left_mem == 0 || left_mem > total_mem)
+ left_mem = total_mem - gpu_mem - fb_mem;
+ }
+
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "gpu_memory=");
+ if (str != NULL) {
+ str += 11;
+ gpu_mem = memparse(str, &str);
+ }
+
+ break;
+ }
+ }
+
+ if (mem_tag) {
+ fb_mem = total_mem - left_mem - gpu_mem;
+ if (fb_mem < 0) {
+ gpu_mem = total_mem - left_mem;
+ fb_mem = 0;
+ }
+ mem_tag->u.mem.size = left_mem;
+
+ /*reserve memory for gpu*/
+ gpu_device.resource[5].start =
+ mem_tag->u.mem.start + left_mem;
+ gpu_device.resource[5].end =
+ gpu_device.resource[5].start + gpu_mem - 1;
+#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \
+ defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
+ if (fb_mem) {
+ mxcfb_resources[0].start =
+ gpu_device.resource[5].end + 1;
+ mxcfb_resources[0].end =
+ mxcfb_resources[0].start + fb_mem - 1;
+ } else {
+ mxcfb_resources[0].start = 0;
+ mxcfb_resources[0].end = 0;
+ }
+#endif
+ }
+}
+
+#define PWGT1SPIEN (1<<15)
+#define PWGT2SPIEN (1<<16)
+#define USEROFFSPI (1<<3)
+
+static void mxc_power_off(void)
+{
+ /* We can do power down one of two ways:
+ Set the power gating
+ Set USEROFFSPI */
+
+ /* Set the power gate bits to power down */
+ pmic_write_reg(REG_POWER_MISC, (PWGT1SPIEN|PWGT2SPIEN),
+ (PWGT1SPIEN|PWGT2SPIEN));
+}
+
+/*!
+ * Power Key interrupt handler.
+ */
+static irqreturn_t power_key_int(int irq, void *dev_id)
+{
+ pwrkey_callback cb = (pwrkey_callback)dev_id;
+
+ cb((void *)1);
+
+ if (gpio_get_value(BABBAGE_POWER_KEY))
+ set_irq_type(irq, IRQF_TRIGGER_FALLING);
+ else
+ set_irq_type(irq, IRQF_TRIGGER_RISING);
+
+ return 0;
+}
+
+static void mxc_register_powerkey(pwrkey_callback pk_cb)
+{
+ /* Set power key as wakeup resource */
+ int irq, ret;
+ irq = IOMUX_TO_IRQ_V3(BABBAGE_POWER_KEY);
+
+ if (gpio_get_value(BABBAGE_POWER_KEY))
+ set_irq_type(irq, IRQF_TRIGGER_FALLING);
+ else
+ set_irq_type(irq, IRQF_TRIGGER_RISING);
+
+ ret = request_irq(irq, power_key_int, 0, "power_key", pk_cb);
+ if (ret)
+ pr_info("register on-off key interrupt failed\n");
+ else
+ enable_irq_wake(irq);
+}
+
+static int mxc_pwrkey_getstatus(int id)
+{
+ return gpio_get_value(BABBAGE_POWER_KEY);
+}
+
+static struct power_key_platform_data pwrkey_data = {
+ .key_value = KEY_F4,
+ .register_pwrkey = mxc_register_powerkey,
+ .get_key_status = mxc_pwrkey_getstatus,
+};
+
+static void __init mx51_babbage_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+ ARRAY_SIZE(mx51babbage_pads));
+
+ gpio_request(BABBAGE_PMIC_INT, "pmic-int");
+ gpio_request(BABBAGE_SD1_CD, "sdhc1-detect");
+ gpio_request(BABBAGE_SD1_WP, "sdhc1-wp");
+
+ gpio_direction_input(BABBAGE_PMIC_INT);
+ gpio_direction_input(BABBAGE_SD1_CD);
+ gpio_direction_input(BABBAGE_SD1_WP);
+
+ if (board_is_rev(BOARD_REV_2)) {
+ /* SD2 CD for BB2.5 */
+ gpio_request(BABBAGE_SD2_CD_2_5, "sdhc2-detect");
+ gpio_direction_input(BABBAGE_SD2_CD_2_5);
+ } else {
+ /* SD2 CD for BB2.0 */
+ gpio_request(BABBAGE_SD2_CD_2_0, "sdhc2-detect");
+ gpio_direction_input(BABBAGE_SD2_CD_2_0);
+ }
+ gpio_request(BABBAGE_SD2_WP, "sdhc2-wp");
+ gpio_direction_input(BABBAGE_SD2_WP);
+
+ /* reset usbh1 hub */
+ gpio_request(BABBAGE_USBH1_HUB_RST, "hub-rst");
+ gpio_direction_output(BABBAGE_USBH1_HUB_RST, 0);
+ gpio_set_value(BABBAGE_USBH1_HUB_RST, 0);
+ msleep(1);
+ gpio_set_value(BABBAGE_USBH1_HUB_RST, 1);
+
+ /* reset FEC PHY */
+ gpio_request(BABBAGE_FEC_PHY_RESET, "fec-phy-reset");
+ gpio_direction_output(BABBAGE_FEC_PHY_RESET, 0);
+ msleep(10);
+ gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+
+ /* reset FM */
+ gpio_request(BABBAGE_FM_RESET, "fm-reset");
+ gpio_direction_output(BABBAGE_FM_RESET, 0);
+ msleep(10);
+ gpio_set_value(BABBAGE_FM_RESET, 1);
+
+ /* Drive 26M_OSC_EN line high */
+ gpio_request(BABBAGE_26M_OSC_EN, "26m-osc-en");
+ gpio_direction_output(BABBAGE_26M_OSC_EN, 1);
+
+ /* Drive USB_CLK_EN_B line low */
+ gpio_request(BABBAGE_USB_CLK_EN_B, "usb-clk_en_b");
+ gpio_direction_output(BABBAGE_USB_CLK_EN_B, 0);
+
+ /* De-assert USB PHY RESETB */
+ gpio_request(BABBAGE_PHY_RESET, "usb-phy-reset");
+ gpio_direction_output(BABBAGE_PHY_RESET, 1);
+
+ /* hphone_det_b */
+ gpio_request(BABBAGE_HEADPHONE_DET, "hphone-det");
+ gpio_direction_input(BABBAGE_HEADPHONE_DET);
+
+ /* audio_clk_en_b */
+ gpio_request(BABBAGE_AUDIO_CLK_EN, "audio-clk-en");
+ gpio_direction_output(BABBAGE_AUDIO_CLK_EN, 0);
+
+ /* power key */
+ gpio_request(BABBAGE_POWER_KEY, "power-key");
+ gpio_direction_input(BABBAGE_POWER_KEY);
+
+ if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) {
+ /* DVI_I2C_ENB = 0 tristates the DVI I2C level shifter */
+ gpio_request(BABBAGE_DVI_I2C_EN, "dvi-i2c-en");
+ gpio_direction_output(BABBAGE_DVI_I2C_EN, 0);
+ }
+
+ /* Deassert VGA reset to free i2c bus */
+ gpio_request(BABBAGE_VGA_RESET, "vga-reset");
+ gpio_direction_output(BABBAGE_VGA_RESET, 1);
+
+ /* LCD related gpio */
+ gpio_request(BABBAGE_DISP_BRIGHTNESS_CTL, "disp-brightness-ctl");
+ gpio_request(BABBAGE_LVDS_POWER_DOWN, "lvds-power-down");
+ gpio_request(BABBAGE_LCD_3V3_ON, "lcd-3v3-on");
+ gpio_request(BABBAGE_LCD_5V_ON, "lcd-5v-on");
+ gpio_direction_output(BABBAGE_DISP_BRIGHTNESS_CTL, 0);
+ gpio_direction_output(BABBAGE_LVDS_POWER_DOWN, 0);
+ gpio_direction_output(BABBAGE_LCD_3V3_ON, 0);
+ gpio_direction_output(BABBAGE_LCD_5V_ON, 0);
+
+ /* Camera reset */
+ gpio_request(BABBAGE_CAM_RESET, "cam-reset");
+ gpio_direction_output(BABBAGE_CAM_RESET, 1);
+
+ /* Camera low power */
+ gpio_request(BABBAGE_CAM_LOW_POWER, "cam-low-power");
+ gpio_direction_output(BABBAGE_CAM_LOW_POWER, 0);
+
+ /* OSC_EN */
+ gpio_request(BABBAGE_OSC_EN_B, "osc-en");
+ gpio_direction_output(BABBAGE_OSC_EN_B, 1);
+
+ if (enable_w1) {
+ /* OneWire */
+ struct pad_desc onewire = MX51_PAD_OWIRE_LINE__OWIRE_LINE;
+ mxc_iomux_v3_setup_pad(&onewire);
+ }
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ mxc_ipu_data.di_clk[0] = clk_get(NULL, "ipu_di0_clk");
+ mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk");
+ mxc_ipu_data.csi_clk[0] = clk_get(NULL, "csi_mclk1");
+ mxc_ipu_data.csi_clk[1] = clk_get(NULL, "csi_mclk2");
+
+ mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk");
+ clk_put(mxc_spdif_data.spdif_core_clk);
+ /* SD card detect irqs */
+ mxcsdhc2_device.resource[2].start = IOMUX_TO_IRQ_V3(BABBAGE_SD2_CD_2_5);
+ mxcsdhc2_device.resource[2].end = IOMUX_TO_IRQ_V3(BABBAGE_SD2_CD_2_5);
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(BABBAGE_SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(BABBAGE_SD1_CD);
+
+ mxc_cpu_common_init();
+ mx51_babbage_io_init();
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+ mxc_register_device(&mxci2c_hs_device, &mxci2c_hs_data);
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_w1_master_device, &mxc_w1_data);
+ mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
+ mxc_register_device(&mxc_tve_device, &tve_data);
+ mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
+ mxc_register_device(&gpu_device, NULL);
+ mxc_register_device(&mxcscc_device, NULL);
+ mxc_register_device(&mx51_lpmode_device, NULL);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+ mxc_register_device(&sdram_autogating_device, NULL);
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&mxc_dvfs_per_device, &dvfs_per_data);
+ mxc_register_device(&mxc_iim_device, &iim_data);
+ mxc_register_device(&mxc_pwm1_device, NULL);
+ mxc_register_device(&mxc_pwm1_backlight_device,
+ &mxc_pwm_backlight_data);
+ mxc_register_device(&mxc_keypad_device, &keypad_plat_data);
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc2_device, &mmc2_data);
+ mxc_register_device(&mxc_ssi1_device, NULL);
+ mxc_register_device(&mxc_ssi2_device, NULL);
+ mxc_register_device(&mxc_ssi3_device, NULL);
+ mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
+ mxc_register_device(&mxc_fec_device, NULL);
+ mxc_register_device(&mxc_v4l2_device, NULL);
+ mxc_register_device(&mxc_v4l2out_device, NULL);
+ mxc_register_device(&mxc_powerkey_device, &pwrkey_data);
+
+ mx51_babbage_init_mc13892();
+
+ if (board_is_rev(BOARD_REV_2))
+ /* BB2.5 */
+ spi_register_board_info(mxc_dataflash_device,
+ ARRAY_SIZE(mxc_dataflash_device));
+ else
+ /* BB2.0 */
+ spi_register_board_info(mxc_spi_nor_device,
+ ARRAY_SIZE(mxc_spi_nor_device));
+
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) >= 1) {
+ vga_data.core_reg = NULL;
+ vga_data.io_reg = NULL;
+ vga_data.analog_reg = NULL;
+ }
+ i2c_register_board_info(3, mxc_i2c_hs_board_info,
+ ARRAY_SIZE(mxc_i2c_hs_board_info));
+
+ pm_power_off = mxc_power_off;
+
+ if (cpu_is_mx51_rev(CHIP_REV_1_1) == 2) {
+ sgtl5000_data.sysclk = 26000000;
+ }
+ gpio_request(BABBAGE_AUDAMP_STBY, "audioamp-stdby");
+ gpio_direction_output(BABBAGE_AUDAMP_STBY, 0);
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+
+ mx5_usb_dr_init();
+ mx5_usbh1_init();
+}
+
+static void __init mx51_babbage_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ /* Change the CPU voltages for TO2*/
+ if (cpu_is_mx51_rev(CHIP_REV_2_0) <= 1) {
+ cpu_wp_auto[0].cpu_voltage = 1175000;
+ cpu_wp_auto[1].cpu_voltage = 1100000;
+ cpu_wp_auto[2].cpu_voltage = 1000000;
+ }
+
+ mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx51_babbage_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX51_BABBAGE data structure.
+ */
+/* *INDENT-OFF* */
+MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .phys_io = AIPS1_BASE_ADDR,
+ .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx51_babbage_pmic_mc13892.c b/arch/arm/mach-mx5/mx51_babbage_pmic_mc13892.c
new file mode 100644
index 000000000000..1d5a06bfb5f4
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_babbage_pmic_mc13892.c
@@ -0,0 +1,436 @@
+/*
+ * mx51-babbage-pmic-mc13892.c -- i.MX51 Babbage Driver for Atlas MC13892 PMIC
+ */
+ /*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+ /*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/pmic_external.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13892/core.h>
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.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)
+
+/* Coin cell charger enable */
+#define COINCHEN_LSH 23
+#define COINCHEN_WID 1
+/* Coin cell charger voltage setting */
+#define VCOIN_LSH 20
+#define VCOIN_WID 3
+
+/* Coin Charger voltage */
+#define VCOIN_2_5V 0x0
+#define VCOIN_2_7V 0x1
+#define VCOIN_2_8V 0x2
+#define VCOIN_2_9V 0x3
+#define VCOIN_3_0V 0x4
+#define VCOIN_3_1V 0x5
+#define VCOIN_3_2V 0x6
+#define VCOIN_3_3V 0x7
+
+/* Keeps VSRTC and CLK32KMCU on for all states */
+#define DRM_LSH 4
+#define DRM_WID 1
+
+/* regulator standby mask */
+#define GEN1_STBY_MASK (1 << 1)
+#define IOHI_STBY_MASK (1 << 4)
+#define DIG_STBY_MASK (1 << 10)
+#define GEN2_STBY_MASK (1 << 13)
+#define PLL_STBY_MASK (1 << 16)
+#define USB2_STBY_MASK (1 << 19)
+
+#define GEN3_STBY_MASK (1 << 1)
+#define CAM_STBY_MASK (1 << 7)
+#define VIDEO_STBY_MASK (1 << 13)
+#define AUDIO_STBY_MASK (1 << 16)
+#define SD_STBY_MASK (1 << 19)
+
+/* 0x92412 */
+#define REG_MODE_0_ALL_MASK (GEN1_STBY_MASK |\
+ DIG_STBY_MASK | GEN2_STBY_MASK |\
+ PLL_STBY_MASK)
+/* 0x92082 */
+#define REG_MODE_1_ALL_MASK (CAM_STBY_MASK | VIDEO_STBY_MASK |\
+ AUDIO_STBY_MASK | SD_STBY_MASK)
+
+/* switch mode setting */
+#define SW1MODE_LSB 0
+#define SW2MODE_LSB 10
+#define SW3MODE_LSB 0
+#define SW4MODE_LSB 8
+
+#define SWMODE_MASK 0xF
+#define SWMODE_AUTO 0x8
+
+/* CPU */
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+static struct regulator_consumer_supply vdig_consumers[] = {
+ {
+ /* sgtl5000 */
+ .supply = "VDDA",
+ .dev_name = "1-000a",
+ },
+};
+
+static struct regulator_consumer_supply vvideo_consumers[] = {
+ {
+ /* sgtl5000 */
+ .supply = "VDDIO",
+ .dev_name = "1-000a",
+ },
+};
+
+struct mc13892;
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = mV_to_uV(600),
+ .max_uV = mV_to_uV(1375),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 850000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = mV_to_uV(1650),
+ .max_uV = mV_to_uV(1650),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
+ .consumer_supplies = vdig_consumers,
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .min_uV = mV_to_uV(2400),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .min_uV = mV_to_uV(2775),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .apply_uV = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
+ .consumer_supplies = vvideo_consumers,
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = mV_to_uV(2300),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vsd_init = {
+ .constraints = {
+ .name = "VSD",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ }
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(1200),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(2900),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ }
+};
+
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .name = "GPO1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo2_init = {
+ .constraints = {
+ .name = "GPO2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .name = "GPO3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo4_init = {
+ .constraints = {
+ .name = "GPO4",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static int mc13892_regulator_init(struct mc13892 *mc13892)
+{
+ unsigned int value, register_mask;
+ printk("Initializing regulators for Babbage.\n");
+ if (mxc_cpu_is_rev(CHIP_REV_2_0) < 0)
+ sw2_init.constraints.state_mem.uV = 1100000;
+ else if (mxc_cpu_is_rev(CHIP_REV_2_0) == 1) {
+ sw2_init.constraints.state_mem.uV = 1250000;
+ sw1_init.constraints.state_mem.uV = 1000000;
+ }
+
+ /* enable standby controll for all regulators */
+ pmic_read_reg(REG_MODE_0, &value, 0xffffff);
+ value |= REG_MODE_0_ALL_MASK;
+ pmic_write_reg(REG_MODE_0, value, 0xffffff);
+
+ pmic_read_reg(REG_MODE_1, &value, 0xffffff);
+ value |= REG_MODE_1_ALL_MASK;
+ pmic_write_reg(REG_MODE_1, value, 0xffffff);
+
+ /* enable switch audo mode */
+ pmic_read_reg(REG_IDENTIFICATION, &value, 0xffffff);
+ /* only for mc13892 2.0A */
+ if ((value & 0x0000FFFF) == 0x45d0) {
+ pmic_read_reg(REG_SW_4, &value, 0xffffff);
+ register_mask = (SWMODE_MASK << SW1MODE_LSB) |
+ (SWMODE_MASK << SW2MODE_LSB);
+ value &= ~register_mask;
+ value |= (SWMODE_AUTO << SW1MODE_LSB) |
+ (SWMODE_AUTO << SW2MODE_LSB);
+ pmic_write_reg(REG_SW_4, value, 0xffffff);
+
+ pmic_read_reg(REG_SW_5, &value, 0xffffff);
+ register_mask = (SWMODE_MASK << SW3MODE_LSB) |
+ (SWMODE_MASK << SW4MODE_LSB);
+ value &= ~register_mask;
+ value |= (SWMODE_AUTO << SW3MODE_LSB) |
+ (SWMODE_AUTO << SW4MODE_LSB);
+ pmic_write_reg(REG_SW_5, value, 0xffffff);
+ }
+
+ /* Enable coin cell charger */
+ value = BITFVAL(COINCHEN, 1) | BITFVAL(VCOIN, VCOIN_3_0V);
+ register_mask = BITFMASK(COINCHEN) | BITFMASK(VCOIN);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+
+#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE)
+ value = BITFVAL(DRM, 1);
+ register_mask = BITFMASK(DRM);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+#endif
+
+ mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init);
+ mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init);
+ mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init);
+ mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init);
+ mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init);
+ mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init);
+ mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init);
+ mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init);
+ mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init);
+ mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init);
+ mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init);
+ mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init);
+
+ regulator_has_full_constraints();
+
+ return 0;
+}
+
+static struct mc13892_platform_data mc13892_plat = {
+ .init = mc13892_regulator_init,
+};
+
+static struct spi_board_info __initdata mc13892_spi_device = {
+ .modalias = "pmic_spi",
+ .irq = IOMUX_TO_IRQ_V3(8),
+ .max_speed_hz = 6000000, /* max spi SCK clock speed in HZ */
+ .bus_num = 1,
+ .chip_select = 0,
+ .platform_data = &mc13892_plat,
+};
+
+
+int __init mx51_babbage_init_mc13892(void)
+{
+ return spi_register_board_info(&mc13892_spi_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx51_pins.h b/arch/arm/mach-mx5/mx51_pins.h
new file mode 100644
index 000000000000..351cdb29a32a
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_pins.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ASM_ARCH_MXC_MX51_PINS_H__
+#define __ASM_ARCH_MXC_MX51_PINS_H__
+#include "iomux.h"
+
+/*!
+ * @file arch-mxc/mx51_pins.h
+ *
+ * @brief MX51 I/O Pin List
+ *
+ * @ingroup GPIO_MX51
+ */
+
+#ifndef __ASSEMBLY__
+
+#define PAD_I_START_MX51 0x3F0
+#define INPUT_CTL_START_MX51 0x8C4
+#define INPUT_CTL_START_MX51_TO1 0x928
+
+#define MUX_I_END_MX51 (PAD_I_START_MX51 - 4)
+
+#define _MXC_BUILD_PIN_MX51(gp, gi, ga, mi, pi) \
+ (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \
+ ((mi) << MUX_I) | \
+ ((pi - PAD_I_START_MX51) << PAD_I) | \
+ ((ga) << GPIO_I))
+
+#define _MXC_BUILD_GPIO_PIN_MX51(gp, gi, ga, mi, pi) \
+ _MXC_BUILD_PIN_MX51(gp, gi, ga, mi, pi)
+
+#define _MXC_BUILD_NON_GPIO_PIN_MX51(mi, pi) \
+ _MXC_BUILD_PIN_MX51(NON_GPIO_PORT, 0, 0, mi, pi)
+/*!
+ * This enumeration is constructed based on the Section
+ * "sw_pad_ctl & sw_mux_ctl details" of the MX51 IC Spec. Each enumerated
+ * value is constructed based on the rules described above.
+ */
+enum iomux_pins_mx51 {
+ MX51_PIN_EIM_DA0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1C, 0x7A8),
+ MX51_PIN_EIM_DA1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x20, 0x7A8),
+ MX51_PIN_EIM_DA2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x24, 0x7A8),
+ MX51_PIN_EIM_DA3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x28, 0x7A8),
+ MX51_PIN_EIM_DA4 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2C, 0x7AC),
+ MX51_PIN_EIM_DA5 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x30, 0x7AC),
+ MX51_PIN_EIM_DA6 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x34, 0x7AC),
+ MX51_PIN_EIM_DA7 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x38, 0x7AC),
+ MX51_PIN_EIM_DA8 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3C, 0x7B0),
+ MX51_PIN_EIM_DA9 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x40, 0x7B0),
+ MX51_PIN_EIM_DA10 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x44, 0x7B0),
+ MX51_PIN_EIM_DA11 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x48, 0x7B0),
+ MX51_PIN_EIM_DA12 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x4C, 0x7BC),
+ MX51_PIN_EIM_DA13 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x50, 0x7BC),
+ MX51_PIN_EIM_DA14 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x54, 0x7BC),
+ MX51_PIN_EIM_DA15 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x58, 0x7BC),
+ MX51_PIN_EIM_D16 = _MXC_BUILD_GPIO_PIN_MX51(1, 0, 1, 0x5C, 0x3F0),
+ MX51_PIN_EIM_D17 = _MXC_BUILD_GPIO_PIN_MX51(1, 1, 1, 0x60, 0x3F4),
+ MX51_PIN_EIM_D18 = _MXC_BUILD_GPIO_PIN_MX51(1, 2, 1, 0x64, 0x3F8),
+ MX51_PIN_EIM_D19 = _MXC_BUILD_GPIO_PIN_MX51(1, 3, 1, 0x68, 0x3FC),
+ MX51_PIN_EIM_D20 = _MXC_BUILD_GPIO_PIN_MX51(1, 4, 1, 0x6C, 0x400),
+ MX51_PIN_EIM_D21 = _MXC_BUILD_GPIO_PIN_MX51(1, 5, 1, 0x70, 0x404),
+ MX51_PIN_EIM_D22 = _MXC_BUILD_GPIO_PIN_MX51(1, 6, 1, 0x74, 0x408),
+ MX51_PIN_EIM_D23 = _MXC_BUILD_GPIO_PIN_MX51(1, 7, 1, 0x78, 0x40C),
+ MX51_PIN_EIM_D24 = _MXC_BUILD_GPIO_PIN_MX51(1, 8, 1, 0x7C, 0x410),
+ MX51_PIN_EIM_D25 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x80, 0x414),
+ MX51_PIN_EIM_D26 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x84, 0x418),
+ MX51_PIN_EIM_D27 = _MXC_BUILD_GPIO_PIN_MX51(1, 9, 1, 0x88, 0x41C),
+ MX51_PIN_EIM_D28 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x8C, 0x420),
+ MX51_PIN_EIM_D29 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x90, 0x424),
+ MX51_PIN_EIM_D30 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x94, 0x428),
+ MX51_PIN_EIM_D31 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x98, 0x42C),
+ MX51_PIN_EIM_A16 = _MXC_BUILD_GPIO_PIN_MX51(1, 10, 1, 0x9C, 0x430),
+ MX51_PIN_EIM_A17 = _MXC_BUILD_GPIO_PIN_MX51(1, 11, 1, 0xA0, 0x434),
+ MX51_PIN_EIM_A18 = _MXC_BUILD_GPIO_PIN_MX51(1, 12, 1, 0xA4, 0x438),
+ MX51_PIN_EIM_A19 = _MXC_BUILD_GPIO_PIN_MX51(1, 13, 1, 0xA8, 0x43C),
+ MX51_PIN_EIM_A20 = _MXC_BUILD_GPIO_PIN_MX51(1, 14, 1, 0xAC, 0x440),
+ MX51_PIN_EIM_A21 = _MXC_BUILD_GPIO_PIN_MX51(1, 15, 1, 0xB0, 0x444),
+ MX51_PIN_EIM_A22 = _MXC_BUILD_GPIO_PIN_MX51(1, 16, 1, 0xB4, 0x448),
+ MX51_PIN_EIM_A23 = _MXC_BUILD_GPIO_PIN_MX51(1, 17, 1, 0xB8, 0x44C),
+ MX51_PIN_EIM_A24 = _MXC_BUILD_GPIO_PIN_MX51(1, 18, 1, 0xBC, 0x450),
+ MX51_PIN_EIM_A25 = _MXC_BUILD_GPIO_PIN_MX51(1, 19, 1, 0xC0, 0x454),
+ MX51_PIN_EIM_A26 = _MXC_BUILD_GPIO_PIN_MX51(1, 20, 1, 0xC4, 0x458),
+ MX51_PIN_EIM_A27 = _MXC_BUILD_GPIO_PIN_MX51(1, 21, 1, 0xC8, 0x45C),
+ MX51_PIN_EIM_EB0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0xCC, 0x460),
+ MX51_PIN_EIM_EB1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0xD0, 0x464),
+ MX51_PIN_EIM_EB2 = _MXC_BUILD_GPIO_PIN_MX51(1, 22, 1, 0xD4, 0x468),
+ MX51_PIN_EIM_EB3 = _MXC_BUILD_GPIO_PIN_MX51(1, 23, 1, 0xD8, 0x46C),
+ MX51_PIN_EIM_OE = _MXC_BUILD_GPIO_PIN_MX51(1, 24, 1, 0xDC, 0x470),
+ MX51_PIN_EIM_CS0 = _MXC_BUILD_GPIO_PIN_MX51(1, 25, 1, 0xE0, 0x474),
+ MX51_PIN_EIM_CS1 = _MXC_BUILD_GPIO_PIN_MX51(1, 26, 1, 0xE4, 0x478),
+ MX51_PIN_EIM_CS2 = _MXC_BUILD_GPIO_PIN_MX51(1, 27, 1, 0xE8, 0x47C),
+ MX51_PIN_EIM_CS3 = _MXC_BUILD_GPIO_PIN_MX51(1, 28, 1, 0xEC, 0x480),
+ MX51_PIN_EIM_CS4 = _MXC_BUILD_GPIO_PIN_MX51(1, 29, 1, 0xF0, 0x484),
+ MX51_PIN_EIM_CS5 = _MXC_BUILD_GPIO_PIN_MX51(1, 30, 1, 0xF4, 0x488),
+ MX51_PIN_EIM_DTACK = _MXC_BUILD_GPIO_PIN_MX51(1, 31, 1, 0xF8, 0x48C),
+ MX51_PIN_EIM_LBA = _MXC_BUILD_GPIO_PIN_MX51(2, 1, 1, 0xFC, 0x494),
+ MX51_PIN_EIM_CRE = _MXC_BUILD_GPIO_PIN_MX51(2, 2, 1, 0x100, 0x4A0),
+ MX51_PIN_DRAM_CS1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x104, 0x4D0),
+ MX51_PIN_NANDF_WE_B = _MXC_BUILD_GPIO_PIN_MX51(2, 3, 3, 0x108, 0x4E4),
+ MX51_PIN_NANDF_RE_B = _MXC_BUILD_GPIO_PIN_MX51(2, 4, 3, 0x10C, 0x4E8),
+ MX51_PIN_NANDF_ALE = _MXC_BUILD_GPIO_PIN_MX51(2, 5, 3, 0x110, 0x4EC),
+ MX51_PIN_NANDF_CLE = _MXC_BUILD_GPIO_PIN_MX51(2, 6, 3, 0x114, 0x4F0),
+ MX51_PIN_NANDF_WP_B = _MXC_BUILD_GPIO_PIN_MX51(2, 7, 3, 0x118, 0x4F4),
+ MX51_PIN_NANDF_RB0 = _MXC_BUILD_GPIO_PIN_MX51(2, 8, 3, 0x11C, 0x4F8),
+ MX51_PIN_NANDF_RB1 = _MXC_BUILD_GPIO_PIN_MX51(2, 9, 3, 0x120, 0x4FC),
+ MX51_PIN_NANDF_RB2 = _MXC_BUILD_GPIO_PIN_MX51(2, 10, 3, 0x124, 0x500),
+ MX51_PIN_NANDF_RB3 = _MXC_BUILD_GPIO_PIN_MX51(2, 11, 3, 0x128, 0x504),
+ MX51_PIN_GPIO_NAND = _MXC_BUILD_GPIO_PIN_MX51(2, 12, 3, 0x12C, 0x514),
+ MX51_PIN_NANDF_RB4 = MX51_PIN_GPIO_NAND,
+ MX51_PIN_NANDF_RB5 = _MXC_BUILD_GPIO_PIN_MX51(2, 13, 3, 0x130, 0x5D8),
+ MX51_PIN_NANDF_RB6 = _MXC_BUILD_GPIO_PIN_MX51(2, 14, 3, 0x134, 0x5DC),
+ MX51_PIN_NANDF_RB7 = _MXC_BUILD_GPIO_PIN_MX51(2, 15, 3, 0x138, 0x5E0),
+ MX51_PIN_NANDF_CS0 = _MXC_BUILD_GPIO_PIN_MX51(2, 16, 3, 0x130, 0x518),
+ MX51_PIN_NANDF_CS1 = _MXC_BUILD_GPIO_PIN_MX51(2, 17, 3, 0x134, 0x51C),
+ MX51_PIN_NANDF_CS2 = _MXC_BUILD_GPIO_PIN_MX51(2, 18, 3, 0x138, 0x520),
+ MX51_PIN_NANDF_CS3 = _MXC_BUILD_GPIO_PIN_MX51(2, 19, 3, 0x13C, 0x524),
+ MX51_PIN_NANDF_CS4 = _MXC_BUILD_GPIO_PIN_MX51(2, 20, 3, 0x140, 0x528),
+ MX51_PIN_NANDF_CS5 = _MXC_BUILD_GPIO_PIN_MX51(2, 21, 3, 0x144, 0x52C),
+ MX51_PIN_NANDF_CS6 = _MXC_BUILD_GPIO_PIN_MX51(2, 22, 3, 0x148, 0x530),
+ MX51_PIN_NANDF_CS7 = _MXC_BUILD_GPIO_PIN_MX51(2, 23, 3, 0x14C, 0x534),
+ MX51_PIN_NANDF_RDY_INT = _MXC_BUILD_GPIO_PIN_MX51(2, 24, 3, 0x150, 0x538),
+ MX51_PIN_NANDF_D15 = _MXC_BUILD_GPIO_PIN_MX51(2, 25, 3, 0x154, 0x53C),
+ MX51_PIN_NANDF_D14 = _MXC_BUILD_GPIO_PIN_MX51(2, 26, 3, 0x158, 0x540),
+ MX51_PIN_NANDF_D13 = _MXC_BUILD_GPIO_PIN_MX51(2, 27, 3, 0x15C, 0x544),
+ MX51_PIN_NANDF_D12 = _MXC_BUILD_GPIO_PIN_MX51(2, 28, 3, 0x160, 0x548),
+ MX51_PIN_NANDF_D11 = _MXC_BUILD_GPIO_PIN_MX51(2, 29, 3, 0x164, 0x54C),
+ MX51_PIN_NANDF_D10 = _MXC_BUILD_GPIO_PIN_MX51(2, 30, 3, 0x168, 0x550),
+ MX51_PIN_NANDF_D9 = _MXC_BUILD_GPIO_PIN_MX51(2, 31, 3, 0x16C, 0x554),
+ MX51_PIN_NANDF_D8 = _MXC_BUILD_GPIO_PIN_MX51(3, 0, 3, 0x170, 0x558),
+ MX51_PIN_NANDF_D7 = _MXC_BUILD_GPIO_PIN_MX51(3, 1, 3, 0x174, 0x55C),
+ MX51_PIN_NANDF_D6 = _MXC_BUILD_GPIO_PIN_MX51(3, 2, 3, 0x178, 0x560),
+ MX51_PIN_NANDF_D5 = _MXC_BUILD_GPIO_PIN_MX51(3, 3, 3, 0x17C, 0x564),
+ MX51_PIN_NANDF_D4 = _MXC_BUILD_GPIO_PIN_MX51(3, 4, 3, 0x180, 0x568),
+ MX51_PIN_NANDF_D3 = _MXC_BUILD_GPIO_PIN_MX51(3, 5, 3, 0x184, 0x56C),
+ MX51_PIN_NANDF_D2 = _MXC_BUILD_GPIO_PIN_MX51(3, 6, 3, 0x188, 0x570),
+ MX51_PIN_NANDF_D1 = _MXC_BUILD_GPIO_PIN_MX51(3, 7, 3, 0x18C, 0x574),
+ MX51_PIN_NANDF_D0 = _MXC_BUILD_GPIO_PIN_MX51(3, 8, 3, 0x190, 0x578),
+ MX51_PIN_CSI1_D8 = _MXC_BUILD_GPIO_PIN_MX51(2, 12, 3, 0x194, 0x57C),
+ MX51_PIN_CSI1_D9 = _MXC_BUILD_GPIO_PIN_MX51(2, 13, 3, 0x198, 0x580),
+ MX51_PIN_CSI1_D10 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x19C, 0x584),
+ MX51_PIN_CSI1_D11 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1A0, 0x588),
+ MX51_PIN_CSI1_D12 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1A4, 0x58C),
+ MX51_PIN_CSI1_D13 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1A8, 0x590),
+ MX51_PIN_CSI1_D14 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1AC, 0x594),
+ MX51_PIN_CSI1_D15 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1B0, 0x598),
+ MX51_PIN_CSI1_D16 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1B4, 0x59C),
+ MX51_PIN_CSI1_D17 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1B8, 0x5A0),
+ MX51_PIN_CSI1_D18 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1BC, 0x5A4),
+ MX51_PIN_CSI1_D19 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x1C0, 0x5A8),
+ MX51_PIN_CSI1_VSYNC = _MXC_BUILD_GPIO_PIN_MX51(2, 14, 3, 0x1C4, 0x5AC),
+ MX51_PIN_CSI1_HSYNC = _MXC_BUILD_GPIO_PIN_MX51(2, 15, 3, 0x1C8, 0x5B0),
+ MX51_PIN_CSI1_PIXCLK = _MXC_BUILD_NON_GPIO_PIN_MX51(NON_MUX_I, 0x5B4),
+ MX51_PIN_CSI1_MCLK = _MXC_BUILD_NON_GPIO_PIN_MX51(NON_MUX_I, 0x5B8),
+ MX51_PIN_CSI1_PKE0 = _MXC_BUILD_NON_GPIO_PIN_MX51(NON_MUX_I, 0x860),
+ MX51_PIN_CSI2_D12 = _MXC_BUILD_GPIO_PIN_MX51(3, 9, 3, 0x1CC, 0x5BC),
+ MX51_PIN_CSI2_D13 = _MXC_BUILD_GPIO_PIN_MX51(3, 10, 3, 0x1D0, 0x5C0),
+ MX51_PIN_CSI2_D14 = _MXC_BUILD_GPIO_PIN_MX51(3, 11, 3, 0x1D4, 0x5C4),
+ MX51_PIN_CSI2_D15 = _MXC_BUILD_GPIO_PIN_MX51(3, 12, 3, 0x1D8, 0x5C8),
+ MX51_PIN_CSI2_D16 = _MXC_BUILD_GPIO_PIN_MX51(3, 11, 3, 0x1DC, 0x5CC),
+ MX51_PIN_CSI2_D17 = _MXC_BUILD_GPIO_PIN_MX51(3, 12, 3, 0x1E0, 0x5D0),
+ MX51_PIN_CSI2_D18 = _MXC_BUILD_GPIO_PIN_MX51(3, 11, 3, 0x1E4, 0x5D4),
+ MX51_PIN_CSI2_D19 = _MXC_BUILD_GPIO_PIN_MX51(3, 12, 3, 0x1E8, 0x5D8),
+ MX51_PIN_CSI2_VSYNC = _MXC_BUILD_GPIO_PIN_MX51(3, 13, 3, 0x1EC, 0x5DC),
+ MX51_PIN_CSI2_HSYNC = _MXC_BUILD_GPIO_PIN_MX51(3, 14, 3, 0x1F0, 0x5E0),
+ MX51_PIN_CSI2_PIXCLK = _MXC_BUILD_GPIO_PIN_MX51(3, 15, 3, 0x1F4, 0x5E4),
+ MX51_PIN_CSI2_PKE0 = _MXC_BUILD_NON_GPIO_PIN_MX51(NON_MUX_I, 0x81C),
+ MX51_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN_MX51(3, 16, 3, 0x1F8, 0x5E8),
+ MX51_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN_MX51(3, 17, 3, 0x1FC, 0x5EC),
+ MX51_PIN_AUD3_BB_TXD = _MXC_BUILD_GPIO_PIN_MX51(3, 18, 3, 0x200, 0x5F0),
+ MX51_PIN_AUD3_BB_RXD = _MXC_BUILD_GPIO_PIN_MX51(3, 19, 3, 0x204, 0x5F4),
+ MX51_PIN_AUD3_BB_CK = _MXC_BUILD_GPIO_PIN_MX51(3, 20, 3, 0x208, 0x5F8),
+ MX51_PIN_AUD3_BB_FS = _MXC_BUILD_GPIO_PIN_MX51(3, 21, 3, 0x20C, 0x5FC),
+ MX51_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN_MX51(3, 22, 3, 0x210, 0x600),
+ MX51_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN_MX51(3, 23, 3, 0x214, 0x604),
+ MX51_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN_MX51(3, 24, 3, 0x218, 0x608),
+ MX51_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN_MX51(3, 25, 3, 0x21C, 0x60C),
+ MX51_PIN_CSPI1_RDY = _MXC_BUILD_GPIO_PIN_MX51(3, 26, 3, 0x220, 0x610),
+ MX51_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN_MX51(3, 27, 3, 0x224, 0x614),
+ MX51_PIN_UART1_RXD = _MXC_BUILD_GPIO_PIN_MX51(3, 28, 3, 0x228, 0x618),
+ MX51_PIN_UART1_TXD = _MXC_BUILD_GPIO_PIN_MX51(3, 29, 3, 0x22C, 0x61C),
+ MX51_PIN_UART1_RTS = _MXC_BUILD_GPIO_PIN_MX51(3, 30, 3, 0x230, 0x620),
+ MX51_PIN_UART1_CTS = _MXC_BUILD_GPIO_PIN_MX51(3, 31, 3, 0x234, 0x624),
+ MX51_PIN_UART2_RXD = _MXC_BUILD_GPIO_PIN_MX51(0, 20, 3, 0x238, 0x628),
+ MX51_PIN_UART2_TXD = _MXC_BUILD_GPIO_PIN_MX51(0, 21, 3, 0x23C, 0x62C),
+ MX51_PIN_UART3_RXD = _MXC_BUILD_GPIO_PIN_MX51(0, 22, 3, 0x240, 0x630),
+ MX51_PIN_UART3_TXD = _MXC_BUILD_GPIO_PIN_MX51(0, 23, 3, 0x244, 0x634),
+ MX51_PIN_OWIRE_LINE = _MXC_BUILD_GPIO_PIN_MX51(0, 24, 3, 0x248, 0x638),
+ MX51_PIN_KEY_ROW0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x24C, 0x63C),
+ MX51_PIN_KEY_ROW1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x250, 0x640),
+ MX51_PIN_KEY_ROW2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x254, 0x644),
+ MX51_PIN_KEY_ROW3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x258, 0x648),
+ MX51_PIN_KEY_COL0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x25C, 0x64C),
+ MX51_PIN_KEY_COL1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x260, 0x650),
+ MX51_PIN_KEY_COL2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x264, 0x654),
+ MX51_PIN_KEY_COL3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x268, 0x658),
+ MX51_PIN_KEY_COL4 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x26C, 0x65C),
+ MX51_PIN_KEY_COL5 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x270, 0x660),
+ MX51_PIN_USBH1_CLK = _MXC_BUILD_GPIO_PIN_MX51(0, 25, 2, 0x278, 0x678),
+ MX51_PIN_USBH1_DIR = _MXC_BUILD_GPIO_PIN_MX51(0, 26, 2, 0x27C, 0x67C),
+ MX51_PIN_USBH1_STP = _MXC_BUILD_GPIO_PIN_MX51(0, 27, 2, 0x280, 0x680),
+ MX51_PIN_USBH1_NXT = _MXC_BUILD_GPIO_PIN_MX51(0, 28, 2, 0x284, 0x684),
+ MX51_PIN_USBH1_DATA0 = _MXC_BUILD_GPIO_PIN_MX51(0, 11, 2, 0x288, 0x688),
+ MX51_PIN_USBH1_DATA1 = _MXC_BUILD_GPIO_PIN_MX51(0, 12, 2, 0x28C, 0x68C),
+ MX51_PIN_USBH1_DATA2 = _MXC_BUILD_GPIO_PIN_MX51(0, 13, 2, 0x290, 0x690),
+ MX51_PIN_USBH1_DATA3 = _MXC_BUILD_GPIO_PIN_MX51(0, 14, 2, 0x294, 0x694),
+ MX51_PIN_USBH1_DATA4 = _MXC_BUILD_GPIO_PIN_MX51(0, 15, 2, 0x298, 0x698),
+ MX51_PIN_USBH1_DATA5 = _MXC_BUILD_GPIO_PIN_MX51(0, 16, 2, 0x29C, 0x69C),
+ MX51_PIN_USBH1_DATA6 = _MXC_BUILD_GPIO_PIN_MX51(0, 17, 2, 0x2A0, 0x6A0),
+ MX51_PIN_USBH1_DATA7 = _MXC_BUILD_GPIO_PIN_MX51(0, 18, 2, 0x2A4, 0x6A4),
+ MX51_PIN_DI1_PIN11 = _MXC_BUILD_GPIO_PIN_MX51(2, 0, 4, 0x2A8, 0x6A8),
+ MX51_PIN_DI1_PIN12 = _MXC_BUILD_GPIO_PIN_MX51(2, 1, 4, 0x2AC, 0x6AC),
+ MX51_PIN_DI1_PIN13 = _MXC_BUILD_GPIO_PIN_MX51(2, 2, 4, 0x2B0, 0x6B0),
+ MX51_PIN_DI1_D0_CS = _MXC_BUILD_GPIO_PIN_MX51(2, 3, 4, 0x2B4, 0x6B4),
+ MX51_PIN_DI1_D1_CS = _MXC_BUILD_GPIO_PIN_MX51(2, 4, 4, 0x2B8, 0x6B8),
+ MX51_PIN_DISPB2_SER_DIN = _MXC_BUILD_GPIO_PIN_MX51(2, 5, 4, 0x2BC, 0x6BC),
+ MX51_PIN_DISPB2_SER_DIO = _MXC_BUILD_GPIO_PIN_MX51(2, 6, 4, 0x2C0, 0x6C0),
+ MX51_PIN_DISPB2_SER_CLK = _MXC_BUILD_GPIO_PIN_MX51(2, 7, 4, 0x2C4, 0x6C4),
+ MX51_PIN_DISPB2_SER_RS = _MXC_BUILD_GPIO_PIN_MX51(2, 8, 4, 0x2C8, 0x6C8),
+ MX51_PIN_DISP1_DAT0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2CC, 0x6CC),
+ MX51_PIN_DISP1_DAT1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2D0, 0x6D0),
+ MX51_PIN_DISP1_DAT2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2D4, 0x6D4),
+ MX51_PIN_DISP1_DAT3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2D8, 0x6D8),
+ MX51_PIN_DISP1_DAT4 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2DC, 0x6DC),
+ MX51_PIN_DISP1_DAT5 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2E0, 0x6E0),
+ MX51_PIN_DISP1_DAT6 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2E4, 0x6E4),
+ MX51_PIN_DISP1_DAT7 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2E8, 0x6E8),
+ MX51_PIN_DISP1_DAT8 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2EC, 0x6EC),
+ MX51_PIN_DISP1_DAT9 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2F0, 0x6F0),
+ MX51_PIN_DISP1_DAT10 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2F4, 0x6F4),
+ MX51_PIN_DISP1_DAT11 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2F8, 0x6F8),
+ MX51_PIN_DISP1_DAT12 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x2FC, 0x6FC),
+ MX51_PIN_DISP1_DAT13 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x300, 0x700),
+ MX51_PIN_DISP1_DAT14 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x304, 0x704),
+ MX51_PIN_DISP1_DAT15 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x308, 0x708),
+ MX51_PIN_DISP1_DAT16 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x30C, 0x70C),
+ MX51_PIN_DISP1_DAT17 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x310, 0x710),
+ MX51_PIN_DISP1_DAT18 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x314, 0x714),
+ MX51_PIN_DISP1_DAT19 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x318, 0x718),
+ MX51_PIN_DISP1_DAT20 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x31C, 0x71C),
+ MX51_PIN_DISP1_DAT21 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x320, 0x720),
+ MX51_PIN_DISP1_DAT22 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x324, 0x724),
+ MX51_PIN_DISP1_DAT23 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x328, 0x728),
+ MX51_PIN_DI1_PIN3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x32C, 0x72C),
+ MX51_PIN_DI1_PIN2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x330, 0x734),
+ MX51_PIN_DI_GP1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x334, 0x73C),
+ MX51_PIN_DI_GP2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x338, 0x740),
+ MX51_PIN_DI_GP3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x33C, 0x744),
+ MX51_PIN_DI2_PIN4 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x340, 0x748),
+ MX51_PIN_DI2_PIN2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x344, 0x74C),
+ MX51_PIN_DI2_PIN3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x348, 0x750),
+ MX51_PIN_DI2_DISP_CLK = _MXC_BUILD_NON_GPIO_PIN_MX51(0x34C, 0x754),
+ MX51_PIN_DI_GP4 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x350, 0x758),
+ MX51_PIN_DISP2_DAT0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x354, 0x75C),
+ MX51_PIN_DISP2_DAT1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x358, 0x760),
+ MX51_PIN_DISP2_DAT2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x35C, 0x764),
+ MX51_PIN_DISP2_DAT3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x360, 0x768),
+ MX51_PIN_DISP2_DAT4 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x364, 0x76C),
+ MX51_PIN_DISP2_DAT5 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x368, 0x770),
+ MX51_PIN_DISP2_DAT6 = _MXC_BUILD_GPIO_PIN_MX51(0, 19, 5, 0x36C, 0x774),
+ MX51_PIN_DISP2_DAT7 = _MXC_BUILD_GPIO_PIN_MX51(0, 29, 5, 0x370, 0x778),
+ MX51_PIN_DISP2_DAT8 = _MXC_BUILD_GPIO_PIN_MX51(0, 30, 5, 0x374, 0x77C),
+ MX51_PIN_DISP2_DAT9 = _MXC_BUILD_GPIO_PIN_MX51(0, 31, 5, 0x378, 0x780),
+ MX51_PIN_DISP2_DAT10 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x37C, 0x784),
+ MX51_PIN_DISP2_DAT11 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x380, 0x788),
+ MX51_PIN_DISP2_DAT12 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x384, 0x78C),
+ MX51_PIN_DISP2_DAT13 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x388, 0x790),
+ MX51_PIN_DISP2_DAT14 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x38C, 0x794),
+ MX51_PIN_DISP2_DAT15 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x390, 0x798),
+ MX51_PIN_SD1_CMD = _MXC_BUILD_NON_GPIO_PIN_MX51(0x394, 0x79C),
+ MX51_PIN_SD1_CLK = _MXC_BUILD_NON_GPIO_PIN_MX51(0x398, 0x7A0),
+ MX51_PIN_SD1_DATA0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x39C, 0x7A4),
+ MX51_PIN_SD1_DATA1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3A0, 0x7A8),
+ MX51_PIN_SD1_DATA2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3A4, 0x7AC),
+ MX51_PIN_SD1_DATA3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3A8, 0x7B0),
+ MX51_PIN_GPIO1_0 = _MXC_BUILD_GPIO_PIN_MX51(0, 0, 1, 0x3AC, 0x7B4),
+ MX51_PIN_GPIO1_1 = _MXC_BUILD_GPIO_PIN_MX51(0, 1, 1, 0x3B0, 0x7B8),
+ MX51_PIN_SD2_CMD = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3B4, 0x7BC),
+ MX51_PIN_SD2_CLK = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3B8, 0x7C0),
+ MX51_PIN_SD2_DATA0 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3BC, 0x7C4),
+ MX51_PIN_SD2_DATA1 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3C0, 0x7C8),
+ MX51_PIN_SD2_DATA2 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3C4, 0x7CC),
+ MX51_PIN_SD2_DATA3 = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3C8, 0x7D0),
+ MX51_PIN_GPIO1_2 = _MXC_BUILD_GPIO_PIN_MX51(0, 2, 0, 0x3CC, 0x7D4),
+ MX51_PIN_GPIO1_3 = _MXC_BUILD_GPIO_PIN_MX51(0, 3, 0, 0x3D0, 0x7D8),
+ MX51_PIN_PMIC_INT_REQ = _MXC_BUILD_NON_GPIO_PIN_MX51(0x3D4, 0x7FC),
+ MX51_PIN_GPIO1_4 = _MXC_BUILD_GPIO_PIN_MX51(0, 4, 0, 0x3D8, 0x804),
+ MX51_PIN_GPIO1_5 = _MXC_BUILD_GPIO_PIN_MX51(0, 5, 0, 0x3DC, 0x808),
+ MX51_PIN_GPIO1_6 = _MXC_BUILD_GPIO_PIN_MX51(0, 6, 0, 0x3E0, 0x80C),
+ MX51_PIN_GPIO1_7 = _MXC_BUILD_GPIO_PIN_MX51(0, 7, 0, 0x3E4, 0x810),
+ MX51_PIN_GPIO1_8 = _MXC_BUILD_GPIO_PIN_MX51(0, 8, 0, 0x3E8, 0x814),
+ MX51_PIN_GPIO1_9 = _MXC_BUILD_GPIO_PIN_MX51(0, 9, 0, 0x3EC, 0x818),
+};
+
+/*!
+ * various IOMUX input select register index
+ */
+enum iomux_input_select_mx51 {
+ MUX_IN_AUDMUX_P4_INPUT_DA_AMX_SELECT_I = 0,
+ MUX_IN_AUDMUX_P4_INPUT_DB_AMX_SELECT_I,
+ MUX_IN_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P5_INPUT_RXFS_AMX_SELECT,
+ MUX_IN_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P6_INPUT_DA_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P6_INPUT_DB_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P6_INPUT_RXCLK_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P6_INPUT_RXFS_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P6_INPUT_TXCLK_AMX_SELECT_INPUT,
+ MUX_IN_AUDMUX_P6_INPUT_TXFS_AMX_SELECT_INPUT,
+ MUX_IN_CCM_IPP_DI_CLK_SELECT_INPUT,
+ /* TO2 */
+ MUX_IN_CCM_IPP_DI1_CLK_SELECT_INPUT,
+ MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT,
+ MUX_IN_CCM_PLL2_BYPASS_CLK_SELECT_INPUT,
+ MUX_IN_CSPI_IPP_CSPI_CLK_IN_SELECT_INPUT,
+ MUX_IN_CSPI_IPP_IND_MISO_SELECT_INPUT,
+ MUX_IN_CSPI_IPP_IND_MOSI_SELECT_INPUT,
+ MUX_IN_CSPI_IPP_IND_SS_B_1_SELECT_INPUT,
+ MUX_IN_CSPI_IPP_IND_SS_B_2_SELECT_INPUT,
+ MUX_IN_CSPI_IPP_IND_SS_B_3_SELECT_INPUT,
+ MUX_IN_DPLLIP1_L1T_TOG_EN_SELECT_INPUT,
+ /* TO2 */
+ MUX_IN_ECSPI2_IPP_IND_SS_B_1_SELECT_INPUT,
+ MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT,
+ MUX_IN_EMI_IPP_IND_RDY_INT_SELECT_INPUT,
+ MUX_IN_ESDHC3_IPP_DAT0_IN_SELECT_INPUT,
+ MUX_IN_ESDHC3_IPP_DAT1_IN_SELECT_INPUT,
+ MUX_IN_ESDHC3_IPP_DAT2_IN_SELECT_INPUT,
+ MUX_IN_ESDHC3_IPP_DAT3_IN_SELECT_INPUT,
+ MUX_IN_FEC_FEC_COL_SELECT_INPUT,
+ MUX_IN_FEC_FEC_CRS_SELECT_INPUT,
+ MUX_IN_FEC_FEC_MDI_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RDATA_0_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RDATA_1_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RDATA_2_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RDATA_3_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RX_CLK_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RX_DV_SELECT_INPUT,
+ MUX_IN_FEC_FEC_RX_ER_SELECT_INPUT,
+ MUX_IN_FEC_FEC_TX_CLK_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_1_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_2_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_3_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_6_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_7_SELECT_INPUT,
+ MUX_IN_GPIO3_IPP_IND_G_IN_8_SELECT_INPUT,
+ /* TO2 */
+ MUX_IN_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT,
+ MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT,
+ MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT,
+ /* TO2 */
+ MUX_IN_HSC_MIPI_MIX_PAR_VSYNC_SELECT_INPUT,
+ /* TO2 */
+ MUX_IN_HSC_MIPI_MIX_PAR_DI_WAIT_SELECT_INPUT,
+ MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT,
+ MUX_IN_I2C1_IPP_SCL_IN_SELECT_INPUT,
+ MUX_IN_I2C1_IPP_SDA_IN_SELECT_INPUT,
+ MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT,
+ MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT,
+
+ MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT,
+
+ MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT,
+
+ MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT,
+ MUX_IN_KPP_IPP_IND_COL_7_SELECT_INPUT,
+ MUX_IN_KPP_IPP_IND_ROW_4_SELECT_INPUT,
+ MUX_IN_KPP_IPP_IND_ROW_5_SELECT_INPUT,
+ MUX_IN_KPP_IPP_IND_ROW_6_SELECT_INPUT,
+ MUX_IN_KPP_IPP_IND_ROW_7_SELECT_INPUT,
+ MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT,
+ MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT,
+ MUX_IN_UART2_IPP_UART_RTS_B_SELECT_INPUT,
+ MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT,
+ MUX_IN_UART3_IPP_UART_RTS_B_SELECT_INPUT,
+ MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_CLK_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_0_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_1_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_2_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_3_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_4_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_5_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_6_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DATA_7_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_DIR_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_NXT_SELECT_INPUT,
+ MUX_IN_USBOH3_IPP_IND_UH3_STP_SELECT_INPUT,
+ MUX_INPUT_NUM_MUX,
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_ARCH_MXC_MX51_PINS_H__ */
diff --git a/arch/arm/mach-mx5/mx53_ard.c b/arch/arm/mach-mx5/mx53_ard.c
new file mode 100644
index 000000000000..dd59608dd338
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_ard.c
@@ -0,0 +1,1322 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/smsc911x.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/keypad.h>
+#include <asm/mach/flash.h>
+#include <mach/memory.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/iomux-mx53.h>
+#include <mach/i2c.h>
+#include <mach/mxc_iim.h>
+
+#include "crm_regs.h"
+#include "devices.h"
+#include "usb.h"
+
+#define ARD_SD1_CD (0*32 + 1) /* GPIO_1_1 */
+#define ARD_SD2_WP (0*32 + 2) /* GPIO_1_2 */
+#define ARD_SD2_CD (0*32 + 4) /* GPIO_1_4 */
+#define ARD_VIDEOIN_INT_B (0*32 + 7) /* GPIO_1_7 */
+#define ARD_SD1_WP (0*32 + 9) /* GPIO_1_9 */
+#define ARD_PMIC_RDY (0*32 + 24) /* GPIO_1_24 */
+
+
+#define ARD_CAN1_NERR_B (1*32 + 0) /* GPIO_2_0 */
+#define ARD_CAN2_NERR_B (1*32 + 1) /* GPIO_2_1 */
+#define ARD_VIDEOIN_PWR (1*32 + 2) /* GPIO_2_2 */
+#define ARD_I2CPORTEXP_B (1*32 + 3) /* GPIO_2_3 */
+#define ARD_ESAI_INT (1*32 + 4) /* GPIO_2_4 */
+#define ARD_GPS_PWREN (1*32 + 5) /* GPIO_2_5 */
+#define ARD_GPS_INT_B (1*32 + 6) /* GPIO_2_6 */
+#define ARD_MLB_INT (1*32 + 7) /* GPIO_2_7 */
+#define ARD_ETHERNET_INT_B (1*32 + 31) /* GPIO_2_31 */
+
+#define ARD_SATE_REQ (3*32 + 0) /* GPIO_4_0 */
+#define ARD_USBH1_OC (3*32 + 1) /* GPIO_4_1 */
+#define ARD_USBH2_OC (3*32 + 2) /* GPIO_4_2 */
+#define ARD_USBH1_PWR (3*32 + 3) /* GPIO_4_3 */
+#define ARD_USER_LED (3*32 + 4) /* GPIO_4_4 */
+#define ARD_FPGA_INT_B (3*32 + 5) /* GPIO_4_5 */
+#define ARD_USBH2_PHYRST_B (3*32 + 14) /* GPIO_4_14 */
+#define ARD_CAN_STBY (3*32 + 15) /* GPIO_4_15 */
+#define ARD_PWM1_OFF (3*32 + 29) /* GPIO_4_29 */
+#define ARD_PWM2_OFF (3*32 + 30) /* GPIO_4_30 */
+
+#define ARD_USBOTG_PWR (4*32 + 2) /* GPIO_5_2 */
+#define ARD_USBOTG_OC (4*32 + 4) /* GPIO_5_4 */
+#define ARD_PMIC_INT (4*32 + 7) /* GPIO_5_7 */
+#define ARD_PMIC_PBSTAT (4*32 + 8) /* GPIO_5_8 */
+#define ARD_MLB_PWRDN (4*32 + 9) /* GPIO_5_9 */
+
+#define ARD_CAN_EN (6*32 + 6) /* GPIO_7_6 */
+#define ARD_TS_INT (6*32 + 12) /* GPIO_7_12 */
+#define ARD_SD1_LCTL (6*32 + 13) /* GPIO_7_13 */
+
+/* Start directly after the CPU's GPIO*/
+#define MAX7310_BASE_ADDR 224 /* 7x32 */
+#define ARD_BACKLIGHT_ON MAX7310_BASE_ADDR
+#define ARD_SPARE (MAX7310_BASE_ADDR + 1)
+#define ARD_CPU_PER_RST_B (MAX7310_BASE_ADDR + 2)
+#define ARD_MAIN_PER_RST_B (MAX7310_BASE_ADDR + 3)
+#define ARD_IPOD_RST_B (MAX7310_BASE_ADDR + 4)
+#define ARD_MLB_RST_B (MAX7310_BASE_ADDR + 5)
+#define ARD_SSI_STEERING (MAX7310_BASE_ADDR + 6)
+#define ARD_GPS_RST_B (MAX7310_BASE_ADDR + 7)
+
+/*!
+ * @file mach-mx53/mx53_ard.c
+ *
+ * @brief This file contains the board specific initialization routines.
+ *
+ * @ingroup MSL_MX53
+ */
+
+static struct pad_desc mx53ard_pads[] = {
+ /* UART1 */
+ MX53_PAD_ATA_DIOW__UART1_TXD,
+ MX53_PAD_ATA_DMACK__UART1_RXD,
+
+ /* UART2 */
+ MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
+ MX53_PAD_ATA_DMARQ__UART2_TXD,
+ MX53_PAD_ATA_DIOR__UART2_RTS,
+ MX53_PAD_ATA_INTRQ__UART2_CTS,
+
+ /* UART3 */
+ MX53_PAD_ATA_CS_0__UART3_TXD,
+ MX53_PAD_ATA_CS_1__UART3_RXD,
+ MX53_PAD_ATA_DA_1__UART3_CTS,
+ MX53_PAD_ATA_DA_2__UART3_RTS,
+
+ /* PMIC */
+ MX53_PAD_DISP0_DAT13__GPIO_5_7,
+ MX53_PAD_FEC_RX_ER__GPIO_1_24,
+ MX53_PAD_DISP0_DAT14__GPIO_5_8,
+
+ /* USBOTG_OC and USBOTG_PWR */
+ MX53_PAD_EIM_A24__GPIO_5_4,
+ MX53_PAD_EIM_A25__GPIO_5_2,
+
+ /* USBH */
+ MX53_PAD_GPIO_11__GPIO_4_1,
+ MX53_PAD_GPIO_12__GPIO_4_2,
+ MX53_PAD_GPIO_13__GPIO_4_3,
+ MX53_PAD_KEY_COL4__GPIO_4_14,
+
+ /* MAINBRD_SPDIF_IN */
+ MX53_PAD_KEY_COL3__SPDIF_IN1,
+
+ /* CAN */
+ MX53_PAD_KEY_COL2__TXCAN1,
+ MX53_PAD_KEY_ROW2__RXCAN1,
+ MX53_PAD_ATA_RESET_B__TXCAN2,
+ MX53_PAD_ATA_IORDY__RXCAN2,
+
+ /* CAN1, CAN2 -- EN */
+ MX53_PAD_ATA_DA_0__GPIO_7_6,
+ /* CAN1, CAN2 -- STBY */
+ MX53_PAD_KEY_ROW4__GPIO_4_15,
+ /* CAN1 -- NERR */
+ MX53_PAD_ATA_DATA0__GPIO_2_0,
+ /* CAN2 -- NERR */
+ MX53_PAD_ATA_DATA1__GPIO_2_1,
+
+ MX53_PAD_DISP0_DAT0__USBH2_DAT0,
+ MX53_PAD_DISP0_DAT1__USBH2_DAT1,
+ MX53_PAD_DISP0_DAT2__USBH2_DAT2,
+ MX53_PAD_DISP0_DAT3__USBH2_DAT3,
+ MX53_PAD_DISP0_DAT4__USBH2_DAT4,
+ MX53_PAD_DISP0_DAT5__USBH2_DAT5,
+ MX53_PAD_DISP0_DAT6__USBH2_DAT6,
+ MX53_PAD_DISP0_DAT7__USBH2_DAT7,
+ MX53_PAD_DISP0_DAT8__PWM1,
+ MX53_PAD_DISP0_DAT9__PWM2,
+ MX53_PAD_DISP0_DAT10__USBH2_STP,
+ MX53_PAD_DISP0_DAT11__USBH2_NXT,
+ MX53_PAD_DISP0_DAT12__USBH2_CLK,
+ MX53_PAD_DI0_DISP_CLK__USBH2_DIR,
+
+ MX53_PAD_LVDS0_TX3_P__LVDS0_TX3,
+ MX53_PAD_LVDS0_CLK_P__LVDS0_CLK,
+ MX53_PAD_LVDS0_TX2_P__LVDS0_TX2,
+ MX53_PAD_LVDS0_TX1_P__LVDS0_TX1,
+ MX53_PAD_LVDS0_TX0_P__LVDS0_TX0,
+
+ MX53_PAD_LVDS1_TX3_P__LVDS1_TX3,
+ MX53_PAD_LVDS1_CLK_P__LVDS1_CLK,
+ MX53_PAD_LVDS1_TX2_P__LVDS1_TX2,
+ MX53_PAD_LVDS1_TX1_P__LVDS1_TX1,
+ MX53_PAD_LVDS1_TX0_P__LVDS1_TX0,
+
+ /* Bluetooth */
+ MX53_PAD_DISP0_DAT23__AUD4_SSI_RXD,
+ MX53_PAD_DISP0_DAT21__AUD4_TXD,
+ MX53_PAD_DISP0_DAT20__AUD4_TXC,
+ MX53_PAD_DISP0_DAT22__AUD4_TXFS,
+
+ /* Video in */
+ MX53_PAD_CSI0_D4__CSI0_D4,
+ MX53_PAD_CSI0_D5__CSI0_D5,
+ MX53_PAD_CSI0_D6__CSI0_D6,
+ MX53_PAD_CSI0_D7__CSI0_D7,
+ MX53_PAD_CSI0_D8__CSI0_D8,
+ MX53_PAD_CSI0_D9__CSI0_D9,
+ MX53_PAD_CSI0_D10__CSI0_D10,
+ MX53_PAD_CSI0_D11__CSI0_D11,
+ MX53_PAD_CSI0_D12__CSI0_D12,
+ MX53_PAD_CSI0_D13__CSI0_D13,
+ MX53_PAD_CSI0_D14__CSI0_D14,
+ MX53_PAD_CSI0_D15__CSI0_D15,
+ MX53_PAD_CSI0_D16__CSI0_D16,
+ MX53_PAD_CSI0_D17__CSI0_D17,
+ MX53_PAD_CSI0_D18__CSI0_D18,
+ MX53_PAD_CSI0_D19__CSI0_D19,
+
+ MX53_PAD_CSI0_VSYNC__CSI0_VSYNC,
+ MX53_PAD_CSI0_MCLK__CSI0_HSYNC,
+ MX53_PAD_CSI0_PIXCLK__CSI0_PIXCLK,
+
+ /* VIDEO_ADC_PWRDN_B */
+ MX53_PAD_GPIO_7__GPIO_1_7,
+ MX53_PAD_ATA_DATA2__GPIO_2_2,
+
+ /* MLB */
+ MX53_PAD_FEC_TXD1__MLBCLK,
+ MX53_PAD_FEC_MDC__MLBDAT,
+ MX53_PAD_GPIO_6__MLBSIG,
+ MX53_PAD_ATA_DATA7__GPIO_2_7,
+ MX53_PAD_DISP0_DAT15__GPIO_5_9,
+
+ /* esdhc1 */
+ MX53_PAD_SD1_CMD__SD1_CMD,
+ MX53_PAD_SD1_CLK__SD1_CLK,
+ MX53_PAD_SD1_DATA0__SD1_DATA0,
+ MX53_PAD_SD1_DATA1__SD1_DATA1,
+ MX53_PAD_SD1_DATA2__SD1_DATA2,
+ MX53_PAD_SD1_DATA3__SD1_DATA3,
+ MX53_PAD_ATA_DATA8__SD1_DATA4,
+ MX53_PAD_ATA_DATA9__SD1_DATA5,
+ MX53_PAD_ATA_DATA10__SD1_DATA6,
+ MX53_PAD_ATA_DATA11__SD1_DATA7,
+ MX53_PAD_GPIO_1__GPIO_1_1,
+ MX53_PAD_GPIO_9__GPIO_1_9,
+
+ /* esdhc2 */
+ MX53_PAD_SD2_DATA0__SD2_DAT0,
+ MX53_PAD_SD2_DATA1__SD2_DAT1,
+ MX53_PAD_SD2_DATA2__SD2_DAT2,
+ MX53_PAD_SD2_DATA3__SD2_DAT3,
+ MX53_PAD_ATA_DATA12__SD2_DAT4,
+ MX53_PAD_ATA_DATA13__SD2_DAT5,
+ MX53_PAD_ATA_DATA14__SD2_DAT6,
+ MX53_PAD_ATA_DATA15__SD2_DAT7,
+ MX53_PAD_SD2_CLK__SD2_CLK,
+ MX53_PAD_SD2_CMD__SD2_CMD,
+ MX53_PAD_GPIO_4__GPIO_1_4,
+ MX53_PAD_GPIO_2__GPIO_1_2,
+
+ /* WEIM for CS1 */
+ /* ETHERNET_INT_B */
+ MX53_PAD_EIM_EB3__GPIO_2_31,
+ MX53_PAD_EIM_D16__EIM_D16,
+ MX53_PAD_EIM_D17__EIM_D17,
+ MX53_PAD_EIM_D18__EIM_D18,
+ MX53_PAD_EIM_D19__EIM_D19,
+ MX53_PAD_EIM_D20__EIM_D20,
+ MX53_PAD_EIM_D21__EIM_D21,
+ MX53_PAD_EIM_D22__EIM_D22,
+ MX53_PAD_EIM_D23__EIM_D23,
+ MX53_PAD_EIM_D24__EIM_D24,
+ MX53_PAD_EIM_D25__EIM_D25,
+ MX53_PAD_EIM_D26__EIM_D26,
+ MX53_PAD_EIM_D27__EIM_D27,
+ MX53_PAD_EIM_D28__EIM_D28,
+ MX53_PAD_EIM_D29__EIM_D29,
+ MX53_PAD_EIM_D30__EIM_D30,
+ MX53_PAD_EIM_D31__EIM_D31,
+ MX53_PAD_EIM_DA0__EIM_DA0,
+ MX53_PAD_EIM_DA1__EIM_DA1,
+ MX53_PAD_EIM_DA2__EIM_DA2,
+ MX53_PAD_EIM_DA3__EIM_DA3,
+ MX53_PAD_EIM_DA4__EIM_DA4,
+ MX53_PAD_EIM_DA5__EIM_DA5,
+ MX53_PAD_EIM_DA6__EIM_DA6,
+ MX53_PAD_EIM_OE__EIM_OE,
+ MX53_PAD_EIM_RW__EIM_RW,
+ MX53_PAD_EIM_CS1__EIM_CS1,
+
+ /* I2C2 */
+ MX53_PAD_EIM_EB2__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+
+ /* I2C3 */
+ MX53_PAD_GPIO_3__I2C3_SCL,
+ MX53_PAD_GPIO_16__I2C3_SDA,
+
+ /* TOUCH_INT_B */
+ MX53_PAD_GPIO_17__GPIO_7_12,
+
+ /* Tuner */
+ MX53_PAD_DI0_PIN15__AUD6_TXC,
+ MX53_PAD_DI0_PIN4__AUD6_RXD,
+ MX53_PAD_DI0_PIN3__AUD6_TXFS,
+
+ /* FPGA */
+ MX53_PAD_EIM_A23__EIM_A23,
+ MX53_PAD_GPIO_19__GPIO_4_5,
+
+ /* eCSPI */
+ MX53_PAD_DISP0_DAT16__ECSPI2_MOSI,
+ MX53_PAD_DISP0_DAT17__ECSPI2_MISO,
+ MX53_PAD_DISP0_DAT18__ECSPI2_SS0,
+ MX53_PAD_DISP0_DAT19__ECSPI2_SCLK,
+
+ /* NAND */
+ MX53_PAD_NANDF_CLE__NANDF_CLE,
+ MX53_PAD_NANDF_ALE__NANDF_ALE,
+ MX53_PAD_NANDF_WP_B__NANDF_WP_B,
+ MX53_PAD_NANDF_WE_B__NANDF_WE_B,
+ MX53_PAD_NANDF_RE_B__NANDF_RE_B,
+ MX53_PAD_NANDF_RB0__NANDF_RB0,
+ MX53_PAD_NANDF_CS0__NANDF_CS0,
+ MX53_PAD_NANDF_CS1__NANDF_CS1 ,
+ MX53_PAD_EIM_DA0__EIM_DA0,
+ MX53_PAD_EIM_DA1__EIM_DA1,
+ MX53_PAD_EIM_DA2__EIM_DA2,
+ MX53_PAD_EIM_DA3__EIM_DA3,
+ MX53_PAD_EIM_DA4__EIM_DA4,
+ MX53_PAD_EIM_DA5__EIM_DA5,
+ MX53_PAD_EIM_DA6__EIM_DA6,
+ MX53_PAD_EIM_DA7__EIM_DA7,
+
+ /* IO Port Expander */
+ MX53_PAD_ATA_DATA3__GPIO_2_3,
+
+ /* GPS */
+ MX53_PAD_GPIO_0__CLKO,
+ MX53_PAD_ATA_DATA5__GPIO_2_5,
+ MX53_PAD_ATA_DATA6__GPIO_2_6,
+
+ MX53_PAD_GPIO_10__GPIO_4_0,
+ MX53_PAD_GPIO_14__GPIO_4_4,
+ MX53_PAD_GPIO_18__GPIO_7_13,
+ MX53_PAD_GPIO_19__GPIO_4_5,
+
+ /* EIM_WAIT, EIM_OE ... */
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 1600x1200 @ 60 Hz 162M pixel clk*/
+ "UXGA", 60, 1600, 1200, 6172,
+ 304, 64,
+ 1, 46,
+ 192, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ /* 2 LVDS modes, had better remove from here */
+ {
+ "1080P60", 60, 1920, 1080, 7692,
+ 100, 40,
+ 30, 3,
+ 10, 2,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ "XGA", 60, 1024, 768, 15385,
+ 220, 40,
+ 21, 7,
+ 60, 10,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct pad_desc mx53_ard_pwm_pads[] = {
+ MX53_PAD_DISP0_DAT8__PWM1,
+ MX53_PAD_DISP0_DAT9__PWM2,
+ MX53_PAD_DISP0_DAT8__GPIO_4_29,
+ MX53_PAD_DISP0_DAT9__GPIO_4_30,
+};
+
+static void enable_pwm1_pad(void)
+{
+ mxc_iomux_v3_setup_pad(&mx53_ard_pwm_pads[0]);
+}
+
+static void disable_pwm1_pad(void)
+{
+ mxc_iomux_v3_setup_pad(&mx53_ard_pwm_pads[2]);
+
+ gpio_request(ARD_PWM2_OFF, "pwm2-off");
+ gpio_direction_output(ARD_PWM2_OFF, 1);
+ gpio_free(ARD_PWM2_OFF);
+}
+
+static struct mxc_pwm_platform_data mxc_pwm1_platform_data = {
+ .pwmo_invert = 1,
+ .enable_pwm_pad = enable_pwm1_pad,
+ .disable_pwm_pad = disable_pwm1_pad,
+};
+
+static struct platform_pwm_backlight_data mxc_pwm1_backlight_data = {
+ .pwm_id = 0,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 5000000,
+};
+
+static void enable_pwm2_pad(void)
+{
+ mxc_iomux_v3_setup_pad(&mx53_ard_pwm_pads[1]);
+}
+
+static void disable_pwm2_pad(void)
+{
+ mxc_iomux_v3_setup_pad(&mx53_ard_pwm_pads[3]);
+
+ gpio_request(ARD_PWM2_OFF, "pwm2-off");
+ gpio_direction_output(ARD_PWM2_OFF, 1);
+ gpio_free(ARD_PWM2_OFF);
+}
+
+static struct mxc_pwm_platform_data mxc_pwm2_platform_data = {
+ .pwmo_invert = 1,
+ .enable_pwm_pad = enable_pwm2_pad,
+ .disable_pwm_pad = disable_pwm2_pad,
+};
+
+static struct platform_pwm_backlight_data mxc_pwm2_backlight_data = {
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 5000000,
+};
+
+static void flexcan_xcvr_enable(int id, int en)
+{
+ if (id < 0 || id > 1)
+ return;
+
+ if (en)
+ gpio_set_value(ARD_CAN_EN, 1);
+ else
+ gpio_set_value(ARD_CAN_EN, 0);
+}
+
+static struct flexcan_platform_data flexcan0_data = {
+ .core_reg = NULL,
+ .io_reg = NULL,
+ .xcvr_enable = flexcan_xcvr_enable,
+ .br_clksrc = 1,
+ .br_rjw = 2,
+ .br_presdiv = 5,
+ .br_propseg = 5,
+ .br_pseg1 = 4,
+ .br_pseg2 = 7,
+ .bcc = 1,
+ .srx_dis = 1,
+ .smp = 1,
+ .boff_rec = 1,
+ .ext_msg = 1,
+ .std_msg = 1,
+};
+static struct flexcan_platform_data flexcan1_data = {
+ .core_reg = NULL,
+ .io_reg = NULL,
+ .xcvr_enable = flexcan_xcvr_enable,
+ .br_clksrc = 1,
+ .br_rjw = 2,
+ .br_presdiv = 5,
+ .br_propseg = 5,
+ .br_pseg1 = 4,
+ .br_pseg2 = 7,
+ .bcc = 1,
+ .srx_dis = 1,
+ .boff_rec = 1,
+ .ext_msg = 1,
+ .std_msg = 1,
+};
+
+
+extern void mx5_ipu_reset(void);
+static struct mxc_ipu_config mxc_ipu_data = {
+ .rev = 3,
+ .reset = mx5_ipu_reset,
+};
+
+extern void mx5_vpu_reset(void);
+static struct mxc_vpu_platform_data mxc_vpu_data = {
+ .reset = mx5_vpu_reset,
+};
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+};
+
+static struct imxi2c_platform_data mxci2c1_data = {
+ .bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mxci2c2_data = {
+ .bitrate = 400000,
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "SW1",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "SW1",
+ .lp_reg_id = "SW2",
+};
+
+static struct ldb_platform_data ldb_data = {
+ .ext_ref = 1,
+};
+
+static void mxc_iim_enable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg |= 0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static void mxc_iim_disable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg &= ~0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static struct mxc_iim_data iim_data = {
+ .bank_start = MXC_IIM_MX53_BANK_START_ADDR,
+ .bank_end = MXC_IIM_MX53_BANK_END_ADDR,
+ .enable_fuse = mxc_iim_enable_fuse,
+ .disable_fuse = mxc_iim_disable_fuse,
+};
+
+static struct pad_desc mx53_ard_esai_pads[] = {
+ MX53_PAD_FEC_MDIO__ESAI_SCKR,
+ MX53_PAD_FEC_REF_CLK__ESAI_FSR,
+ MX53_PAD_FEC_CRS_DV__ESAI_SCKT,
+ MX53_PAD_FEC_RXD1__ESAI_FST,
+ MX53_PAD_FEC_TX_EN__ESAI_TX3_RX2,
+ MX53_PAD_GPIO_5__ESAI_TX2_RX3,
+ MX53_PAD_FEC_TXD0__ESAI_TX4_RX1,
+ MX53_PAD_GPIO_8__ESAI_TX5_RX0,
+ MX53_PAD_NANDF_CS2__ESAI_TX0,
+ MX53_PAD_NANDF_CS3__ESAI_TX1,
+ MX53_PAD_ATA_DATA4__GPIO_2_4,
+};
+
+
+void ard_gpio_activate_esai_ports(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_ard_esai_pads,
+ ARRAY_SIZE(mx53_ard_esai_pads));
+ /* ESAI_INT */
+ gpio_request(ARD_ESAI_INT, "esai-int");
+ gpio_direction_input(ARD_ESAI_INT);
+
+}
+
+static struct mxc_esai_platform_data esai_data = {
+ .activate_esai_ports = ard_gpio_activate_esai_ports,
+};
+
+static void mx53_ard_usbotg_driver_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(ARD_USBOTG_PWR, 1);
+ else
+ gpio_set_value(ARD_USBOTG_PWR, 0);
+}
+
+static void mx53_ard_host1_driver_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(ARD_USBH1_PWR, 1);
+ else
+ gpio_set_value(ARD_USBH1_PWR, 0);
+}
+
+static void adv7180_pwdn(int pwdn)
+{
+ gpio_request(ARD_VIDEOIN_PWR, "tvin-pwr");
+ if (pwdn)
+ gpio_set_value(ARD_VIDEOIN_PWR, 0);
+ else
+ gpio_set_value(ARD_VIDEOIN_PWR, 1);
+ gpio_free(ARD_VIDEOIN_PWR);
+}
+
+static struct mxc_tvin_platform_data adv7180_data = {
+ .dvddio_reg = NULL,
+ .dvdd_reg = NULL,
+ .avdd_reg = NULL,
+ .pvdd_reg = NULL,
+ .pwdn = adv7180_pwdn,
+ .reset = NULL,
+ .cvbs = true,
+};
+
+static struct resource mxcfb_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "800x480M@55",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_GBR24,
+ .mode_str = "1024x768M-16@60",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+extern int primary_di;
+static int __init mxc_init_fb(void)
+{
+ if (!machine_is_mx53_ard())
+ return 0;
+
+ if (primary_di) {
+ printk(KERN_INFO "DI1 is primary\n");
+ /* DI1 -> DP-BG channel: */
+ mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[1].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+
+ /* DI0 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+ } else {
+ printk(KERN_INFO "DI0 is primary\n");
+
+ /* DI0 -> DP-BG channel: */
+ mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[0].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+
+ /* DI1 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+ }
+
+ /*
+ * DI0/1 DP-FG channel:
+ */
+ mxc_register_device(&mxc_fb_devices[2], NULL);
+
+ return 0;
+}
+device_initcall(mxc_init_fb);
+
+static struct mxc_audio_codec_platform_data cs42888_data = {
+ .analog_regulator = NULL,
+};
+
+static int mx53_ard_max7310_setup(struct i2c_client *client,
+ unsigned gpio_base, unsigned ngpio,
+ void *context)
+{
+ static int max7310_gpio_value[] = {
+ 1, 1, 1, 1, 0, 0, 0, 0,
+ };
+ int n;
+
+ for (n = 0; n < ARRAY_SIZE(max7310_gpio_value); ++n) {
+ gpio_request(gpio_base + n, "MAX7310 GPIO Expander");
+ if (max7310_gpio_value[n] < 0)
+ gpio_direction_input(gpio_base + n);
+ else
+ gpio_direction_output(gpio_base + n,
+ max7310_gpio_value[n]);
+ /* Export, direction locked down */
+ gpio_export(gpio_base + n, 0);
+ }
+
+ return 0;
+}
+
+static struct pca953x_platform_data mx53_i2c_max7310_platdata = {
+ .gpio_base = MAX7310_BASE_ADDR,
+ .invert = 0, /* Do not invert */
+ .setup = mx53_ard_max7310_setup,
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "cs42888",
+ .addr = 0x48,
+ .platform_data = &cs42888_data,
+ },
+ {
+ .type = "ipod",
+ .addr = 0x10,
+ },
+ {
+ .type = "tuner",
+ .addr = 0x62,
+ },
+};
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ .type = "max11801",
+ .addr = 0x49,
+ .irq = IOMUX_TO_IRQ_V3(ARD_TS_INT),
+ },
+ {
+ .type = "max7310",
+ .addr = 0x18,
+ .platform_data = &mx53_i2c_max7310_platdata,
+ },
+ {
+ .type = "mlb",
+ .addr = 0x20,
+ },
+ {
+ .type = "adv7180",
+ .addr = 0x21,
+ .platform_data = (void *)&adv7180_data,
+ },
+};
+
+static struct mtd_partition mxc_dataflash_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x000100000,},
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,},
+};
+
+static struct flash_platform_data mxc_spi_flash_data[] = {
+ {
+ .name = "mxc_dataflash",
+ .parts = mxc_dataflash_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_dataflash_partitions),
+ .type = "at45db321d",}
+};
+
+
+static struct spi_board_info mxc_dataflash_device[] __initdata = {
+ {
+ .modalias = "mxc_dataflash",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .platform_data = &mxc_spi_flash_data[0],},
+};
+
+static int sdhc_write_protect(struct device *dev)
+{
+ unsigned short rc = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ rc = gpio_get_value(ARD_SD1_WP);
+ else
+ rc = gpio_get_value(ARD_SD2_WP);
+
+ return rc;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret;
+ if (to_platform_device(dev)->id == 0) {
+ ret = gpio_get_value(ARD_SD1_CD);
+ } else{ /* config the det pin for SDHC2 */
+ ret = gpio_get_value(ARD_SD2_CD);
+ }
+
+ return ret;
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static struct resource ard_smsc911x_resources[] = {
+ {
+ .start = MX53_CS1_BASE_ADDR,
+ .end = MX53_CS1_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IOMUX_TO_IRQ_V3(ARD_ETHERNET_INT_B),
+ .end = IOMUX_TO_IRQ_V3(ARD_ETHERNET_INT_B),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+ .resource = ard_smsc911x_resources,
+};
+
+static struct mxc_mlb_platform_data mlb_data = {
+ .reg_nvcc = NULL,
+ .mlb_clk = "mlb_clk",
+};
+
+/* NAND Flash Partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition nand_flash_partitions[] = {
+/* MX53 ROM require the boot FCB/DBBT support which need
+ * more space to store such info on NAND boot partition.
+ * 16M should cover all kind of NAND boot support on MX53.
+ */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 16 * 1024 * 1024},
+ {
+ .name = "nand.kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 5 * 1024 * 1024},
+ {
+ .name = "nand.rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024 * 1024},
+ {
+ .name = "nand.userfs1",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024 * 1024},
+ {
+ .name = "nand.userfs2",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL},
+};
+#endif
+
+static int nand_init(void)
+{
+ u32 i, reg;
+ void __iomem *base;
+
+ #define M4IF_GENP_WEIM_MM_MASK 0x00000001
+ #define WEIM_GCR2_MUX16_BYP_GRANT_MASK 0x00001000
+
+ base = ioremap(MX53_BASE_ADDR(M4IF_BASE_ADDR), SZ_4K);
+ reg = __raw_readl(base + 0xc);
+ reg &= ~M4IF_GENP_WEIM_MM_MASK;
+ __raw_writel(reg, base + 0xc);
+
+ iounmap(base);
+
+ base = ioremap(MX53_BASE_ADDR(WEIM_BASE_ADDR), SZ_4K);
+ for (i = 0x4; i < 0x94; i += 0x18) {
+ reg = __raw_readl((u32)base + i);
+ reg &= ~WEIM_GCR2_MUX16_BYP_GRANT_MASK;
+ __raw_writel(reg, (u32)base + i);
+ }
+
+ iounmap(base);
+
+ return 0;
+}
+
+static struct flash_platform_data mxc_nand_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .parts = nand_flash_partitions,
+ .nr_parts = ARRAY_SIZE(nand_flash_partitions),
+#endif
+ .width = 1,
+ .init = nand_init,
+};
+
+static struct mxc_asrc_platform_data mxc_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2.
+};
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 0,
+ .spdif_rx = 1,
+ .spdif_clk_44100 = 0, /* Souce from CKIH1 for 44.1K */
+ .spdif_clk_48000 = 7, /* Source from CKIH2 for 48k and 32k */
+ .spdif_clkid = 0,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static struct mxc_audio_platform_data mxc_surround_audio_data = {
+ .ext_ram = 1,
+ .sysclk = 24576000,
+};
+
+
+static struct platform_device mxc_alsa_surround_device = {
+ .name = "imx-3stack-cs42888",
+};
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ struct tag *t;
+ struct tag *mem_tag = 0;
+ int total_mem = SZ_1G;
+ int left_mem = 0;
+ int gpu_mem = SZ_128M;
+ int fb_mem = SZ_32M;
+ char *str;
+
+ mxc_set_cpu_type(MXC_CPU_MX53);
+
+ for_each_tag(mem_tag, tags) {
+ if (mem_tag->hdr.tag == ATAG_MEM) {
+ total_mem = mem_tag->u.mem.size;
+ left_mem = total_mem - gpu_mem - fb_mem;
+ break;
+ }
+ }
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "mem=");
+ if (str != NULL) {
+ str += 4;
+ left_mem = memparse(str, &str);
+ if (left_mem == 0 || left_mem > total_mem)
+ left_mem = total_mem - gpu_mem - fb_mem;
+ }
+
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "gpu_memory=");
+ if (str != NULL) {
+ str += 11;
+ gpu_mem = memparse(str, &str);
+ }
+
+ break;
+ }
+ }
+
+ if (mem_tag) {
+ fb_mem = total_mem - left_mem - gpu_mem;
+ if (fb_mem < 0) {
+ gpu_mem = total_mem - left_mem;
+ fb_mem = 0;
+ }
+ mem_tag->u.mem.size = left_mem;
+
+ /*reserve memory for gpu*/
+ gpu_device.resource[5].start =
+ mem_tag->u.mem.start + left_mem;
+ gpu_device.resource[5].end =
+ gpu_device.resource[5].start + gpu_mem - 1;
+#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \
+ defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
+ if (fb_mem) {
+ mxcfb_resources[0].start =
+ gpu_device.resource[5].end + 1;
+ mxcfb_resources[0].end =
+ mxcfb_resources[0].start + fb_mem - 1;
+ } else {
+ mxcfb_resources[0].start = 0;
+ mxcfb_resources[0].end = 0;
+ }
+#endif
+ }
+}
+
+static void __init mx53_ard_io_init(void)
+{
+ /* MX53 ARD board */
+ pr_info("MX53 ARD board \n");
+ mxc_iomux_v3_setup_multiple_pads(mx53ard_pads,
+ ARRAY_SIZE(mx53ard_pads));
+
+ /* USBOTG_OC */
+ gpio_request(ARD_USBOTG_OC, "otg-oc");
+ gpio_direction_input(ARD_USBOTG_OC);
+ /* USBOTG_PWR */
+ gpio_request(ARD_USBOTG_PWR, "otg-pwr");
+ gpio_direction_output(ARD_USBOTG_PWR, 1);
+
+ gpio_request(ARD_USBH1_OC, "usbh1-oc");
+ gpio_direction_input(ARD_USBH1_OC);
+
+ gpio_request(ARD_USBH2_OC, "usbh2-oc");
+ gpio_direction_input(ARD_USBH2_OC);
+
+ gpio_request(ARD_USBH1_PWR, "usbh1-pwr");
+ gpio_direction_output(ARD_USBH1_PWR, 1);
+
+ gpio_request(ARD_USBH2_PHYRST_B, "usbh2-phyrst");
+ gpio_direction_output(ARD_USBH2_PHYRST_B, 1);
+
+ gpio_request(ARD_SD1_CD, "sdhc1-cd");
+ gpio_direction_input(ARD_SD1_CD); /* SD1 CD */
+ gpio_request(ARD_SD1_WP, "sdhc1-wp");
+ gpio_direction_input(ARD_SD1_WP); /* SD1 WP */
+
+ /* SD2 CD */
+ gpio_request(ARD_SD2_CD, "sdhc2-cd");
+ gpio_direction_input(ARD_SD2_CD);
+
+ /* SD2 WP */
+ gpio_request(ARD_SD2_WP, "sdhc2-wp");
+ gpio_direction_input(ARD_SD2_WP);
+
+ gpio_request(ARD_PMIC_INT, "pmic-int");
+ gpio_direction_input(ARD_PMIC_INT); /*PMIC_INT*/
+ gpio_request(ARD_PMIC_RDY, "pmic-rdy");
+ gpio_direction_input(ARD_PMIC_RDY); /*PMIC_RDY*/
+ gpio_request(ARD_PMIC_PBSTAT, "pmic-pbstat");
+ gpio_direction_input(ARD_PMIC_PBSTAT); /*PMIC_PBSTAT*/
+
+ /* CAN1 enable GPIO*/
+ gpio_request(ARD_CAN_EN, "can-en");
+ gpio_direction_output(ARD_CAN_EN, 0);
+
+ gpio_request(ARD_CAN_STBY, "can-stby");
+ gpio_direction_output(ARD_CAN_STBY, 0);
+
+ gpio_request(ARD_CAN1_NERR_B, "can1-nerr");
+ gpio_direction_input(ARD_CAN1_NERR_B);
+
+ gpio_request(ARD_CAN2_NERR_B, "can2-nerr");
+ gpio_direction_input(ARD_CAN2_NERR_B);
+
+ gpio_request(ARD_VIDEOIN_PWR, "videoin-pwr");
+ gpio_direction_output(ARD_VIDEOIN_PWR, 0);
+
+ gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+ gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+
+ gpio_request(ARD_GPS_PWREN, "gps-pwren");
+ gpio_direction_output(ARD_GPS_PWREN, 1);
+
+ gpio_request(ARD_GPS_INT_B, "gps-int");
+ gpio_direction_input(ARD_GPS_INT_B);
+
+ gpio_request(ARD_MLB_INT, "mlb-int");
+ gpio_direction_input(ARD_MLB_INT);
+
+ gpio_request(ARD_MLB_PWRDN, "mlb-pwrdn");
+ gpio_direction_input(ARD_MLB_PWRDN);
+
+ gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+ gpio_direction_input(ARD_ETHERNET_INT_B);
+
+ gpio_request(ARD_FPGA_INT_B, "fpga-int");
+ gpio_direction_input(ARD_FPGA_INT_B);
+
+ gpio_request(ARD_TS_INT, "ts-int");
+ gpio_direction_input(ARD_TS_INT);
+ gpio_free(ARD_TS_INT);
+}
+
+/* Config CS1 settings for ethernet controller */
+static void weim_cs_config(void)
+{
+ u32 reg;
+ void __iomem *weim_base, *iomuxc_base;
+
+ weim_base = ioremap(MX53_BASE_ADDR(WEIM_BASE_ADDR), SZ_4K);
+ iomuxc_base = ioremap(MX53_BASE_ADDR(IOMUXC_BASE_ADDR), SZ_4K);
+
+ /* CS1 timings for LAN9220 */
+ writel(0x20001, (weim_base + 0x18));
+ writel(0x0, (weim_base + 0x1C));
+ writel(0x16000202, (weim_base + 0x20));
+ writel(0x00000002, (weim_base + 0x24));
+ writel(0x16002082, (weim_base + 0x28));
+ writel(0x00000000, (weim_base + 0x2C));
+ writel(0x00000000, (weim_base + 0x90));
+
+ /* specify 64 MB on CS1 and CS0 on GPR1 */
+ reg = readl(iomuxc_base + 0x4);
+ reg &= ~0x3F;
+ reg |= 0x1B;
+ writel(reg, (iomuxc_base + 0x4));
+
+ iounmap(iomuxc_base);
+ iounmap(weim_base);
+}
+
+static int mxc_read_mac_iim(void)
+{
+ struct clk *iim_clk;
+ void __iomem *iim_base = IO_ADDRESS(IIM_BASE_ADDR);
+ void __iomem *iim_mac_base = iim_base + \
+ MXC_IIM_MX53_BANK_AREA_1_OFFSET + \
+ MXC_IIM_MX53_MAC_ADDR_OFFSET;
+ int i;
+
+ iim_clk = clk_get(NULL, "iim_clk");
+
+ if (!iim_clk) {
+ printk(KERN_ERR "Could not get IIM clk to read MAC fuses!\n");
+ return ~EINVAL;
+ }
+
+ clk_enable(iim_clk);
+
+ for (i = 0; i < 6; i++)
+ ard_smsc911x_config.mac[i] = readl(iim_mac_base + (i*4));
+
+ clk_disable(iim_clk);
+ return 0;
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ mxc_ipu_data.di_clk[0] = clk_get(NULL, "ipu_di0_clk");
+ mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk");
+ mxc_ipu_data.csi_clk[0] = clk_get(NULL, "ssi_ext1_clk");
+ mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk");
+ clk_put(mxc_spdif_data.spdif_core_clk);
+
+ mxcsdhc2_device.resource[2].start = IOMUX_TO_IRQ_V3(ARD_SD2_CD);
+ mxcsdhc2_device.resource[2].end = IOMUX_TO_IRQ_V3(ARD_SD2_CD);
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(ARD_SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(ARD_SD1_CD);
+
+ mxc_cpu_common_init();
+
+ mx53_ard_io_init();
+ weim_cs_config();
+ mxc_read_mac_iim();
+ mxc_register_device(&ard_smsc_lan9220_device, &ard_smsc911x_config);
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c1_data);
+ mxc_register_device(&mxci2c_devices[2], &mxci2c2_data);
+
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
+ mxc_register_device(&mxc_ldb_device, &ldb_data);
+ mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
+ mxc_register_device(&gpu_device, &z160_revision);
+ mxc_register_device(&mxcscc_device, NULL);
+
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+
+ mxc_register_device(&mxc_iim_device, &iim_data);
+
+ mxc_register_device(&mxc_pwm1_device, &mxc_pwm1_platform_data);
+ mxc_register_device(&mxc_pwm1_backlight_device,
+ &mxc_pwm1_backlight_data);
+
+ mxc_register_device(&mxc_pwm2_device, &mxc_pwm2_platform_data);
+ mxc_register_device(&mxc_pwm2_backlight_device,
+ &mxc_pwm2_backlight_data);
+
+ mxc_register_device(&mxc_flexcan0_device, &flexcan0_data);
+ mxc_register_device(&mxc_flexcan1_device, &flexcan1_data);
+
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc2_device, &mmc2_data);
+
+ mxc_register_device(&ahci_fsl_device, &sata_data);
+
+ /* ASRC is only available for MX53 TO2.0 */
+ if (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1) {
+ mxc_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ clk_put(mxc_asrc_data.asrc_core_clk);
+ mxc_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ clk_put(mxc_asrc_data.asrc_audio_clk);
+ mxc_register_device(&mxc_asrc_device, &mxc_asrc_data);
+ }
+
+ mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
+
+ spi_register_board_info(mxc_dataflash_device,
+ ARRAY_SIZE(mxc_dataflash_device));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+ mxc_register_device(&mxc_mlb_device, &mlb_data);
+ mx5_set_otghost_vbus_func(mx53_ard_usbotg_driver_vbus);
+ mx5_usb_dr_init();
+ mx5_set_host1_vbus_func(mx53_ard_host1_driver_vbus);
+ mx5_usbh1_init();
+ mx5_usbh2_init();
+ mxc_register_device(&mxc_nandv2_mtd_device, &mxc_nand_data);
+ mxc_register_device(&mxc_esai_device, &esai_data);
+ mxc_register_device(&mxc_alsa_surround_device,
+ &mxc_surround_audio_data);
+
+ mxc_register_device(&mxc_v4l2out_device, NULL);
+ mxc_register_device(&mxc_v4l2_device, NULL);
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx53_clocks_init(32768, 24000000, 22579200, 24576000);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(MX53_BASE_ADDR(UART1_BASE_ADDR), uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx53_ard_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX53_ARD data structure.
+ */
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx53_ard_pmic_ltc3589.c b/arch/arm/mach-mx5/mx53_ard_pmic_ltc3589.c
new file mode 100644
index 000000000000..02538815d2a4
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_ard_pmic_ltc3589.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*
+ * mx53_ard_pmic_ltc3589.c -- i.MX53 ARD Driver for Linear LTC3589
+ * PMIC
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/ltc3589.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/ltc3589/core.h>
+#include <mach/iomux-mx53.h>
+#include <mach/irqs.h>
+
+#define ARD_PMIC_INT (4*32 + 7) /* GPIO_5_7 */
+
+/* CPU */
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+struct ltc3589;
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = 564000,
+ .max_uV = 1167000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = 704000,
+ .max_uV = 1456000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = 1342000,
+ .max_uV = 2775000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .apply_uV = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data ldo1_init = {
+ .constraints = {
+ .name = "LDO1_STBY",
+ .apply_uV = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data ldo2_init = {
+ .constraints = {
+ .name = "LDO2",
+ .min_uV = 704000,
+ .max_uV = 1456000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data ldo3_init = {
+ .constraints = {
+ .name = "LDO3",
+ .apply_uV = 1,
+ .boot_on = 1,
+ },
+};
+
+static struct regulator_init_data ldo4_init = {
+ .constraints = {
+ .name = "LDO4",
+ .min_uV = 1800000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .always_on = 1,
+ .boot_on = 1,
+ },
+};
+
+static void ltc3589_nop_release(struct device *dev)
+{
+ /* Nothing */
+}
+
+static struct platform_device ltc3589_regulator_device[] = {
+ {
+ .name = "ltc3589-dev",
+ .id = 0,
+ .dev = {
+ .release = ltc3589_nop_release,
+ },
+ },
+};
+
+static int mx53_ltc3589_init(struct ltc3589 *ltc3589)
+{
+ int i;
+
+ printk(KERN_INFO "Initializing regulators for ARD\n");
+ for (i = 0; i < ARRAY_SIZE(ltc3589_regulator_device); i++) {
+ if (platform_device_register(&ltc3589_regulator_device[i]) < 0)
+ dev_err(&ltc3589_regulator_device[i].dev,
+ "Unable to register LTC3589 device\n");
+ }
+
+ ltc3589_register_regulator(ltc3589, LTC3589_SW1, &sw1_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_SW2, &sw2_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_SW3, &sw3_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_SW4, &sw4_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_LDO1, &ldo1_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_LDO2, &ldo2_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_LDO3, &ldo3_init);
+ ltc3589_register_regulator(ltc3589, LTC3589_LDO4, &ldo4_init);
+
+ return 0;
+}
+
+static struct ltc3589_platform_data __initdata ltc3589_plat = {
+ .init = mx53_ltc3589_init,
+};
+
+static struct i2c_board_info __initdata ltc3589_i2c_device = {
+ I2C_BOARD_INFO("ltc3589", 0x34),
+ .irq = IOMUX_TO_IRQ_V3(ARD_PMIC_INT),
+ .platform_data = &ltc3589_plat,
+};
+
+static __init int mx53_init_i2c(void)
+{
+ return i2c_register_board_info(1, &ltc3589_i2c_device, 1);
+}
+
+subsys_initcall(mx53_init_i2c);
+
+static __init int ltc3589_pmic_init(void)
+{
+ int i = 0;
+ int ret = 0;
+ struct regulator *regulator;
+
+ char *ltc3589_global_regulator[] = {
+ "SW1",
+ "SW2",
+ "SW3",
+ "SW4",
+ "LDO1_STBY",
+ "LDO2",
+ "LDO3",
+ "LDO4",
+ };
+
+ while ((i < ARRAY_SIZE(ltc3589_global_regulator)) &&
+ !IS_ERR_VALUE(
+ (unsigned long)(regulator =
+ regulator_get(NULL,
+ ltc3589_global_regulator
+ [i])))) {
+ regulator_enable(regulator);
+ i++;
+ }
+
+ return ret;
+}
+
+late_initcall(ltc3589_pmic_init);
+
diff --git a/arch/arm/mach-mx5/mx53_evk.c b/arch/arm/mach-mx5/mx53_evk.c
new file mode 100644
index 000000000000..092aec5498d0
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_evk.c
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/powerkey.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/keypad.h>
+#include <asm/mach/flash.h>
+#include <mach/memory.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/iomux-mx53.h>
+#include <mach/i2c.h>
+#include <mach/mxc_iim.h>
+
+#include "crm_regs.h"
+#include "devices.h"
+#include "usb.h"
+
+#define ARM2_SD1_CD (0*32 + 1) /* GPIO_1_1 */
+
+#define MX53_HP_DETECT (1*32 + 5) /* GPIO_2_5 */
+
+#define EVK_SD3_CD (2*32 + 11) /* GPIO_3_11 */
+#define EVK_SD3_WP (2*32 + 12) /* GPIO_3_12 */
+#define EVK_SD1_CD (2*32 + 13) /* GPIO_3_13 */
+#define EVK_SD1_WP (2*32 + 14) /* GPIO_3_14 */
+#define ARM2_OTG_VBUS (2*32 + 22) /* GPIO_3_22 */
+#define MX53_DVI_PD (2*32 + 24) /* GPIO_3_24 */
+#define EVK_TS_INT (2*32 + 26) /* GPIO_3_26 */
+#define MX53_DVI_I2C (2*32 + 28) /* GPIO_3_28 */
+#define MX53_DVI_DETECT (2*32 + 31) /* GPIO_3_31 */
+
+#define MX53_CAM_RESET (3*32 + 0) /* GPIO_4_0 */
+#define MX53_ESAI_RESET (3*32 + 2) /* GPIO_4_2 */
+#define MX53_CAN2_EN2 (3*32 + 4) /* GPIO_4_4 */
+#define MX53_12V_EN (3*32 + 5) /* GPIO_4_5 */
+#define ARM2_LCD_CONTRAST (3*32 + 20) /* GPIO_4_20 */
+
+#define MX53_DVI_RESET (4*32 + 0) /* GPIO_5_0 */
+#define EVK_USB_HUB_RESET (4*32 + 20) /* GPIO_5_20 */
+#define MX53_TVIN_PWR (4*32 + 23) /* GPIO_5_23 */
+#define MX53_CAN2_EN1 (4*32 + 24) /* GPIO_5_24 */
+#define MX53_TVIN_RESET (4*32 + 25) /* GPIO_5_25 */
+
+#define EVK_OTG_VBUS (5*32 + 6) /* GPIO_6_6 */
+
+#define EVK_FEC_PHY_RESET (6*32 + 6) /* GPIO_7_6 */
+#define EVK_USBH1_VBUS (6*32 + 8) /* GPIO_7_8 */
+#define MX53_PMIC_INT (6*32 + 11) /* GPIO_7_11 */
+#define MX53_CAN1_EN1 (6*32 + 12) /* GPIO_7_12 */
+#define MX53_CAN1_EN2 (6*32 + 13) /* GPIO_7_13 */
+
+/*!
+ * @file mach-mx53/mx53_evk.c
+ *
+ * @brief This file contains the board specific initialization routines.
+ *
+ * @ingroup MSL_MX53
+ */
+extern int __init mx53_evk_init_mc13892(void);
+
+static struct pad_desc mx53common_pads[] = {
+ MX53_PAD_EIM_WAIT__GPIO_5_0,
+
+ MX53_PAD_EIM_OE__DI1_PIN7,
+ MX53_PAD_EIM_RW__DI1_PIN8,
+
+ MX53_PAD_EIM_A25__DI0_D1_CS,
+
+ MX53_PAD_EIM_D16__CSPI1_SCLK,
+ MX53_PAD_EIM_D17__CSPI1_MISO,
+ MX53_PAD_EIM_D18__CSPI1_MOSI,
+
+ MX53_PAD_EIM_D20__SER_DISP0_CS,
+
+ MX53_PAD_EIM_D23__DI0_D0_CS,
+
+ MX53_PAD_EIM_D24__GPIO_3_24,
+ MX53_PAD_EIM_D26__GPIO_3_26,
+
+ MX53_PAD_EIM_D29__DISPB0_SER_RS,
+
+ MX53_PAD_EIM_D30__DI0_PIN11,
+ MX53_PAD_EIM_D31__DI0_PIN12,
+
+ MX53_PAD_ATA_DA_1__GPIO_7_7,
+ MX53_PAD_ATA_DATA4__GPIO_2_4,
+ MX53_PAD_ATA_DATA5__GPIO_2_5,
+ MX53_PAD_ATA_DATA6__GPIO_2_6,
+
+ MX53_PAD_SD2_CLK__SD2_CLK,
+ MX53_PAD_SD2_CMD__SD2_CMD,
+ MX53_PAD_SD2_DATA0__SD2_DAT0,
+ MX53_PAD_SD2_DATA1__SD2_DAT1,
+ MX53_PAD_SD2_DATA2__SD2_DAT2,
+ MX53_PAD_SD2_DATA3__SD2_DAT3,
+ MX53_PAD_ATA_DATA12__SD2_DAT4,
+ MX53_PAD_ATA_DATA13__SD2_DAT5,
+ MX53_PAD_ATA_DATA14__SD2_DAT6,
+ MX53_PAD_ATA_DATA15__SD2_DAT7,
+
+ MX53_PAD_CSI0_D10__UART1_TXD,
+ MX53_PAD_CSI0_D11__UART1_RXD,
+
+ MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
+ MX53_PAD_ATA_DMARQ__UART2_TXD,
+ MX53_PAD_ATA_DIOR__UART2_RTS,
+ MX53_PAD_ATA_INTRQ__UART2_CTS,
+
+ MX53_PAD_ATA_CS_0__UART3_TXD,
+ MX53_PAD_ATA_CS_1__UART3_RXD,
+
+ MX53_PAD_KEY_COL0__AUD5_TXC,
+ MX53_PAD_KEY_ROW0__AUD5_TXD,
+ MX53_PAD_KEY_COL1__AUD5_TXFS,
+ MX53_PAD_KEY_ROW1__AUD5_RXD,
+
+ MX53_PAD_CSI0_D7__GPIO_5_25,
+
+ MX53_PAD_GPIO_2__MLBDAT,
+ MX53_PAD_GPIO_3__MLBCLK,
+
+ MX53_PAD_GPIO_6__MLBSIG,
+
+ MX53_PAD_GPIO_4__GPIO_1_4,
+ MX53_PAD_GPIO_7__GPIO_1_7,
+ MX53_PAD_GPIO_8__GPIO_1_8,
+
+ MX53_PAD_GPIO_10__GPIO_4_0,
+
+ MX53_PAD_KEY_COL2__TXCAN1,
+ MX53_PAD_KEY_ROW2__RXCAN1,
+
+ /* CAN1 -- EN */
+ MX53_PAD_GPIO_18__GPIO_7_13,
+ /* CAN1 -- STBY */
+ MX53_PAD_GPIO_17__GPIO_7_12,
+ /* CAN1 -- NERR */
+ MX53_PAD_GPIO_5__GPIO_1_5,
+
+ MX53_PAD_KEY_COL4__TXCAN2,
+ MX53_PAD_KEY_ROW4__RXCAN2,
+
+ /* CAN2 -- EN */
+ MX53_PAD_CSI0_D6__GPIO_5_24,
+ /* CAN2 -- STBY */
+ MX53_PAD_GPIO_14__GPIO_4_4,
+ /* CAN2 -- NERR */
+ MX53_PAD_CSI0_D4__GPIO_5_22,
+
+ MX53_PAD_GPIO_11__GPIO_4_1,
+ MX53_PAD_GPIO_12__GPIO_4_2,
+ MX53_PAD_GPIO_13__GPIO_4_3,
+ MX53_PAD_GPIO_16__GPIO_7_11,
+ MX53_PAD_GPIO_19__GPIO_4_5,
+
+ /* DI0 display clock */
+ MX53_PAD_DI0_DISP_CLK__DI0_DISP_CLK,
+
+ /* DI0 data enable */
+ MX53_PAD_DI0_PIN15__DI0_PIN15,
+ /* DI0 HSYNC */
+ MX53_PAD_DI0_PIN2__DI0_PIN2,
+ /* DI0 VSYNC */
+ MX53_PAD_DI0_PIN3__DI0_PIN3,
+
+ MX53_PAD_DISP0_DAT0__DISP0_DAT0,
+ MX53_PAD_DISP0_DAT1__DISP0_DAT1,
+ MX53_PAD_DISP0_DAT2__DISP0_DAT2,
+ MX53_PAD_DISP0_DAT3__DISP0_DAT3,
+ MX53_PAD_DISP0_DAT4__DISP0_DAT4,
+ MX53_PAD_DISP0_DAT5__DISP0_DAT5,
+ MX53_PAD_DISP0_DAT6__DISP0_DAT6,
+ MX53_PAD_DISP0_DAT7__DISP0_DAT7,
+ MX53_PAD_DISP0_DAT8__DISP0_DAT8,
+ MX53_PAD_DISP0_DAT9__DISP0_DAT9,
+ MX53_PAD_DISP0_DAT10__DISP0_DAT10,
+ MX53_PAD_DISP0_DAT11__DISP0_DAT11,
+ MX53_PAD_DISP0_DAT12__DISP0_DAT12,
+ MX53_PAD_DISP0_DAT13__DISP0_DAT13,
+ MX53_PAD_DISP0_DAT14__DISP0_DAT14,
+ MX53_PAD_DISP0_DAT15__DISP0_DAT15,
+ MX53_PAD_DISP0_DAT16__DISP0_DAT16,
+ MX53_PAD_DISP0_DAT17__DISP0_DAT17,
+ MX53_PAD_DISP0_DAT18__DISP0_DAT18,
+ MX53_PAD_DISP0_DAT19__DISP0_DAT19,
+ MX53_PAD_DISP0_DAT20__DISP0_DAT20,
+ MX53_PAD_DISP0_DAT21__DISP0_DAT21,
+ MX53_PAD_DISP0_DAT22__DISP0_DAT22,
+ MX53_PAD_DISP0_DAT23__DISP0_DAT23,
+
+ MX53_PAD_LVDS0_TX3_P__LVDS0_TX3,
+ MX53_PAD_LVDS0_CLK_P__LVDS0_CLK,
+ MX53_PAD_LVDS0_TX2_P__LVDS0_TX2,
+ MX53_PAD_LVDS0_TX1_P__LVDS0_TX1,
+ MX53_PAD_LVDS0_TX0_P__LVDS0_TX0,
+
+ MX53_PAD_LVDS1_TX3_P__LVDS1_TX3,
+ MX53_PAD_LVDS1_CLK_P__LVDS1_CLK,
+ MX53_PAD_LVDS1_TX2_P__LVDS1_TX2,
+ MX53_PAD_LVDS1_TX1_P__LVDS1_TX1,
+ MX53_PAD_LVDS1_TX0_P__LVDS1_TX0,
+
+ /* audio and CSI clock out */
+ MX53_PAD_GPIO_0__SSI_EXT1_CLK,
+
+ MX53_PAD_CSI0_D12__CSI0_D12,
+ MX53_PAD_CSI0_D13__CSI0_D13,
+ MX53_PAD_CSI0_D14__CSI0_D14,
+ MX53_PAD_CSI0_D15__CSI0_D15,
+ MX53_PAD_CSI0_D16__CSI0_D16,
+ MX53_PAD_CSI0_D17__CSI0_D17,
+ MX53_PAD_CSI0_D18__CSI0_D18,
+ MX53_PAD_CSI0_D19__CSI0_D19,
+
+ MX53_PAD_CSI0_VSYNC__CSI0_VSYNC,
+ MX53_PAD_CSI0_MCLK__CSI0_HSYNC,
+ MX53_PAD_CSI0_PIXCLK__CSI0_PIXCLK,
+ /* Camera low power */
+ MX53_PAD_CSI0_D5__GPIO_5_23,
+
+ /* esdhc1 */
+ MX53_PAD_SD1_CMD__SD1_CMD,
+ MX53_PAD_SD1_CLK__SD1_CLK,
+ MX53_PAD_SD1_DATA0__SD1_DATA0,
+ MX53_PAD_SD1_DATA1__SD1_DATA1,
+ MX53_PAD_SD1_DATA2__SD1_DATA2,
+ MX53_PAD_SD1_DATA3__SD1_DATA3,
+
+ /* esdhc3 */
+ MX53_PAD_ATA_DATA8__SD3_DAT0,
+ MX53_PAD_ATA_DATA9__SD3_DAT1,
+ MX53_PAD_ATA_DATA10__SD3_DAT2,
+ MX53_PAD_ATA_DATA11__SD3_DAT3,
+ MX53_PAD_ATA_DATA0__SD3_DAT4,
+ MX53_PAD_ATA_DATA1__SD3_DAT5,
+ MX53_PAD_ATA_DATA2__SD3_DAT6,
+ MX53_PAD_ATA_DATA3__SD3_DAT7,
+ MX53_PAD_ATA_RESET_B__SD3_CMD,
+ MX53_PAD_ATA_IORDY__SD3_CLK,
+
+ /* FEC pins */
+ MX53_PAD_FEC_MDIO__FEC_MDIO,
+ MX53_PAD_FEC_REF_CLK__FEC_REF_CLK,
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+ MX53_PAD_FEC_CRS_DV__FEC_CRS_DV,
+ MX53_PAD_FEC_RXD1__FEC_RXD1,
+ MX53_PAD_FEC_RXD0__FEC_RXD0,
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+ MX53_PAD_FEC_TXD1__FEC_TXD1,
+ MX53_PAD_FEC_TXD0__FEC_TXD0,
+ MX53_PAD_FEC_MDC__FEC_MDC,
+
+ MX53_PAD_CSI0_D8__I2C1_SDA,
+ MX53_PAD_CSI0_D9__I2C1_SCL,
+
+ MX53_PAD_KEY_COL3__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+};
+
+static struct pad_desc mx53evk_pads[] = {
+ /* USB OTG USB_OC */
+ MX53_PAD_EIM_A24__GPIO_5_4,
+
+ /* USB OTG USB_PWR */
+ MX53_PAD_EIM_A23__GPIO_6_6,
+
+ /* DISPB0_SER_CLK */
+ MX53_PAD_EIM_D21__DISPB0_SER_CLK,
+
+ /* DI0_PIN1 */
+ MX53_PAD_EIM_D22__DISPB0_SER_DIN,
+
+ /* DVI I2C ENABLE */
+ MX53_PAD_EIM_D28__GPIO_3_28,
+
+ /* DVI DET */
+ MX53_PAD_EIM_D31__GPIO_3_31,
+
+ /* SDHC1 SD_CD */
+ MX53_PAD_EIM_DA13__GPIO_3_13,
+
+ /* SDHC1 SD_WP */
+ MX53_PAD_EIM_DA14__GPIO_3_14,
+
+ /* SDHC3 SD_CD */
+ MX53_PAD_EIM_DA11__GPIO_3_11,
+
+ /* SDHC3 SD_WP */
+ MX53_PAD_EIM_DA12__GPIO_3_12,
+
+ /* PWM backlight */
+ MX53_PAD_GPIO_1__PWMO,
+
+ /* USB HOST USB_PWR */
+ MX53_PAD_ATA_DA_2__GPIO_7_8,
+
+ /* USB HOST USB_RST */
+ MX53_PAD_CSI0_DATA_EN__GPIO_5_20,
+
+ /* USB HOST CARD_ON */
+ MX53_PAD_EIM_DA15__GPIO_3_15,
+
+ /* USB HOST CARD_RST */
+ MX53_PAD_ATA_DATA7__GPIO_2_7,
+
+ /* USB HOST WAN_WAKE */
+ MX53_PAD_EIM_D25__GPIO_3_25,
+
+ /* FEC_RST */
+ MX53_PAD_ATA_DA_0__GPIO_7_6,
+};
+
+static struct pad_desc mx53arm2_pads[] = {
+ /* USB OTG USB_OC */
+ MX53_PAD_EIM_D21__GPIO_3_21,
+
+ /* USB OTG USB_PWR */
+ MX53_PAD_EIM_D22__GPIO_3_22,
+
+ /* SDHC1 SD_CD */
+ MX53_PAD_GPIO_1__GPIO_1_1,
+
+ /* gpio backlight */
+ MX53_PAD_DI0_PIN4__GPIO_4_20,
+};
+
+static struct pad_desc mx53_nand_pads[] = {
+ MX53_PAD_NANDF_CLE__NANDF_CLE,
+ MX53_PAD_NANDF_ALE__NANDF_ALE,
+ MX53_PAD_NANDF_WP_B__NANDF_WP_B,
+ MX53_PAD_NANDF_WE_B__NANDF_WE_B,
+ MX53_PAD_NANDF_RE_B__NANDF_RE_B,
+ MX53_PAD_NANDF_RB0__NANDF_RB0,
+ MX53_PAD_NANDF_CS0__NANDF_CS0,
+ MX53_PAD_NANDF_CS1__NANDF_CS1 ,
+ MX53_PAD_NANDF_CS2__NANDF_CS2,
+ MX53_PAD_NANDF_CS3__NANDF_CS3 ,
+ MX53_PAD_EIM_DA0__EIM_DA0,
+ MX53_PAD_EIM_DA1__EIM_DA1,
+ MX53_PAD_EIM_DA2__EIM_DA2,
+ MX53_PAD_EIM_DA3__EIM_DA3,
+ MX53_PAD_EIM_DA4__EIM_DA4,
+ MX53_PAD_EIM_DA5__EIM_DA5,
+ MX53_PAD_EIM_DA6__EIM_DA6,
+ MX53_PAD_EIM_DA7__EIM_DA7,
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 1600x1200 @ 60 Hz 162M pixel clk*/
+ "UXGA", 60, 1600, 1200, 6172,
+ 304, 64,
+ 1, 46,
+ 192, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ /* 2 LVDS modes, had better remove from here */
+ {
+ "1080P60", 60, 1920, 1080, 7692,
+ 100, 40,
+ 30, 3,
+ 10, 2,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ "XGA", 60, 1024, 768, 15385,
+ 220, 40,
+ 21, 7,
+ 60, 10,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_w1_config mxc_w1_data = {
+ .search_rom_accelerator = 1,
+};
+
+static struct platform_pwm_backlight_data mxc_pwm_backlight_data = {
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+static void flexcan_xcvr_enable(int id, int en)
+{
+ static int pwdn;
+ if (id < 0 || id > 1)
+ return;
+
+ if (en) {
+ if (!(pwdn++))
+ gpio_set_value(MX53_12V_EN, 1);
+
+ if (id == 0) {
+ gpio_set_value(MX53_CAN1_EN1, 1);
+ gpio_set_value(MX53_CAN1_EN2, 1);
+ } else {
+ gpio_set_value(MX53_CAN2_EN1, 1);
+ gpio_set_value(MX53_CAN2_EN2, 1);
+ }
+
+ } else {
+ if (!(--pwdn))
+ gpio_set_value(MX53_12V_EN, 0);
+
+ if (id == 0) {
+ gpio_set_value(MX53_CAN1_EN1, 0);
+ gpio_set_value(MX53_CAN1_EN2, 0);
+ } else {
+ gpio_set_value(MX53_CAN2_EN1, 0);
+ gpio_set_value(MX53_CAN2_EN2, 0);
+ }
+ }
+}
+
+static struct flexcan_platform_data flexcan0_data = {
+ .core_reg = NULL,
+ .io_reg = NULL,
+ .root_clk_id = "lp_apm", /*lp_apm is 24MHz */
+ .xcvr_enable = flexcan_xcvr_enable,
+ .br_clksrc = 0,
+ .br_rjw = 2,
+ .br_presdiv = 3,
+ .br_propseg = 2,
+ .br_pseg1 = 3,
+ .br_pseg2 = 3,
+ .bcc = 1,
+ .srx_dis = 1,
+ .smp = 1,
+ .boff_rec = 1,
+ .ext_msg = 1,
+ .std_msg = 1,
+};
+static struct flexcan_platform_data flexcan1_data = {
+ .core_reg = NULL,
+ .io_reg = NULL,
+ .root_clk_id = "lp_apm", /*lp_apm is 24MHz */
+ .xcvr_enable = flexcan_xcvr_enable,
+ .br_clksrc = 0,
+ .br_rjw = 2,
+ .br_presdiv = 3,
+ .br_propseg = 2,
+ .br_pseg1 = 3,
+ .br_pseg2 = 3,
+ .bcc = 1,
+ .srx_dis = 1,
+ .boff_rec = 1,
+ .ext_msg = 1,
+ .std_msg = 1,
+};
+
+
+extern void mx5_ipu_reset(void);
+static struct mxc_ipu_config mxc_ipu_data = {
+ .rev = 3,
+ .reset = mx5_ipu_reset,
+};
+
+extern void mx5_vpu_reset(void);
+static struct mxc_vpu_platform_data mxc_vpu_data = {
+ .reset = mx5_vpu_reset,
+};
+
+static struct fec_platform_data fec_data = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+/* workaround for ecspi chipselect pin may not keep correct level when idle */
+static void mx53_evk_gpio_spi_chipselect_active(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ switch (chipselect) {
+ case 0x1:
+ {
+ struct pad_desc eim_d19_gpio = MX53_PAD_EIM_D19__GPIO_3_19;
+ struct pad_desc cspi_ss0 = MX53_PAD_EIM_EB2__CSPI_SS0;
+
+ /* de-select SS1 of instance: ecspi1. */
+ mxc_iomux_v3_setup_pad(&eim_d19_gpio);
+ mxc_iomux_v3_setup_pad(&cspi_ss0);
+ }
+ break;
+ case 0x2:
+ {
+ struct pad_desc eim_eb2_gpio = MX53_PAD_EIM_EB2__GPIO_2_30;
+ struct pad_desc cspi_ss1 = MX53_PAD_EIM_D19__CSPI_SS1;
+
+ /* de-select SS0 of instance: ecspi1. */
+ mxc_iomux_v3_setup_pad(&eim_eb2_gpio);
+ mxc_iomux_v3_setup_pad(&cspi_ss1);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+static void mx53_evk_gpio_spi_chipselect_inactive(int cspi_mode, int status,
+ int chipselect)
+{
+ switch (cspi_mode) {
+ case 1:
+ switch (chipselect) {
+ case 0x1:
+ break;
+ case 0x2:
+ break;
+ default:
+ break;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ break;
+ default:
+ break;
+ }
+}
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+ .chipselect_active = mx53_evk_gpio_spi_chipselect_active,
+ .chipselect_inactive = mx53_evk_gpio_spi_chipselect_inactive,
+};
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "SW1",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "SW1",
+ .lp_reg_id = "SW2",
+};
+
+static struct tve_platform_data tve_data = {
+ .dac_reg = "VVIDEO",
+};
+
+static struct ldb_platform_data ldb_data = {
+ .lvds_bg_reg = "VAUDIO",
+ .ext_ref = 1,
+};
+
+static void mxc_iim_enable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg |= 0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static void mxc_iim_disable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg &= ~0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static struct mxc_iim_data iim_data = {
+ .bank_start = MXC_IIM_MX53_BANK_START_ADDR,
+ .bank_end = MXC_IIM_MX53_BANK_END_ADDR,
+ .enable_fuse = mxc_iim_enable_fuse,
+ .disable_fuse = mxc_iim_disable_fuse,
+};
+
+static struct pad_desc mx53esai_pads[] = {
+ MX53_PAD_FEC_MDIO__ESAI_SCKR,
+ MX53_PAD_FEC_REF_CLK__ESAI_FSR,
+ MX53_PAD_FEC_RX_ER__ESAI_HCKR,
+ MX53_PAD_FEC_CRS_DV__ESAI_SCKT,
+ MX53_PAD_FEC_RXD1__ESAI_FST,
+ MX53_PAD_FEC_RXD0__ESAI_HCKT,
+ MX53_PAD_FEC_TX_EN__ESAI_TX3_RX2,
+ MX53_PAD_FEC_TXD1__ESAI_TX2_RX3,
+ MX53_PAD_FEC_TXD0__ESAI_TX4_RX1,
+ MX53_PAD_FEC_MDC__ESAI_TX5_RX0,
+ MX53_PAD_NANDF_CS2__ESAI_TX0,
+ MX53_PAD_NANDF_CS3__ESAI_TX1,
+};
+
+void gpio_activate_esai_ports(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53esai_pads,
+ ARRAY_SIZE(mx53esai_pads));
+}
+
+static struct mxc_esai_platform_data esai_data = {
+ .activate_esai_ports = gpio_activate_esai_ports,
+};
+
+void gpio_cs42888_pdwn(int pdwn)
+{
+ if (pdwn)
+ gpio_set_value(MX53_ESAI_RESET, 0);
+ else
+ gpio_set_value(MX53_ESAI_RESET, 1);
+}
+
+static void gpio_usbotg_vbus_active(void)
+{
+ if (board_is_mx53_arm2()) {
+ /* MX53 ARM2 CPU board */
+ /* Enable OTG VBus with GPIO low */
+ gpio_set_value(ARM2_OTG_VBUS, 0);
+ } else if (board_is_mx53_evk_a()) {
+ /* MX53 EVK board ver A*/
+ /* Enable OTG VBus with GPIO low */
+ gpio_set_value(EVK_OTG_VBUS, 0);
+ } else if (board_is_mx53_evk_b()) {
+ /* MX53 EVK board ver B*/
+ /* Enable OTG VBus with GPIO high */
+ gpio_set_value(EVK_OTG_VBUS, 1);
+ }
+}
+
+static void gpio_usbotg_vbus_inactive(void)
+{
+ if (board_is_mx53_arm2()) {
+ /* MX53 ARM2 CPU board */
+ /* Disable OTG VBus with GPIO high */
+ gpio_set_value(ARM2_OTG_VBUS, 1);
+ } else if (board_is_mx53_evk_a()) {
+ /* MX53 EVK board ver A*/
+ /* Disable OTG VBus with GPIO high */
+ gpio_set_value(EVK_OTG_VBUS, 1);
+ } else if (board_is_mx53_evk_b()) {
+ /* MX53 EVK board ver B*/
+ /* Disable OTG VBus with GPIO low */
+ gpio_set_value(EVK_OTG_VBUS, 0);
+ }
+}
+
+static void mx53_gpio_usbotg_driver_vbus(bool on)
+{
+ if (on)
+ gpio_usbotg_vbus_active();
+ else
+ gpio_usbotg_vbus_inactive();
+}
+
+static void mx53_gpio_host1_driver_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(EVK_USBH1_VBUS, 1);
+ else
+ gpio_set_value(EVK_USBH1_VBUS, 0);
+}
+
+static void adv7180_pwdn(int pwdn)
+{
+ gpio_request(MX53_TVIN_PWR, "tvin-pwr");
+ if (pwdn)
+ gpio_set_value(MX53_TVIN_PWR, 0);
+ else
+ gpio_set_value(MX53_TVIN_PWR, 1);
+ gpio_free(MX53_TVIN_PWR);
+}
+
+static struct mxc_tvin_platform_data adv7180_data = {
+ .dvddio_reg = NULL,
+ .dvdd_reg = NULL,
+ .avdd_reg = NULL,
+ .pvdd_reg = NULL,
+ .pwdn = adv7180_pwdn,
+ .reset = NULL,
+};
+
+static struct resource mxcfb_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "800x480M@55",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_GBR24,
+ .mode_str = "1024x768M-16@60",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+extern int primary_di;
+static int __init mxc_init_fb(void)
+{
+ if (!machine_is_mx53_evk())
+ return 0;
+
+ if (primary_di) {
+ printk(KERN_INFO "DI1 is primary\n");
+ /* DI1 -> DP-BG channel: */
+ mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[1].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+
+ /* DI0 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+ } else {
+ printk(KERN_INFO "DI0 is primary\n");
+
+ /* DI0 -> DP-BG channel: */
+ mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[0].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+
+ /* DI1 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+ }
+
+ /*
+ * DI0/1 DP-FG channel:
+ */
+ mxc_register_device(&mxc_fb_devices[2], NULL);
+
+ return 0;
+}
+device_initcall(mxc_init_fb);
+
+static void camera_pwdn(int pwdn)
+{
+ gpio_request(MX53_TVIN_PWR, "tvin-pwr");
+ gpio_set_value(MX53_TVIN_PWR, pwdn);
+ gpio_free(MX53_TVIN_PWR);
+}
+
+static struct mxc_camera_platform_data camera_data = {
+ .analog_regulator = "VSD",
+ .gpo_regulator = "VVIDEO",
+ .mclk = 24000000,
+ .csi = 0,
+ .pwdn = camera_pwdn,
+};
+
+static struct mxc_audio_codec_platform_data cs42888_data = {
+ .analog_regulator = "VSD",
+ .pwdn = gpio_cs42888_pdwn,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ .type = "ov3640",
+ .addr = 0x3C,
+ .platform_data = (void *)&camera_data,
+ },
+ {
+ .type = "adv7180",
+ .addr = 0x21,
+ .platform_data = (void *)&adv7180_data,
+ },
+ {
+ .type = "cs42888",
+ .addr = 0x48,
+ .platform_data = &cs42888_data,
+ },
+};
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX53_DVI_RESET, 0);
+ msleep(10);
+ gpio_set_value(MX53_DVI_RESET, 1);
+ msleep(10);
+}
+
+static struct mxc_lcd_platform_data sii902x_hdmi_data = {
+ .reset = sii902x_hdmi_reset,
+};
+
+/* TO DO add platform data */
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "tsc2007",
+ .addr = 0x48,
+ .irq = IOMUX_TO_IRQ_V3(EVK_TS_INT),
+ },
+ {
+ .type = "backlight-i2c",
+ .addr = 0x2c,
+ },
+ {
+ .type = "vga-ddc",
+ .addr = 0x1f,
+ },
+ {
+ .type = "eeprom",
+ .addr = 0x50,
+ },
+ {
+ .type = "sii902x",
+ .addr = 0x39,
+ .irq = IOMUX_TO_IRQ_V3(MX53_DVI_DETECT),
+ .platform_data = &sii902x_hdmi_data,
+ },
+};
+
+static struct mtd_partition mxc_dataflash_partitions[] = {
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 0x000100000,},
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,},
+};
+
+static struct flash_platform_data mxc_spi_flash_data[] = {
+ {
+ .name = "mxc_dataflash",
+ .parts = mxc_dataflash_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_dataflash_partitions),
+ .type = "at45db321d",}
+};
+
+
+static struct spi_board_info mxc_dataflash_device[] __initdata = {
+ {
+ .modalias = "mxc_dataflash",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ .platform_data = &mxc_spi_flash_data[0],},
+};
+
+static int sdhc_write_protect(struct device *dev)
+{
+ unsigned short rc = 0;
+
+ if (!board_is_mx53_arm2()) {
+ if (to_platform_device(dev)->id == 0)
+ rc = gpio_get_value(EVK_SD1_WP);
+ else
+ rc = gpio_get_value(EVK_SD3_WP);
+ }
+
+ return rc;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret;
+ if (board_is_mx53_arm2()) {
+ if (to_platform_device(dev)->id == 0)
+ ret = gpio_get_value(ARM2_SD1_CD);
+ else
+ ret = 1;
+ } else {
+ if (to_platform_device(dev)->id == 0) {
+ ret = gpio_get_value(EVK_SD1_CD);
+ } else{ /* config the det pin for SDHC3 */
+ ret = gpio_get_value(EVK_SD3_CD);
+ }
+ }
+
+ return ret;
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA
+ | MMC_CAP_DATA_DDR,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static int mxc_sgtl5000_amp_enable(int enable)
+{
+/* TO DO */
+return 0;
+}
+
+static int headphone_det_status(void)
+{
+ return (gpio_get_value(MX53_HP_DETECT) == 0);
+}
+
+static int mxc_sgtl5000_init(void);
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 5,
+ .hp_irq = IOMUX_TO_IRQ(MX53_HP_DETECT),
+ .hp_status = headphone_det_status,
+ .amp_enable = mxc_sgtl5000_amp_enable,
+ .init = mxc_sgtl5000_init,
+};
+
+static int mxc_sgtl5000_init(void)
+{
+ struct clk *ssi_ext1;
+ int rate;
+
+ if (board_is_mx53_arm2()) {
+ sgtl5000_data.sysclk = 12000000;
+ } else {
+ ssi_ext1 = clk_get(NULL, "ssi_ext1_clk");
+ if (IS_ERR(ssi_ext1))
+ return -1;
+
+ rate = clk_round_rate(ssi_ext1, 24000000);
+ if (rate < 8000000 || rate > 27000000) {
+ printk(KERN_ERR "Error: SGTL5000 mclk freq %d out of range!\n",
+ rate);
+ clk_put(ssi_ext1);
+ return -1;
+ }
+
+ clk_set_rate(ssi_ext1, rate);
+ clk_enable(ssi_ext1);
+ sgtl5000_data.sysclk = rate;
+ }
+
+ return 0;
+}
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+static struct mxc_mlb_platform_data mlb_data = {
+ .reg_nvcc = "VCAM",
+ .mlb_clk = "mlb_clk",
+};
+
+static void mxc_register_powerkey(pwrkey_callback pk_cb)
+{
+ pmic_event_callback_t power_key_event;
+
+ power_key_event.param = (void *)1;
+ power_key_event.func = (void *)pk_cb;
+ pmic_event_subscribe(EVENT_PWRONI, power_key_event);
+}
+
+static int mxc_pwrkey_getstatus(int id)
+{
+ int sense;
+
+ pmic_read_reg(REG_INT_SENSE1, &sense, 0xffffffff);
+ if (sense & (1 << 3))
+ return 0;
+
+ return 1;
+}
+
+static struct power_key_platform_data pwrkey_data = {
+ .key_value = KEY_F4,
+ .register_pwrkey = mxc_register_powerkey,
+ .get_key_status = mxc_pwrkey_getstatus,
+};
+
+/* NAND Flash Partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition nand_flash_partitions[] = {
+/* MX53 ROM require the boot FCB/DBBT support which need
+ * more space to store such info on NAND boot partition.
+ * 16M should cover all kind of NAND boot support on MX53.
+ */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 16 * 1024 * 1024},
+ {
+ .name = "nand.kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 5 * 1024 * 1024},
+ {
+ .name = "nand.rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024 * 1024},
+ {
+ .name = "nand.userfs1",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 256 * 1024 * 1024},
+ {
+ .name = "nand.userfs2",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL},
+};
+#endif
+
+static int nand_init(void)
+{
+ u32 i, reg;
+ void __iomem *base;
+
+ #define M4IF_GENP_WEIM_MM_MASK 0x00000001
+ #define WEIM_GCR2_MUX16_BYP_GRANT_MASK 0x00001000
+
+ base = ioremap(MX53_BASE_ADDR(M4IF_BASE_ADDR), SZ_4K);
+ reg = __raw_readl(base + 0xc);
+ reg &= ~M4IF_GENP_WEIM_MM_MASK;
+ __raw_writel(reg, base + 0xc);
+
+ iounmap(base);
+
+ base = ioremap(MX53_BASE_ADDR(WEIM_BASE_ADDR), SZ_4K);
+ for (i = 0x4; i < 0x94; i += 0x18) {
+ reg = __raw_readl((u32)base + i);
+ reg &= ~WEIM_GCR2_MUX16_BYP_GRANT_MASK;
+ __raw_writel(reg, (u32)base + i);
+ }
+
+ iounmap(base);
+
+ return 0;
+}
+
+static struct flash_platform_data mxc_nand_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .parts = nand_flash_partitions,
+ .nr_parts = ARRAY_SIZE(nand_flash_partitions),
+#endif
+ .width = 1,
+ .init = nand_init,
+};
+
+static struct mxc_asrc_platform_data mxc_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 0, /* Souce from CKIH1 for 44.1K */
+ .spdif_clk_48000 = 7, /* Source from CKIH2 for 48k and 32k */
+ .spdif_clkid = 0,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static struct mxc_audio_platform_data mxc_surround_audio_data = {
+ .ext_ram = 1,
+ .sysclk = 22579200,
+};
+
+
+static struct platform_device mxc_alsa_surround_device = {
+ .name = "imx-3stack-cs42888",
+};
+
+static int __initdata mxc_apc_on = { 0 }; /* OFF: 0 (default), ON: 1 */
+static int __init apc_setup(char *__unused)
+{
+ mxc_apc_on = 1;
+ printk(KERN_INFO "Automotive Port Card is Plugged on\n");
+ return 1;
+}
+__setup("apc", apc_setup);
+
+static int __initdata enable_w1 = { 0 };
+static int __init w1_setup(char *__unused)
+{
+ enable_w1 = 1;
+ return cpu_is_mx53();
+}
+__setup("w1", w1_setup);
+
+
+static int __initdata enable_spdif = { 0 };
+static int __init spdif_setup(char *__unused)
+{
+ enable_spdif = 1;
+ return 1;
+}
+__setup("spdif", spdif_setup);
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ struct tag *t;
+ struct tag *mem_tag = 0;
+ int total_mem = SZ_1G;
+ int left_mem = 0;
+ int gpu_mem = SZ_128M;
+ int fb_mem = SZ_32M;
+ char *str;
+
+ mxc_set_cpu_type(MXC_CPU_MX53);
+
+ for_each_tag(mem_tag, tags) {
+ if (mem_tag->hdr.tag == ATAG_MEM) {
+ total_mem = mem_tag->u.mem.size;
+ left_mem = total_mem - gpu_mem - fb_mem;
+ break;
+ }
+ }
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "mem=");
+ if (str != NULL) {
+ str += 4;
+ left_mem = memparse(str, &str);
+ if (left_mem == 0 || left_mem > total_mem)
+ left_mem = total_mem - gpu_mem - fb_mem;
+ }
+
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "gpu_memory=");
+ if (str != NULL) {
+ str += 11;
+ gpu_mem = memparse(str, &str);
+ }
+
+ break;
+ }
+ }
+
+ if (mem_tag) {
+ fb_mem = total_mem - left_mem - gpu_mem;
+ if (fb_mem < 0) {
+ gpu_mem = total_mem - left_mem;
+ fb_mem = 0;
+ }
+ mem_tag->u.mem.size = left_mem;
+
+ /*reserve memory for gpu*/
+ gpu_device.resource[5].start =
+ mem_tag->u.mem.start + left_mem;
+ gpu_device.resource[5].end =
+ gpu_device.resource[5].start + gpu_mem - 1;
+#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \
+ defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
+ if (fb_mem) {
+ mxcfb_resources[0].start =
+ gpu_device.resource[5].end + 1;
+ mxcfb_resources[0].end =
+ mxcfb_resources[0].start + fb_mem - 1;
+ } else {
+ mxcfb_resources[0].start = 0;
+ mxcfb_resources[0].end = 0;
+ }
+#endif
+ }
+}
+
+static void __init mx53_evk_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53common_pads,
+ ARRAY_SIZE(mx53common_pads));
+
+ if (board_is_mx53_arm2()) {
+ /* MX53 ARM2 CPU board */
+ pr_info("MX53 ARM2 board \n");
+ mxc_iomux_v3_setup_multiple_pads(mx53arm2_pads,
+ ARRAY_SIZE(mx53arm2_pads));
+
+ /* Config GPIO for OTG VBus */
+ gpio_request(ARM2_OTG_VBUS, "otg-vbus");
+ gpio_direction_output(ARM2_OTG_VBUS, 1);
+
+ gpio_request(ARM2_SD1_CD, "sdhc1-cd");
+ gpio_direction_input(ARM2_SD1_CD); /* SD1 CD */
+
+ gpio_request(ARM2_LCD_CONTRAST, "lcd-contrast");
+ gpio_direction_output(ARM2_LCD_CONTRAST, 1);
+ } else {
+ /* MX53 EVK board */
+ pr_info("MX53 EVK board \n");
+ mxc_iomux_v3_setup_multiple_pads(mx53evk_pads,
+ ARRAY_SIZE(mx53evk_pads));
+
+ /* Host1 Vbus with GPIO high */
+ gpio_request(EVK_USBH1_VBUS, "usbh1-vbus");
+ gpio_direction_output(EVK_USBH1_VBUS, 1);
+ /* shutdown the Host1 Vbus when system bring up,
+ * Vbus will be opened in Host1 driver's probe function */
+ gpio_set_value(EVK_USBH1_VBUS, 0);
+
+ /* USB HUB RESET - De-assert USB HUB RESET_N */
+ gpio_request(EVK_USB_HUB_RESET, "usb-hub-reset");
+ gpio_direction_output(EVK_USB_HUB_RESET, 0);
+ msleep(1);
+ gpio_set_value(EVK_USB_HUB_RESET, 1);
+
+ /* Config GPIO for OTG VBus */
+ gpio_request(EVK_OTG_VBUS, "otg-vbus");
+ gpio_direction_output(EVK_OTG_VBUS, 0);
+ if (board_is_mx53_evk_a()) /*rev A,"1" disable, "0" enable vbus*/
+ gpio_set_value(EVK_OTG_VBUS, 1);
+ else if (board_is_mx53_evk_b()) /* rev B,"0" disable,"1" enable Vbus*/
+ gpio_set_value(EVK_OTG_VBUS, 0);
+
+ gpio_request(EVK_SD1_CD, "sdhc1-cd");
+ gpio_direction_input(EVK_SD1_CD); /* SD1 CD */
+ gpio_request(EVK_SD1_WP, "sdhc1-wp");
+ gpio_direction_input(EVK_SD1_WP); /* SD1 WP */
+
+ /* SD3 CD */
+ gpio_request(EVK_SD3_CD, "sdhc3-cd");
+ gpio_direction_input(EVK_SD3_CD);
+
+ /* SD3 WP */
+ gpio_request(EVK_SD3_WP, "sdhc3-wp");
+ gpio_direction_input(EVK_SD3_WP);
+
+ /* reset FEC PHY */
+ gpio_request(EVK_FEC_PHY_RESET, "fec-phy-reset");
+ gpio_direction_output(EVK_FEC_PHY_RESET, 0);
+ msleep(1);
+ gpio_set_value(EVK_FEC_PHY_RESET, 1);
+
+ gpio_request(MX53_ESAI_RESET, "fesai-reset");
+ gpio_direction_output(MX53_ESAI_RESET, 0);
+ }
+
+ /* DVI Detect */
+ gpio_request(MX53_DVI_DETECT, "dvi-detect");
+ gpio_direction_input(MX53_DVI_DETECT);
+ /* DVI Reset - Assert for i2c disabled mode */
+ gpio_request(MX53_DVI_RESET, "dvi-reset");
+ gpio_direction_output(MX53_DVI_RESET, 0);
+
+ /* DVI Power-down */
+ gpio_request(MX53_DVI_PD, "dvi-pd");
+ gpio_direction_output(MX53_DVI_PD, 1);
+
+ /* DVI I2C enable */
+ gpio_request(MX53_DVI_I2C, "dvi-i2c");
+ gpio_direction_output(MX53_DVI_I2C, 0);
+
+ mxc_iomux_v3_setup_multiple_pads(mx53_nand_pads,
+ ARRAY_SIZE(mx53_nand_pads));
+
+ gpio_request(MX53_PMIC_INT, "pmic-int");
+ gpio_direction_input(MX53_PMIC_INT); /*PMIC_INT*/
+
+ /* headphone_det_b */
+ gpio_request(MX53_HP_DETECT, "hp-detect");
+ gpio_direction_input(MX53_HP_DETECT);
+
+ /* power key */
+
+ /* LCD related gpio */
+
+ /* Camera reset */
+ gpio_request(MX53_CAM_RESET, "cam-reset");
+ gpio_direction_output(MX53_CAM_RESET, 1);
+
+ /* TVIN reset */
+ gpio_request(MX53_TVIN_RESET, "tvin-reset");
+ gpio_direction_output(MX53_TVIN_RESET, 0);
+ msleep(5);
+ gpio_set_value(MX53_TVIN_RESET, 1);
+
+ /* TVin power down */
+ gpio_request(MX53_TVIN_PWR, "tvin-pwr");
+ gpio_direction_output(MX53_TVIN_PWR, 0);
+
+ /* CAN1 enable GPIO*/
+ gpio_request(MX53_CAN1_EN1, "can1-en1");
+ gpio_direction_output(MX53_CAN1_EN1, 0);
+
+ gpio_request(MX53_CAN1_EN2, "can1-en2");
+ gpio_direction_output(MX53_CAN1_EN2, 0);
+
+ /* CAN2 enable GPIO*/
+ gpio_request(MX53_CAN2_EN1, "can2-en1");
+ gpio_direction_output(MX53_CAN2_EN1, 0);
+
+ gpio_request(MX53_CAN2_EN2, "can2-en2");
+ gpio_direction_output(MX53_CAN2_EN2, 0);
+
+ if (enable_spdif) {
+ struct pad_desc spdif_pin = MX53_PAD_GPIO_19__SPDIF_TX1;
+ mxc_iomux_v3_setup_pad(&spdif_pin);
+ } else {
+ /* GPIO for 12V */
+ gpio_request(MX53_12V_EN, "12v-en");
+ gpio_direction_output(MX53_12V_EN, 0);
+ }
+}
+
+extern void mx53_gpio_usbotg_driver_vbus(bool on);
+extern void mx53_gpio_host1_driver_vbus(bool on);
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ mxc_ipu_data.di_clk[0] = clk_get(NULL, "ipu_di0_clk");
+ mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk");
+ mxc_ipu_data.csi_clk[0] = clk_get(NULL, "ssi_ext1_clk");
+ mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk");
+ clk_put(mxc_spdif_data.spdif_core_clk);
+
+ /* SD card detect irqs */
+ if (board_is_mx53_arm2()) {
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(ARM2_SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(ARM2_SD1_CD);
+ mmc3_data.card_inserted_state = 1;
+ mmc3_data.status = NULL;
+ mmc3_data.wp_status = NULL;
+ mmc1_data.wp_status = NULL;
+ } else {
+ mxcsdhc3_device.resource[2].start = IOMUX_TO_IRQ_V3(EVK_SD3_CD);
+ mxcsdhc3_device.resource[2].end = IOMUX_TO_IRQ_V3(EVK_SD3_CD);
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(EVK_SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(EVK_SD1_CD);
+ }
+
+ mxc_cpu_common_init();
+ mx53_evk_io_init();
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[2], &mxci2c_data);
+
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_w1_master_device, &mxc_w1_data);
+ mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
+ mxc_register_device(&mxc_ldb_device, &ldb_data);
+ mxc_register_device(&mxc_tve_device, &tve_data);
+ mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
+ mxc_register_device(&gpu_device, &z160_revision);
+ mxc_register_device(&mxcscc_device, NULL);
+ /*
+ mxc_register_device(&mx53_lpmode_device, NULL);
+ mxc_register_device(&sdram_autogating_device, NULL);
+ */
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+
+ /*
+ mxc_register_device(&mxc_dvfs_per_device, &dvfs_per_data);
+ */
+
+ mxc_register_device(&mxc_iim_device, &iim_data);
+ if (!board_is_mx53_arm2()) {
+ mxc_register_device(&mxc_pwm2_device, NULL);
+ mxc_register_device(&mxc_pwm1_backlight_device,
+ &mxc_pwm_backlight_data);
+ }
+ mxc_register_device(&mxc_flexcan0_device, &flexcan0_data);
+ mxc_register_device(&mxc_flexcan1_device, &flexcan1_data);
+
+/* mxc_register_device(&mxc_keypad_device, &keypad_plat_data); */
+
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc3_device, &mmc3_data);
+ mxc_register_device(&mxc_ssi1_device, NULL);
+ mxc_register_device(&mxc_ssi2_device, NULL);
+ mxc_register_device(&ahci_fsl_device, &sata_data);
+
+ /* ASRC is only available for MX53 TO2.0 */
+ if (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1) {
+ mxc_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ clk_put(mxc_asrc_data.asrc_core_clk);
+ mxc_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ clk_put(mxc_asrc_data.asrc_audio_clk);
+ mxc_register_device(&mxc_asrc_device, &mxc_asrc_data);
+ }
+
+ mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
+ if (!mxc_apc_on) {
+ mxc_register_device(&mxc_fec_device, &fec_data);
+ mxc_register_device(&mxc_ptp_device, NULL);
+ }
+ spi_register_board_info(mxc_dataflash_device,
+ ARRAY_SIZE(mxc_dataflash_device));
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+
+ mx53_evk_init_mc13892();
+/*
+ pm_power_off = mxc_power_off;
+ */
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+ mxc_register_device(&mxc_mlb_device, &mlb_data);
+ mxc_register_device(&mxc_powerkey_device, &pwrkey_data);
+ mx5_set_otghost_vbus_func(mx53_gpio_usbotg_driver_vbus);
+ mx5_usb_dr_init();
+ mx5_set_host1_vbus_func(mx53_gpio_host1_driver_vbus);
+ mx5_usbh1_init();
+ mxc_register_device(&mxc_nandv2_mtd_device, &mxc_nand_data);
+ if (mxc_apc_on) {
+ mxc_register_device(&mxc_esai_device, &esai_data);
+ mxc_register_device(&mxc_alsa_surround_device,
+ &mxc_surround_audio_data);
+ }
+ mxc_register_device(&mxc_v4l2_device, NULL);
+ mxc_register_device(&mxc_v4l2out_device, NULL);
+}
+
+static void __init mx53_evk_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx53_clocks_init(32768, 24000000, 22579200, 24576000);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(MX53_BASE_ADDR(UART1_BASE_ADDR), uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx53_evk_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX53_EVK data structure.
+ */
+MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx53_evk_pmic_mc13892.c b/arch/arm/mach-mx5/mx53_evk_pmic_mc13892.c
new file mode 100644
index 000000000000..3ed2e14e49ba
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_evk_pmic_mc13892.c
@@ -0,0 +1,351 @@
+/*
+ * mx53-evk-pmic-mc13892.c -- i.MX53 3STACK Driver for Atlas MC13892 PMIC
+ */
+ /*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+ /*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/pmic_external.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/mc13892/core.h>
+#include <mach/irqs.h>
+
+#include <mach/iomux-mx53.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)
+
+#define STANDBYSECINV_LSH 11
+#define STANDBYSECINV_WID 1
+
+/* Coin cell charger enable */
+#define COINCHEN_LSH 23
+#define COINCHEN_WID 1
+/* Coin cell charger voltage setting */
+#define VCOIN_LSH 20
+#define VCOIN_WID 3
+
+/* Coin Charger voltage */
+#define VCOIN_2_5V 0x0
+#define VCOIN_2_7V 0x1
+#define VCOIN_2_8V 0x2
+#define VCOIN_2_9V 0x3
+#define VCOIN_3_0V 0x4
+#define VCOIN_3_1V 0x5
+#define VCOIN_3_2V 0x6
+#define VCOIN_3_3V 0x7
+
+/* Keeps VSRTC and CLK32KMCU on for all states */
+#define DRM_LSH 4
+#define DRM_WID 1
+
+/* CPU */
+static struct regulator_consumer_supply sw1_consumers[] = {
+ {
+ .supply = "cpu_vcc",
+ }
+};
+
+struct mc13892;
+
+static struct regulator_init_data sw1_init = {
+ .constraints = {
+ .name = "SW1",
+ .min_uV = mV_to_uV(600),
+ .max_uV = mV_to_uV(1375),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .valid_modes_mask = 0,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 850000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+ .consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+ .constraints = {
+ .name = "SW2",
+ .min_uV = mV_to_uV(900),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ .initial_state = PM_SUSPEND_MEM,
+ .state_mem = {
+ .uV = 950000,
+ .mode = REGULATOR_MODE_NORMAL,
+ .enabled = 1,
+ },
+ }
+};
+
+static struct regulator_init_data sw3_init = {
+ .constraints = {
+ .name = "SW3",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data sw4_init = {
+ .constraints = {
+ .name = "SW4",
+ .min_uV = mV_to_uV(1100),
+ .max_uV = mV_to_uV(1850),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data viohi_init = {
+ .constraints = {
+ .name = "VIOHI",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb_init = {
+ .constraints = {
+ .name = "VUSB",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data swbst_init = {
+ .constraints = {
+ .name = "SWBST",
+ }
+};
+
+static struct regulator_init_data vdig_init = {
+ .constraints = {
+ .name = "VDIG",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vpll_init = {
+ .constraints = {
+ .name = "VPLL",
+ .min_uV = mV_to_uV(1050),
+ .max_uV = mV_to_uV(1800),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vusb2_init = {
+ .constraints = {
+ .name = "VUSB2",
+ .min_uV = mV_to_uV(2400),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vvideo_init = {
+ .constraints = {
+ .name = "VVIDEO",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(2775),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = 1,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vaudio_init = {
+ .constraints = {
+ .name = "VAUDIO",
+ .min_uV = mV_to_uV(2300),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vsd_init = {
+ .constraints = {
+ .name = "VSD",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vcam_init = {
+ .constraints = {
+ .name = "VCAM",
+ .min_uV = mV_to_uV(2500),
+ .max_uV = mV_to_uV(3000),
+ .valid_ops_mask =
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+ }
+};
+
+static struct regulator_init_data vgen1_init = {
+ .constraints = {
+ .name = "VGEN1",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data vgen2_init = {
+ .constraints = {
+ .name = "VGEN2",
+ .min_uV = mV_to_uV(1200),
+ .max_uV = mV_to_uV(3150),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1,
+ }
+};
+
+static struct regulator_init_data vgen3_init = {
+ .constraints = {
+ .name = "VGEN3",
+ .min_uV = mV_to_uV(1800),
+ .max_uV = mV_to_uV(2900),
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo1_init = {
+ .constraints = {
+ .name = "GPO1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo2_init = {
+ .constraints = {
+ .name = "GPO2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo3_init = {
+ .constraints = {
+ .name = "GPO3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static struct regulator_init_data gpo4_init = {
+ .constraints = {
+ .name = "GPO4",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ }
+};
+
+static int mc13892_regulator_init(struct mc13892 *mc13892)
+{
+ unsigned int value;
+ int register_mask;
+
+ pr_info("Initializing regulators for MX53 EVK \n");
+
+ /* Bit 4 DRM: keep VSRTC and CLK32KMCU on for all states */
+#if defined(CONFIG_RTC_DRV_MXC_V2) || defined(CONFIG_RTC_DRV_MXC_V2_MODULE)
+ value = BITFVAL(DRM, 1);
+ register_mask = BITFMASK(DRM);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+#endif
+ /* Set the STANDBYSECINV bit, so that STANDBY pin is
+ * interpreted as active low.
+ */
+ value = BITFVAL(STANDBYSECINV, 1);
+ register_mask = BITFMASK(STANDBYSECINV);
+ pmic_write_reg(REG_POWER_CTL2, value, register_mask);
+
+ /* Disable coin cell charger since the cell is not rechargeable */
+ value = BITFVAL(COINCHEN, 0) | BITFVAL(VCOIN, VCOIN_3_0V);
+ register_mask = BITFMASK(COINCHEN) | BITFMASK(VCOIN);
+ pmic_write_reg(REG_POWER_CTL0, value, register_mask);
+
+ mc13892_register_regulator(mc13892, MC13892_SW1, &sw1_init);
+ mc13892_register_regulator(mc13892, MC13892_SW2, &sw2_init);
+ mc13892_register_regulator(mc13892, MC13892_SW3, &sw3_init);
+ mc13892_register_regulator(mc13892, MC13892_SW4, &sw4_init);
+ mc13892_register_regulator(mc13892, MC13892_SWBST, &swbst_init);
+ mc13892_register_regulator(mc13892, MC13892_VIOHI, &viohi_init);
+ mc13892_register_regulator(mc13892, MC13892_VPLL, &vpll_init);
+ mc13892_register_regulator(mc13892, MC13892_VDIG, &vdig_init);
+ mc13892_register_regulator(mc13892, MC13892_VSD, &vsd_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB2, &vusb2_init);
+ mc13892_register_regulator(mc13892, MC13892_VVIDEO, &vvideo_init);
+ mc13892_register_regulator(mc13892, MC13892_VAUDIO, &vaudio_init);
+ mc13892_register_regulator(mc13892, MC13892_VCAM, &vcam_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN1, &vgen1_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN2, &vgen2_init);
+ mc13892_register_regulator(mc13892, MC13892_VGEN3, &vgen3_init);
+ mc13892_register_regulator(mc13892, MC13892_VUSB, &vusb_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO1, &gpo1_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO2, &gpo2_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO3, &gpo3_init);
+ mc13892_register_regulator(mc13892, MC13892_GPO4, &gpo4_init);
+
+ return 0;
+}
+
+static struct mc13892_platform_data mc13892_plat = {
+ .init = mc13892_regulator_init,
+};
+
+static struct i2c_board_info __initdata mc13892_i2c_device = {
+ I2C_BOARD_INFO("mc13892", 0x08),
+ .irq = IOMUX_TO_IRQ_V3(203),
+ .platform_data = &mc13892_plat,
+};
+
+int __init mx53_evk_init_mc13892(void)
+{
+ return i2c_register_board_info(1, &mc13892_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx53_loco.c b/arch/arm/mach-mx5/mx53_loco.c
new file mode 100644
index 000000000000..7074dcdf55de
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_loco.c
@@ -0,0 +1,839 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/ahci_platform.h>
+#include <linux/gpio_keys.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/keypad.h>
+#include <asm/mach/flash.h>
+#include <mach/memory.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/iomux-mx53.h>
+#include <mach/i2c.h>
+#include <mach/mxc_iim.h>
+
+#include "crm_regs.h"
+#include "devices.h"
+#include "usb.h"
+
+/*!
+ * @file mach-mx5/mx53_loco.c
+ *
+ * @brief This file contains MX53 loco board specific initialization routines.
+ *
+ * @ingroup MSL_MX53
+ */
+
+/* MX53 LOCO GPIO PIN configurations */
+#define NVDD_FAULT (0*32 + 5) /* GPIO1_5 */
+
+#define FEC_INT (1*32 + 4) /* GPIO_2_4 */
+#define HEADPHONE_DEC_B (1*32 + 5) /* GPIO_2_5 */
+#define MIC_DEC_B (1*32 + 6) /* GPIO_2_6 */
+#define USER_UI1 (1*32 + 14) /* GPIO_2_14 */
+#define USER_UI2 (1*32 + 15) /* GPIO_2_15 */
+#define MX53_nONKEY (0*32 + 8) /* GPIO_1_8 */
+
+#define SD3_CD (2*32 + 11) /* GPIO_3_11 */
+#define SD3_WP (2*32 + 12) /* GPIO_3_12 */
+#define DISP0_POWER_EN (2*32 + 24) /* GPIO_3_24 */
+#define DISP0_DET_INT (2*32 + 31) /* GPIO_3_31 */
+
+#define DISP0_RESET (4*32 + 0) /* GPIO_5_0 */
+
+#define CSI0_RTSB (5*32 + 9) /* GPIO_6_9 */
+#define CSI0_PWDN (5*32 + 10) /* GPIO_6_10 */
+#define ACCL_EN (5*32 + 14) /* GPIO_6_14 */
+#define ACCL_INT1_IN (5*32 + 15) /* GPIO_6_15 */
+#define ACCL_INT2_IN (5*32 + 16) /* GPIO_6_16 */
+
+#define LCD_BLT_EN (6*32 + 2) /* GPIO_7_2 */
+#define FEC_RST (6*32 + 6) /* GPIO_7_6 */
+#define USER_LED_EN (6*32 + 7) /* GPIO_7_7 */
+#define USB_PWREN (6*32 + 8) /* GPIO_7_8 */
+#define NIRQ (6*32 + 11) /* GPIO7_11 */
+
+extern int __init mx53_loco_init_da9052(void);
+
+static struct pad_desc mx53_loco_pads[] = {
+ /* FEC */
+ MX53_PAD_FEC_MDC__FEC_MDC,
+ MX53_PAD_FEC_MDIO__FEC_MDIO,
+ MX53_PAD_FEC_REF_CLK__FEC_REF_CLK,
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+ MX53_PAD_FEC_CRS_DV__FEC_CRS_DV,
+ MX53_PAD_FEC_RXD1__FEC_RXD1,
+ MX53_PAD_FEC_RXD0__FEC_RXD0,
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+ MX53_PAD_FEC_TXD1__FEC_TXD1,
+ MX53_PAD_FEC_TXD0__FEC_TXD0,
+ /* FEC_nRST */
+ MX53_PAD_ATA_DA_0__GPIO_7_6,
+ /* FEC_nINT */
+ MX53_PAD_ATA_DATA4__GPIO_2_4,
+ /* AUDMUX5 */
+ MX53_PAD_KEY_COL0__AUD5_TXC,
+ MX53_PAD_KEY_ROW0__AUD5_TXD,
+ MX53_PAD_KEY_COL1__AUD5_TXFS,
+ MX53_PAD_KEY_ROW1__AUD5_RXD,
+ /* I2C2 */
+ MX53_PAD_KEY_COL3__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+ /* SD1 */
+ MX53_PAD_SD1_CMD__SD1_CMD,
+ MX53_PAD_SD1_CLK__SD1_CLK,
+ MX53_PAD_SD1_DATA0__SD1_DATA0,
+ MX53_PAD_SD1_DATA1__SD1_DATA1,
+ MX53_PAD_SD1_DATA2__SD1_DATA2,
+ MX53_PAD_SD1_DATA3__SD1_DATA3,
+ /* SD3 */
+ MX53_PAD_ATA_DATA8__SD3_DAT0,
+ MX53_PAD_ATA_DATA9__SD3_DAT1,
+ MX53_PAD_ATA_DATA10__SD3_DAT2,
+ MX53_PAD_ATA_DATA11__SD3_DAT3,
+ MX53_PAD_ATA_DATA0__SD3_DAT4,
+ MX53_PAD_ATA_DATA1__SD3_DAT5,
+ MX53_PAD_ATA_DATA2__SD3_DAT6,
+ MX53_PAD_ATA_DATA3__SD3_DAT7,
+ MX53_PAD_ATA_IORDY__SD3_CLK,
+ MX53_PAD_ATA_RESET_B__SD3_CMD,
+ /* SD3_CD */
+ MX53_PAD_EIM_DA11__GPIO_3_11,
+ /* SD3_WP */
+ MX53_PAD_EIM_DA12__GPIO_3_12,
+ /* VGA */
+ MX53_PAD_EIM_OE__DI1_PIN7,
+ MX53_PAD_EIM_RW__DI1_PIN8,
+ /* DISPLB */
+ MX53_PAD_EIM_D20__SER_DISP0_CS,
+ MX53_PAD_EIM_D21__DISPB0_SER_CLK,
+ MX53_PAD_EIM_D22__DISPB0_SER_DIN,
+ MX53_PAD_EIM_D23__DI0_D0_CS,
+ /* DISP0_POWER_EN */
+ MX53_PAD_EIM_D24__GPIO_3_24,
+ /* DISP0 DET INT */
+ MX53_PAD_EIM_D31__GPIO_3_31,
+
+ /* LVDS */
+ MX53_PAD_LVDS0_TX3_P__LVDS0_TX3,
+ MX53_PAD_LVDS0_CLK_P__LVDS0_CLK,
+ MX53_PAD_LVDS0_TX2_P__LVDS0_TX2,
+ MX53_PAD_LVDS0_TX1_P__LVDS0_TX1,
+ MX53_PAD_LVDS0_TX0_P__LVDS0_TX0,
+ MX53_PAD_LVDS1_TX3_P__LVDS1_TX3,
+ MX53_PAD_LVDS1_TX2_P__LVDS1_TX2,
+ MX53_PAD_LVDS1_CLK_P__LVDS1_CLK,
+ MX53_PAD_LVDS1_TX1_P__LVDS1_TX1,
+ MX53_PAD_LVDS1_TX0_P__LVDS1_TX0,
+ /* I2C1 */
+ MX53_PAD_CSI0_D8__I2C1_SDA,
+ MX53_PAD_CSI0_D9__I2C1_SCL,
+ /* UART1 */
+ MX53_PAD_CSI0_D10__UART1_TXD,
+ MX53_PAD_CSI0_D11__UART1_RXD,
+ /* CSI0 */
+ MX53_PAD_CSI0_D12__CSI0_D12,
+ MX53_PAD_CSI0_D13__CSI0_D13,
+ MX53_PAD_CSI0_D14__CSI0_D14,
+ MX53_PAD_CSI0_D15__CSI0_D15,
+ MX53_PAD_CSI0_D16__CSI0_D16,
+ MX53_PAD_CSI0_D17__CSI0_D17,
+ MX53_PAD_CSI0_D18__CSI0_D18,
+ MX53_PAD_CSI0_D19__CSI0_D19,
+ MX53_PAD_CSI0_VSYNC__CSI0_VSYNC,
+ MX53_PAD_CSI0_MCLK__CSI0_HSYNC,
+ MX53_PAD_CSI0_PIXCLK__CSI0_PIXCLK,
+ /* DISPLAY */
+ MX53_PAD_DI0_DISP_CLK__DI0_DISP_CLK,
+ MX53_PAD_DI0_PIN15__DI0_PIN15,
+ MX53_PAD_DI0_PIN2__DI0_PIN2,
+ MX53_PAD_DI0_PIN3__DI0_PIN3,
+ MX53_PAD_DISP0_DAT0__DISP0_DAT0,
+ MX53_PAD_DISP0_DAT1__DISP0_DAT1,
+ MX53_PAD_DISP0_DAT2__DISP0_DAT2,
+ MX53_PAD_DISP0_DAT3__DISP0_DAT3,
+ MX53_PAD_DISP0_DAT4__DISP0_DAT4,
+ MX53_PAD_DISP0_DAT5__DISP0_DAT5,
+ MX53_PAD_DISP0_DAT6__DISP0_DAT6,
+ MX53_PAD_DISP0_DAT7__DISP0_DAT7,
+ MX53_PAD_DISP0_DAT8__DISP0_DAT8,
+ MX53_PAD_DISP0_DAT9__DISP0_DAT9,
+ MX53_PAD_DISP0_DAT10__DISP0_DAT10,
+ MX53_PAD_DISP0_DAT11__DISP0_DAT11,
+ MX53_PAD_DISP0_DAT12__DISP0_DAT12,
+ MX53_PAD_DISP0_DAT13__DISP0_DAT13,
+ MX53_PAD_DISP0_DAT14__DISP0_DAT14,
+ MX53_PAD_DISP0_DAT15__DISP0_DAT15,
+ MX53_PAD_DISP0_DAT16__DISP0_DAT16,
+ MX53_PAD_DISP0_DAT17__DISP0_DAT17,
+ MX53_PAD_DISP0_DAT18__DISP0_DAT18,
+ MX53_PAD_DISP0_DAT19__DISP0_DAT19,
+ MX53_PAD_DISP0_DAT20__DISP0_DAT20,
+ MX53_PAD_DISP0_DAT21__DISP0_DAT21,
+ MX53_PAD_DISP0_DAT22__DISP0_DAT22,
+ MX53_PAD_DISP0_DAT23__DISP0_DAT23,
+ /* Audio CLK*/
+ MX53_PAD_GPIO_0__SSI_EXT1_CLK,
+ /* PWM */
+ MX53_PAD_GPIO_1__PWMO,
+ /* SPDIF */
+ MX53_PAD_GPIO_7__PLOCK,
+ MX53_PAD_GPIO_17__SPDIF_OUT1,
+ /* GPIO */
+ MX53_PAD_ATA_DA_1__GPIO_7_7,
+ MX53_PAD_ATA_DA_2__GPIO_7_8,
+ MX53_PAD_ATA_DATA5__GPIO_2_5,
+ MX53_PAD_ATA_DATA6__GPIO_2_6,
+ MX53_PAD_ATA_DATA14__GPIO_2_14,
+ MX53_PAD_ATA_DATA15__GPIO_2_15,
+ MX53_PAD_ATA_INTRQ__GPIO_7_2,
+ MX53_PAD_EIM_WAIT__GPIO_5_0,
+ MX53_PAD_NANDF_WP_B__GPIO_6_9,
+ MX53_PAD_NANDF_RB0__GPIO_6_10,
+ MX53_PAD_NANDF_CS1__GPIO_6_14,
+ MX53_PAD_NANDF_CS2__GPIO_6_15,
+ MX53_PAD_NANDF_CS3__GPIO_6_16,
+ MX53_PAD_GPIO_5__GPIO_1_5,
+ MX53_PAD_GPIO_16__GPIO_7_11,
+ MX53_PAD_GPIO_8__GPIO_1_8,
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 800x480 @ 60 Hz , pixel clk @ 32MHz */
+ "SEIKO-WVGA", 60, 800, 480, 29850, 89, 164, 23, 10, 10, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 1600x1200 @ 60 Hz 162M pixel clk*/
+ "UXGA", 60, 1600, 1200, 6172,
+ 304, 64,
+ 1, 46,
+ 192, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ /* 2 LVDS modes, had better remove from here */
+ {
+ "1080P60", 60, 1920, 1080, 7692,
+ 100, 40,
+ 30, 3,
+ 10, 2,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ "XGA", 60, 1024, 768, 15385,
+ 220, 40,
+ 21, 7,
+ 60, 10,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct platform_pwm_backlight_data mxc_pwm_backlight_data = {
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+extern void mx5_ipu_reset(void);
+static struct mxc_ipu_config mxc_ipu_data = {
+ .rev = 3,
+ .reset = mx5_ipu_reset,
+};
+
+extern void mx5_vpu_reset(void);
+static struct mxc_vpu_platform_data mxc_vpu_data = {
+ .reset = mx5_vpu_reset,
+};
+
+static struct fec_platform_data fec_data = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "DA9052_BUCK_CORE",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "DA9052_BUCK_CORE",
+ .lp_reg_id = "DA9052_BUCK_PRO",
+};
+
+static struct tve_platform_data tve_data = {
+ .dac_reg = "DA9052_LDO7",
+};
+
+static struct ldb_platform_data ldb_data = {
+ .ext_ref = 1,
+};
+
+static void mxc_iim_enable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg |= 0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static void mxc_iim_disable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg &= ~0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static struct mxc_iim_data iim_data = {
+ .bank_start = MXC_IIM_MX53_BANK_START_ADDR,
+ .bank_end = MXC_IIM_MX53_BANK_END_ADDR,
+ .enable_fuse = mxc_iim_enable_fuse,
+ .disable_fuse = mxc_iim_disable_fuse,
+};
+
+static struct resource mxcfb_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "800x480M@55",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_GBR24,
+ .mode_str = "1024x768M-16@60",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+extern int primary_di;
+static int __init mxc_init_fb(void)
+{
+ if (!machine_is_mx53_loco())
+ return 0;
+
+ if (primary_di) {
+ printk(KERN_INFO "DI1 is primary\n");
+ /* DI1 -> DP-BG channel: */
+ mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[1].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+
+ /* DI0 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+ } else {
+ printk(KERN_INFO "DI0 is primary\n");
+
+ /* DI0 -> DP-BG channel: */
+ mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[0].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+
+ /* DI1 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+ }
+
+ /*
+ * DI0/1 DP-FG channel:
+ */
+ mxc_register_device(&mxc_fb_devices[2], NULL);
+
+ return 0;
+}
+device_initcall(mxc_init_fb);
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(DISP0_RESET, 0);
+ msleep(10);
+ gpio_set_value(DISP0_RESET, 1);
+ msleep(10);
+}
+
+static struct mxc_lcd_platform_data sii902x_hdmi_data = {
+ .reset = sii902x_hdmi_reset,
+};
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ .type = "mma8450",
+ .addr = 0x1C,
+ },
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "sii902x",
+ .addr = 0x39,
+ .irq = IOMUX_TO_IRQ_V3(DISP0_DET_INT),
+ .platform_data = &sii902x_hdmi_data,
+ },
+};
+
+static int sdhc_write_protect(struct device *dev)
+{
+ int ret = 0;
+
+ if (to_platform_device(dev)->id == 2)
+ ret = gpio_get_value(SD3_WP);
+
+ return ret;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret = 0;
+
+ if (to_platform_device(dev)->id == 2)
+ ret = gpio_get_value(SD3_CD);
+
+ return ret;
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 1,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA
+ | MMC_CAP_DATA_DDR,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+static int headphone_det_status(void)
+{
+ return (gpio_get_value(HEADPHONE_DEC_B) == 0);
+}
+
+static int mxc_sgtl5000_init(void);
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 5,
+ .hp_irq = IOMUX_TO_IRQ_V3(HEADPHONE_DEC_B),
+ .hp_status = headphone_det_status,
+ .init = mxc_sgtl5000_init,
+};
+
+static int mxc_sgtl5000_init(void)
+{
+ struct clk *ssi_ext1;
+ int rate;
+
+ ssi_ext1 = clk_get(NULL, "ssi_ext1_clk");
+ if (IS_ERR(ssi_ext1))
+ return -1;
+
+ rate = clk_round_rate(ssi_ext1, 24000000);
+ if (rate < 8000000 || rate > 27000000) {
+ printk(KERN_ERR "Error: SGTL5000 mclk freq %d out of range!\n",
+ rate);
+ clk_put(ssi_ext1);
+ return -1;
+ }
+
+ clk_set_rate(ssi_ext1, rate);
+ clk_enable(ssi_ext1);
+ sgtl5000_data.sysclk = rate;
+
+ return 0;
+}
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+static struct mxc_asrc_platform_data mxc_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = -1, /* Souce from CKIH1 for 44.1K */
+ /* Source from CCM spdif_clk (24M) for 48k and 32k
+ * It's not accurate
+ */
+ .spdif_clk_48000 = 1,
+ .spdif_clkid = 0,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static void mx53_loco_usbh1_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(USB_PWREN, 1);
+ else
+ gpio_set_value(USB_PWREN, 0);
+}
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button loco_buttons[] = {
+ GPIO_BUTTON(MX53_nONKEY, KEY_POWER, 1, "power", 0),
+ GPIO_BUTTON(USER_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(USER_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static struct gpio_keys_platform_data loco_button_data = {
+ .buttons = loco_buttons,
+ .nbuttons = ARRAY_SIZE(loco_buttons),
+};
+
+static struct platform_device loco_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &loco_button_data,
+ }
+};
+
+static void __init loco_add_device_buttons(void)
+{
+ platform_device_register(&loco_button_device);
+}
+#else
+static void __init loco_add_device_buttons(void) {}
+#endif
+
+
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ struct tag *t;
+ struct tag *mem_tag = 0;
+ int total_mem = SZ_1G;
+ int left_mem = 0;
+ int gpu_mem = SZ_128M;
+ int fb_mem = SZ_32M;
+ char *str;
+
+ mxc_set_cpu_type(MXC_CPU_MX53);
+
+ for_each_tag(mem_tag, tags) {
+ if (mem_tag->hdr.tag == ATAG_MEM) {
+ total_mem = mem_tag->u.mem.size;
+ left_mem = total_mem - gpu_mem - fb_mem;
+ break;
+ }
+ }
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "mem=");
+ if (str != NULL) {
+ str += 4;
+ left_mem = memparse(str, &str);
+ if (left_mem == 0 || left_mem > total_mem)
+ left_mem = total_mem - gpu_mem - fb_mem;
+ }
+
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "gpu_memory=");
+ if (str != NULL) {
+ str += 11;
+ gpu_mem = memparse(str, &str);
+ }
+
+ break;
+ }
+ }
+
+ if (mem_tag) {
+ fb_mem = total_mem - left_mem - gpu_mem;
+ if (fb_mem < 0) {
+ gpu_mem = total_mem - left_mem;
+ fb_mem = 0;
+ }
+ mem_tag->u.mem.size = left_mem;
+
+ /*reserve memory for gpu*/
+ gpu_device.resource[5].start =
+ mem_tag->u.mem.start + left_mem;
+ gpu_device.resource[5].end =
+ gpu_device.resource[5].start + gpu_mem - 1;
+#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \
+ defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
+ if (fb_mem) {
+ mxcfb_resources[0].start =
+ gpu_device.resource[5].end + 1;
+ mxcfb_resources[0].end =
+ mxcfb_resources[0].start + fb_mem - 1;
+ } else {
+ mxcfb_resources[0].start = 0;
+ mxcfb_resources[0].end = 0;
+ }
+#endif
+ }
+}
+
+static void __init mx53_loco_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+ ARRAY_SIZE(mx53_loco_pads));
+
+ /* SD3 */
+ gpio_request(SD3_CD, "sd3-cd");
+ gpio_direction_input(SD3_CD);
+ gpio_request(SD3_WP, "sd3-wp");
+ gpio_direction_input(SD3_WP);
+
+ /* reset FEC PHY */
+ gpio_request(FEC_RST, "fec-rst");
+ gpio_direction_output(FEC_RST, 0);
+ gpio_set_value(FEC_RST, 0);
+ msleep(1);
+ gpio_set_value(FEC_RST, 1);
+
+ /* headphone_det_b */
+ gpio_request(HEADPHONE_DEC_B, "headphone-dec");
+ gpio_direction_input(HEADPHONE_DEC_B);
+
+ /* USB PWR enable */
+ gpio_request(USB_PWREN, "usb-pwr");
+ gpio_direction_output(USB_PWREN, 0);
+
+ /* Sii902x HDMI controller */
+ gpio_request(DISP0_RESET, "disp0-reset");
+ gpio_direction_output(DISP0_RESET, 0);
+ gpio_request(DISP0_DET_INT, "disp0-detect");
+ gpio_direction_input(DISP0_DET_INT);
+
+ /* LCD panel power enable */
+ gpio_request(DISP0_POWER_EN, "disp0-power-en");
+ gpio_direction_output(DISP0_POWER_EN, 1);
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ mxc_ipu_data.di_clk[0] = clk_get(NULL, "ipu_di0_clk");
+ mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk");
+ mxc_ipu_data.csi_clk[0] = clk_get(NULL, "ssi_ext1_clk");
+ mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk");
+ clk_put(mxc_spdif_data.spdif_core_clk);
+
+ mxcsdhc3_device.resource[2].start = IOMUX_TO_IRQ_V3(SD3_CD);
+ mxcsdhc3_device.resource[2].end = IOMUX_TO_IRQ_V3(SD3_CD);
+
+ mxc_cpu_common_init();
+ mx53_loco_io_init();
+
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+
+ mx53_loco_init_da9052();
+
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
+ mxc_register_device(&mxc_ldb_device, &ldb_data);
+ mxc_register_device(&mxc_tve_device, &tve_data);
+ mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
+ mxc_register_device(&gpu_device, &z160_revision);
+ mxc_register_device(&mxcscc_device, NULL);
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+ mxc_register_device(&mxc_iim_device, &iim_data);
+ mxc_register_device(&mxc_pwm2_device, NULL);
+ mxc_register_device(&mxc_pwm1_backlight_device, &mxc_pwm_backlight_data);
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc3_device, &mmc3_data);
+ mxc_register_device(&mxc_ssi1_device, NULL);
+ mxc_register_device(&mxc_ssi2_device, NULL);
+ mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
+ mxc_register_device(&ahci_fsl_device, &sata_data);
+ mxc_register_device(&mxc_fec_device, &fec_data);
+ /* ASRC is only available for MX53 TO2.0 */
+ if (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1) {
+ mxc_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ clk_put(mxc_asrc_data.asrc_core_clk);
+ mxc_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ clk_put(mxc_asrc_data.asrc_audio_clk);
+ mxc_register_device(&mxc_asrc_device, &mxc_asrc_data);
+ }
+
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+ mx5_usb_dr_init();
+ mx5_set_host1_vbus_func(mx53_loco_usbh1_vbus);
+ mx5_usbh1_init();
+ mxc_register_device(&mxc_v4l2_device, NULL);
+ mxc_register_device(&mxc_v4l2out_device, NULL);
+ loco_add_device_buttons();
+}
+
+static void __init mx53_loco_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx53_clocks_init(32768, 24000000, 0, 0);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(MX53_BASE_ADDR(UART1_BASE_ADDR), uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx53_loco_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX53_LOCO data structure.
+ */
+MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx53_loco_pmic_da9053.c b/arch/arm/mach-mx5/mx53_loco_pmic_da9053.c
new file mode 100644
index 000000000000..e11243b67043
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_loco_pmic_da9053.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+/*
+ * mx53_loco_pmic_da9053.c -- i.MX53 LOCO driver for pmic da9053
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/pm.h>
+#include <linux/mfd/da9052/led.h>
+#include <linux/mfd/da9052/tsi.h>
+#include <mach/irqs.h>
+#include <mach/iomux-mx53.h>
+
+#define DA9052_LDO(max, min, rname, suspend_mv) \
+{\
+ .constraints = {\
+ .name = (rname), \
+ .max_uV = (max) * 1000,\
+ .min_uV = (min) * 1000,\
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE\
+ |REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE,\
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,\
+ .state_mem = { \
+ .uV = suspend_mv * 1000, \
+ .mode = REGULATOR_MODE_NORMAL, \
+ .enabled = (0 == suspend_mv) ? 0 : 1, \
+ .disabled = 0, \
+ }, \
+ },\
+}
+
+/* currently the suspend_mv here takes no effects for DA9053
+preset-voltage have to be done in the latest stage during
+suspend*/
+static struct regulator_init_data da9052_regulators_init[] = {
+ DA9052_LDO(DA9052_LDO1_VOLT_UPPER,
+ DA9052_LDO1_VOLT_LOWER, "DA9052_LDO1", 1300),
+ DA9052_LDO(DA9052_LDO2_VOLT_UPPER,
+ DA9052_LDO2_VOLT_LOWER, "DA9052_LDO2", 1300),
+ DA9052_LDO(DA9052_LDO34_VOLT_UPPER,
+ DA9052_LDO34_VOLT_LOWER, "DA9052_LDO3", 3300),
+ DA9052_LDO(DA9052_LDO34_VOLT_UPPER,
+ DA9052_LDO34_VOLT_LOWER, "DA9052_LDO4", 2775),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO5", 1300),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO6", 1200),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO7", 2750),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO8", 1800),
+ DA9052_LDO(DA9052_LDO9_VOLT_UPPER,
+ DA9052_LDO9_VOLT_LOWER, "DA9052_LDO9", 2500),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO10", 1200),
+
+ /* BUCKS */
+ DA9052_LDO(DA9052_BUCK_CORE_PRO_VOLT_UPPER,
+ DA9052_BUCK_CORE_PRO_VOLT_LOWER, "DA9052_BUCK_CORE", 850),
+ DA9052_LDO(DA9052_BUCK_CORE_PRO_VOLT_UPPER,
+ DA9052_BUCK_CORE_PRO_VOLT_LOWER, "DA9052_BUCK_PRO", 950),
+ DA9052_LDO(DA9052_BUCK_MEM_VOLT_UPPER,
+ DA9052_BUCK_MEM_VOLT_LOWER, "DA9052_BUCK_MEM", 1500),
+ DA9052_LDO(DA9052_BUCK_PERI_VOLT_UPPER,
+ DA9052_BUCK_PERI_VOLT_LOWER, "DA9052_BUCK_PERI", 2500)
+};
+
+
+static struct da9052_tsi_platform_data da9052_tsi = {
+ .pen_up_interval = 50,
+ .tsi_delay_bit_shift = 6,
+ .tsi_skip_bit_shift = 3,
+ .num_gpio_tsi_register = 3,
+ .tsi_supply_voltage = 2500,
+ /* This is the DA9052 LDO number used for powering the TSI */
+ .tsi_ref_source = 9,
+ .max_tsi_delay = TSI_DELAY_4SLOTS,
+ .max_tsi_skip_slot = TSI_SKIP_330SLOTS,
+};
+
+static struct da9052_led_platform_data da9052_gpio_led[] = {
+ {
+ .id = DA9052_LED_4,
+ .name = "LED_GPIO14",
+ },
+ {
+ .id = DA9052_LED_5,
+ .name = "LED_GPIO15",
+ },
+};
+
+static struct da9052_leds_platform_data da9052_gpio_leds = {
+ .num_leds = ARRAY_SIZE(da9052_gpio_led),
+ .led = da9052_gpio_led,
+};
+
+
+static struct da9052_bat_platform_data da9052_bat = {
+ .sw_temp_control_en = 0,
+ .monitoring_interval = 500,
+ .sw_bat_temp_threshold = 60,
+ .sw_junc_temp_threshold = 120,
+ .hysteresis_window_size = 1,
+ .current_monitoring_window = 10,
+ .bat_with_no_resistor = 62,
+ .bat_capacity_limit_low = 4,
+ .bat_capacity_full = 100,
+ .bat_capacity_limit_high = 70,
+ .chg_hysteresis_const = 89,
+ .hysteresis_reading_interval = 1000,
+ .hysteresis_no_of_reading = 10,
+ .filter_size = 4,
+ .bat_volt_cutoff = 2800,
+ .vbat_first_valid_detect_iteration = 3,
+};
+
+static void da9052_init_ssc_cache(struct da9052 *da9052)
+{
+ unsigned char cnt;
+
+ /* First initialize all registers as Non-volatile */
+ for (cnt = 0; cnt < DA9052_REG_CNT; cnt++) {
+ da9052->ssc_cache[cnt].type = NON_VOLATILE;
+ da9052->ssc_cache[cnt].status = INVALID;
+ da9052->ssc_cache[cnt].val = 0;
+ }
+
+ /* Now selectively set type for all Volatile registers */
+ /* Reg 1 - 9 */
+ da9052->ssc_cache[DA9052_STATUSA_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_STATUSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_STATUSC_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_STATUSD_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTA_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTC_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTD_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_FAULTLOG_REG].type = VOLATILE;
+
+ /* Reg 15 */
+ da9052->ssc_cache[DA9052_CONTROLB_REG].type = VOLATILE;
+ /* Reg - 17 */
+ da9052->ssc_cache[DA9052_CONTROLD_REG].type = VOLATILE;
+ /* Reg - 60 */
+ da9052->ssc_cache[DA9052_SUPPLY_REG].type = VOLATILE;
+ /* Reg - 62 */
+ da9052->ssc_cache[DA9052_CHGBUCK_REG].type = VOLATILE;
+
+ /* Reg 67 - 68 */
+ da9052->ssc_cache[DA9052_INPUTCONT_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_CHGTIME_REG].type = VOLATILE;
+
+ /* Reg - 70 */
+ da9052->ssc_cache[DA9052_BOOST_REG].type = VOLATILE;
+
+ /* Reg - 81 */
+ da9052->ssc_cache[DA9052_ADCMAN_REG].type = VOLATILE;
+
+ /* Reg - 83 - 85 */
+ da9052->ssc_cache[DA9052_ADCRESL_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_ADCRESH_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_VDDRES_REG].type = VOLATILE;
+
+ /* Reg - 87 */
+ da9052->ssc_cache[DA9052_ICHGAV_REG].type = VOLATILE;
+
+ /* Reg - 90 */
+ da9052->ssc_cache[DA9052_TBATRES_REG].type = VOLATILE;
+
+ /* Reg - 95 */
+ da9052->ssc_cache[DA9052_ADCIN4RES_REG].type = VOLATILE;
+
+ /* Reg - 98 */
+ da9052->ssc_cache[DA9052_ADCIN5RES_REG].type = VOLATILE;
+
+ /* Reg - 101 */
+ da9052->ssc_cache[DA9052_ADCIN6RES_REG].type = VOLATILE;
+
+ /* Reg - 104 */
+ da9052->ssc_cache[DA9052_TJUNCRES_REG].type = VOLATILE;
+
+ /* Reg 106 - 110 */
+ da9052->ssc_cache[DA9052_TSICONTB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSIXMSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSIYMSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSILSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSIZMSB_REG].type = VOLATILE;
+
+ /* Reg 111 - 117 */
+ da9052->ssc_cache[DA9052_COUNTS_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTMI_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTH_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTD_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTMO_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTY_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_ALARMMI_REG].type = VOLATILE;
+
+ /* Reg 122 - 125 */
+ da9052->ssc_cache[DA9052_SECONDA_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_SECONDB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_SECONDC_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_SECONDD_REG].type = VOLATILE;
+
+ /* Following addresses are not assigned to any register */
+ da9052->ssc_cache[126].type = VOLATILE;
+ da9052->ssc_cache[127].type = VOLATILE;
+}
+
+
+#define MX53_LOCO_DA9052_IRQ (6*32 + 11) /* GPIO7_11 */
+
+static int __init loco_da9052_init(struct da9052 *da9052)
+{
+ /* Configuring for DA9052 interrupt servce */
+ /* s3c_gpio_setpull(DA9052_IRQ_PIN, S3C_GPIO_PULL_UP);*/
+
+ /* Set interrupt as LOW LEVEL interrupt source */
+ set_irq_type(IOMUX_TO_IRQ_V3(MX53_LOCO_DA9052_IRQ), IRQF_TRIGGER_LOW);
+
+ da9052_init_ssc_cache(da9052);
+
+ return 0;
+}
+
+static struct da9052_platform_data __initdata da9052_plat = {
+ .init = loco_da9052_init,
+ .num_regulators = ARRAY_SIZE(da9052_regulators_init),
+ .regulators = da9052_regulators_init,
+ .led_data = &da9052_gpio_leds,
+ .tsi_data = &da9052_tsi,
+ .bat_data = &da9052_bat,
+ /* .gpio_base = GPIO_BOARD_START, */
+};
+
+
+static struct i2c_board_info __initdata da9052_i2c_device = {
+ I2C_BOARD_INFO(DA9052_SSC_I2C_DEVICE_NAME, DA9052_I2C_ADDR >> 1),
+ .irq = IOMUX_TO_IRQ_V3(MX53_LOCO_DA9052_IRQ),
+ .platform_data = &da9052_plat,
+};
+
+int __init mx53_loco_init_da9052(void)
+{
+ return i2c_register_board_info(0, &da9052_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx53_smd.c b/arch/arm/mach-mx5/mx53_smd.c
new file mode 100644
index 000000000000..fd46e9de944a
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_smd.c
@@ -0,0 +1,1122 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/i2c/mpr.h>
+#include <linux/ata.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <linux/pmic_status.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/pwm_backlight.h>
+#include <linux/fec.h>
+#include <linux/ahci_platform.h>
+#include <linux/gpio_keys.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/keypad.h>
+#include <asm/mach/flash.h>
+#include <mach/memory.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+#include <mach/mxc_dvfs.h>
+#include <mach/iomux-mx53.h>
+#include <mach/i2c.h>
+#include <mach/mxc_iim.h>
+#include <mach/mxc_rfkill.h>
+
+#include "crm_regs.h"
+#include "devices.h"
+#include "usb.h"
+
+/*!
+ * @file mach-mx5/mx53_smd.c
+ *
+ * @brief This file contains MX53 smd board specific initialization routines.
+ *
+ * @ingroup MSL_MX53
+ */
+
+/* MX53 SMD GPIO PIN configurations */
+#define MX53_SMD_KEY_RESET (0*32 + 2) /* GPIO1_2 */
+#define MX53_SMD_SATA_CLK_GPEN (0*32 + 4) /* GPIO1_4 */
+#define MX53_SMD_PMIC_FAULT (0*32 + 5) /* GPIO1_5 */
+#define MX53_SMD_SYS_ON_OFF_CTL (0*32 + 7) /* GPIO1_7 */
+#define MX53_SMD_PMIC_ON_OFF_REQ (0*32 + 8) /* GPIO1_8 */
+
+#define MX53_SMD_FEC_INT (1*32 + 4) /* GPIO2_4 */
+#define MX53_SMD_HEADPHONE_DEC (1*32 + 5) /* GPIO2_5 */
+#define MX53_SMD_ZIGBEE_INT (1*32 + 6) /* GPIO2_6 */
+#define MX53_SMD_ZIGBEE_RESET_B (1*32 + 7) /* GPIO2_7 */
+#define MX53_SMD_GPS_RESET_B (1*32 + 12) /* GPIO2_12 */
+#define MX53_SMD_WAKEUP_ZIGBEE (1*32 + 13) /* GPIO2_13 */
+#define MX53_SMD_KEY_VOL_DOWN (1*32 + 14) /* GPIO2_14 */
+#define MX53_SMD_KEY_VOL_UP (1*32 + 15) /* GPIO2_15 */
+#define MX53_SMD_FEC_PWR_EN (1*32 + 16) /* GPIO_2_16 */
+#define MX53_SMD_LID_OPN_CLS_SW (1*32 + 23) /* GPIO_2_23 */
+#define MX53_SMD_GPS_PPS (1*32 + 24) /* GPIO_2_24 */
+
+#define MX53_SMD_DCDC1V8_EN (2*32 + 1) /*GPIO_3_1 */
+#define MX53_SMD_AUD_AMP_STBY_B (2*32 + 2) /*GPIO_3_2 */
+#define MX53_SMD_SATA_PWR_EN (2*32 + 3) /*GPIO_3_3 */
+#define MX53_SMD_TPM_OSC_EN (2*32 + 4) /*GPIO_3_4 */
+#define MX53_SMD_WLAN_PD (2*32 + 5) /*GPIO_3_5 */
+#define MX53_SMD_WiFi_BT_PWR_EN (2*32 + 10) /*GPIO_3_10 */
+#define MX53_SMD_RECOVERY_MODE_SW (2*32 + 11) /*GPIO_3_11 */
+#define MX53_SMD_USB_OTG_OC (2*32 + 12) /*GPIO_3_12 */
+#define MX53_SMD_SD1_CD (2*32 + 13) /*GPIO_3_13 */
+#define MX53_SMD_USB_HUB_RESET_B (2*32 + 14) /*GPIO_3_14 */
+#define MX53_SMD_eCOMPASS_INT (2*32 + 15) /*GPIO_3_15 */
+#define MX53_SMD_CAP_TCH_INT1 (2*32 + 20) /* GPIO_3_20 */
+#define MX53_SMD_BT_PRIORITY (2*32 + 21) /* GPIO_3_21 */
+#define MX53_SMD_ALS_INT (2*32 + 22) /* GPIO_3_22 */
+#define MX53_SMD_TPM_INT (2*32 + 26) /* GPIO_3_26 */
+#define MX53_SMD_MODEM_WKUP (2*32 + 27) /* GPIO_3_27 */
+#define MX53_SMD_BT_RESET (2*32 + 28) /* GPIO_3_28 */
+#define MX53_SMD_TPM_RST_B (2*32 + 29) /* GPIO_3_29 */
+#define MX53_SMD_CHRG_OR_CMOS (2*32 + 30) /* GPIO_3_30 */
+#define MX53_SMD_CAP_TCH_INT0 (2*32 + 31) /* GPIO_3_31 */
+
+#define MX53_SMD_CHA_ISET (3*32 + 2) /* GPIO_4_2 */
+#define MX53_SMD_SYS_EJECT (3*32 + 3) /* GPIO_4_3 */
+#define MX53_SMD_HDMI_CEC_D (3*32 + 4) /* GPIO_4_4 */
+
+#define MX53_SMD_MODEM_DISABLE_B (3*32 + 10) /* GPIO_4_10 */
+#define MX53_SMD_SD1_WP (3*32 + 11) /* GPIO_4_11 */
+#define MX53_SMD_DCDC5V_BB_EN (3*32 + 14) /* GPIO_4_14 */
+#define MX53_SMD_WLAN_HOST_WAKE (3*32 + 15) /* GPIO_4_15 */
+
+#define MX53_SMD_HDMI_RESET_B (4*32 + 0) /* GPIO_5_0 */
+#define MX53_SMD_MODEM_RESET_B (4*32 + 2) /* GPIO_5_2 */
+#define MX53_SMD_KEY_INT (4*32 + 4) /* GPIO_5_4 */
+
+#define MX53_SMD_CAP_TCH_FUN0 (5*32 + 6) /* GPIO_6_6 */
+#define MX53_SMD_CSI0_RST (5*32 + 9) /* GPIO_6_9 */
+#define MX53_SMD_CSI0_PWN (5*32 + 10) /* GPIO_6_10 */
+#define MX53_SMD_OSC_CKIH1_EN (5*32 + 11) /* GPIO_6_11 */
+#define MX53_SMD_HDMI_INT (5*32 + 12) /* GPIO_6_12 */
+#define MX53_SMD_LCD_PWR_EN (5*32 + 13) /* GPIO_6_13 */
+#define MX53_SMD_ACCL_INT1_IN (5*32 + 15) /* GPIO_6_15 */
+#define MX53_SMD_ACCL_INT2_IN (5*32 + 16) /* GPIO_6_16 */
+#define MX53_SMD_AC_IN (5*32 + 17) /* GPIO_6_17 */
+#define MX53_SMD_PWR_GOOD (5*32 + 18) /* GPIO_6_18 */
+
+#define MX53_SMD_CABC_EN0 (6*32 + 2) /* GPIO_7_2 */
+#define MX53_SMD_DOCK_DECTECT (6*32 + 3) /* GPIO_7_3 */
+#define MX53_SMD_FEC_RST (6*32 + 6) /* GPIO_7_6 */
+#define MX53_SMD_USER_DEG_CHG_NONE (6*32 + 7) /* GPIO_7_7 */
+#define MX53_SMD_USB_OTG_PWR_EN (6*32 + 8) /* GPIO_7_8 */
+#define MX53_SMD_DEVELOP_MODE_SW (6*32 + 9) /* GPIO_7_9 */
+#define MX53_SMD_CABC_EN1 (6*32 + 10) /* GPIO_7_10 */
+#define MX53_SMD_PMIC_INT (6*32 + 11) /* GPIO_7_11 */
+#define MX53_SMD_CAP_TCH_FUN1 (6*32 + 13) /* GPIO_7_13 */
+
+extern int __init mx53_smd_init_da9052(void);
+
+static struct pad_desc mx53_smd_pads[] = {
+ /* DI_VGA_HSYNC */
+ MX53_PAD_EIM_OE__DI1_PIN7,
+ /* HDMI reset */
+ MX53_PAD_EIM_WAIT__GPIO_5_0,
+ /* DI_VGA_VSYNC */
+ MX53_PAD_EIM_RW__DI1_PIN8,
+ /* CSPI1 */
+ MX53_PAD_EIM_EB2__CSPI_SS0,
+ MX53_PAD_EIM_D16__CSPI1_SCLK,
+ MX53_PAD_EIM_D17__CSPI1_MISO,
+ MX53_PAD_EIM_D18__CSPI1_MOSI,
+ MX53_PAD_EIM_D19__CSPI_SS1,
+ /* BT: UART3*/
+ MX53_PAD_EIM_D23__UART3_CTS,
+ MX53_PAD_EIM_D24_UART3_TXD,
+ MX53_PAD_EIM_EB3__UART3_RTS,
+ MX53_PAD_EIM_D25__UART3_RXD,
+ /* LID_OPN_CLS_SW*/
+ MX53_PAD_EIM_CS0__GPIO_2_23,
+ /* GPS_PPS */
+ MX53_PAD_EIM_CS1__GPIO_2_24,
+ /* FEC_PWR_EN */
+ MX53_PAD_EIM_A22__GPIO_2_16,
+ /* CAP_TCH_FUN0*/
+ MX53_PAD_EIM_A23__GPIO_6_6,
+ /* KEY_INT */
+ MX53_PAD_EIM_A24__GPIO_5_4,
+ /* MODEM_RESET_B */
+ MX53_PAD_EIM_A25__GPIO_5_2,
+ /* CAP_TCH_INT1 */
+ MX53_PAD_EIM_D20__GPIO_3_20,
+ /* BT_PRIORITY */
+ MX53_PAD_EIM_D21__GPIO_3_21,
+ /* ALS_INT */
+ MX53_PAD_EIM_D22__GPIO_3_22,
+ /* TPM_INT */
+ MX53_PAD_EIM_D26__GPIO_3_26,
+ /* MODEM_WKUP */
+ MX53_PAD_EIM_D27__GPIO_3_27,
+ /* BT_RESET */
+ MX53_PAD_EIM_D28__GPIO_3_28,
+ /* TPM_RST_B */
+ MX53_PAD_EIM_D29__GPIO_3_29,
+ /* CHARGER_NOW_OR_CMOS_RUN */
+ MX53_PAD_EIM_D30__GPIO_3_30,
+ /* CAP_TCH_INT0 */
+ MX53_PAD_EIM_D31__GPIO_3_31,
+ /* DCDC1V8_EN */
+ MX53_PAD_EIM_DA1__GPIO_3_1,
+ /* AUD_AMP_STBY_B */
+ MX53_PAD_EIM_DA2__GPIO_3_2,
+ /* SATA_PWR_EN */
+ MX53_PAD_EIM_DA3__GPIO_3_3,
+ /* TPM_OSC_EN */
+ MX53_PAD_EIM_DA4__GPIO_3_4,
+ /* WLAN_PD */
+ MX53_PAD_EIM_DA5__GPIO_3_5,
+ /* WiFi_BT_PWR_EN */
+ MX53_PAD_EIM_DA10__GPIO_3_10,
+ /* RECOVERY_MODE_SW */
+ MX53_PAD_EIM_DA11__GPIO_3_11,
+ /* USB_OTG_OC */
+ MX53_PAD_EIM_DA12__GPIO_3_12,
+ /* SD1_CD */
+ MX53_PAD_EIM_DA13__GPIO_3_13,
+ /* USB_HUB_RESET_B */
+ MX53_PAD_EIM_DA14__GPIO_3_14,
+ /* eCOMPASS_IN */
+ MX53_PAD_EIM_DA15__GPIO_3_15,
+ /* HDMI_INT */
+ MX53_PAD_NANDF_WE_B__GPIO_6_12,
+ /* LCD_PWR_EN */
+ MX53_PAD_NANDF_RE_B__GPIO_6_13,
+ /* CSI0_RST */
+ MX53_PAD_NANDF_WP_B__GPIO_6_9,
+ /* CSI0_PWN */
+ MX53_PAD_NANDF_RB0__GPIO_6_10,
+ /* OSC_CKIH1_EN */
+ MX53_PAD_NANDF_CS0__GPIO_6_11,
+ /* ACCL_INT1_IN */
+ MX53_PAD_NANDF_CS2__GPIO_6_15,
+ /* ACCL_INT2_IN */
+ MX53_PAD_NANDF_CS3__GPIO_6_16,
+ /* AUDMUX */
+ MX53_PAD_CSI0_D4__AUD3_TXC,
+ MX53_PAD_CSI0_D5__AUD3_TXD,
+ MX53_PAD_CSI0_D6__AUD3_TXFS,
+ MX53_PAD_CSI0_D7__AUD3_RXD,
+ /* I2C1 */
+ MX53_PAD_CSI0_D8__I2C1_SDA,
+ MX53_PAD_CSI0_D9__I2C1_SCL,
+ /* UART1 */
+ MX53_PAD_CSI0_D10__UART1_TXD,
+ MX53_PAD_CSI0_D11__UART1_RXD,
+ /* CSI0 */
+ MX53_PAD_CSI0_D12__CSI0_D12,
+ MX53_PAD_CSI0_D13__CSI0_D13,
+ MX53_PAD_CSI0_D14__CSI0_D14,
+ MX53_PAD_CSI0_D15__CSI0_D15,
+ MX53_PAD_CSI0_D16__CSI0_D16,
+ MX53_PAD_CSI0_D17__CSI0_D17,
+ MX53_PAD_CSI0_D18__CSI0_D18,
+ MX53_PAD_CSI0_D19__CSI0_D19,
+ MX53_PAD_CSI0_VSYNC__CSI0_VSYNC,
+ MX53_PAD_CSI0_MCLK__CSI0_HSYNC,
+ MX53_PAD_CSI0_PIXCLK__CSI0_PIXCLK,
+ /* DISPLAY */
+ MX53_PAD_DI0_DISP_CLK__DI0_DISP_CLK,
+ MX53_PAD_DI0_PIN15__DI0_PIN15,
+ MX53_PAD_DI0_PIN2__DI0_PIN2,
+ MX53_PAD_DI0_PIN3__DI0_PIN3,
+ MX53_PAD_DISP0_DAT0__DISP0_DAT0,
+ MX53_PAD_DISP0_DAT1__DISP0_DAT1,
+ MX53_PAD_DISP0_DAT2__DISP0_DAT2,
+ MX53_PAD_DISP0_DAT3__DISP0_DAT3,
+ MX53_PAD_DISP0_DAT4__DISP0_DAT4,
+ MX53_PAD_DISP0_DAT5__DISP0_DAT5,
+ MX53_PAD_DISP0_DAT6__DISP0_DAT6,
+ MX53_PAD_DISP0_DAT7__DISP0_DAT7,
+ MX53_PAD_DISP0_DAT8__DISP0_DAT8,
+ MX53_PAD_DISP0_DAT9__DISP0_DAT9,
+ MX53_PAD_DISP0_DAT10__DISP0_DAT10,
+ MX53_PAD_DISP0_DAT11__DISP0_DAT11,
+ MX53_PAD_DISP0_DAT12__DISP0_DAT12,
+ MX53_PAD_DISP0_DAT13__DISP0_DAT13,
+ MX53_PAD_DISP0_DAT14__DISP0_DAT14,
+ MX53_PAD_DISP0_DAT15__DISP0_DAT15,
+ MX53_PAD_DISP0_DAT16__DISP0_DAT16,
+ MX53_PAD_DISP0_DAT17__DISP0_DAT17,
+ MX53_PAD_DISP0_DAT18__DISP0_DAT18,
+ MX53_PAD_DISP0_DAT19__DISP0_DAT19,
+ MX53_PAD_DISP0_DAT20__DISP0_DAT20,
+ MX53_PAD_DISP0_DAT21__DISP0_DAT21,
+ MX53_PAD_DISP0_DAT22__DISP0_DAT22,
+ MX53_PAD_DISP0_DAT23__DISP0_DAT23,
+ /* FEC */
+ MX53_PAD_FEC_MDC__FEC_MDC,
+ MX53_PAD_FEC_MDIO__FEC_MDIO,
+ MX53_PAD_FEC_REF_CLK__FEC_REF_CLK,
+ MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+ MX53_PAD_FEC_CRS_DV__FEC_CRS_DV,
+ MX53_PAD_FEC_RXD1__FEC_RXD1,
+ MX53_PAD_FEC_RXD0__FEC_RXD0,
+ MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+ MX53_PAD_FEC_TXD1__FEC_TXD1,
+ MX53_PAD_FEC_TXD0__FEC_TXD0,
+ /* AUDMUX5 */
+ MX53_PAD_KEY_COL0__AUD5_TXC,
+ MX53_PAD_KEY_ROW0__AUD5_TXD,
+ MX53_PAD_KEY_COL1__AUD5_TXFS,
+ MX53_PAD_KEY_ROW1__AUD5_RXD,
+ /* MODEM_DISABLE_B */
+ MX53_PAD_KEY_COL2__GPIO_4_10,
+ /* SD1_WP */
+ MX53_PAD_KEY_ROW2__GPIO_4_11,
+ /* I2C2 */
+ MX53_PAD_KEY_COL3__I2C2_SCL,
+ MX53_PAD_KEY_ROW3__I2C2_SDA,
+ /* DCDC5V_BB_EN */
+ MX53_PAD_KEY_COL4__GPIO_4_14,
+ /* WLAN_HOST_WAKE */
+ MX53_PAD_KEY_ROW4__GPIO_4_15,
+ /* SD1 */
+ MX53_PAD_SD1_CMD__SD1_CMD,
+ MX53_PAD_SD1_CLK__SD1_CLK,
+ MX53_PAD_SD1_DATA0__SD1_DATA0,
+ MX53_PAD_SD1_DATA1__SD1_DATA1,
+ MX53_PAD_SD1_DATA2__SD1_DATA2,
+ MX53_PAD_SD1_DATA3__SD1_DATA3,
+ /* SD2 */
+ MX53_PAD_SD2_CMD__SD2_CMD,
+ MX53_PAD_SD2_CLK__SD2_CLK,
+ MX53_PAD_SD2_DATA0__SD2_DAT0,
+ MX53_PAD_SD2_DATA1__SD2_DAT1,
+ MX53_PAD_SD2_DATA2__SD2_DAT2,
+ MX53_PAD_SD2_DATA3__SD2_DAT3,
+ /* UART2 */
+ MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
+ MX53_PAD_ATA_DMARQ__UART2_TXD,
+ /* DEVELOP_MODE_SW */
+ MX53_PAD_ATA_CS_0__GPIO_7_9,
+ /* CABC_EN1 */
+ MX53_PAD_ATA_CS_1__GPIO_7_10,
+ /* FEC_nRST */
+ MX53_PAD_ATA_DA_0__GPIO_7_6,
+ /* USER_DEBUG_OR_CHARGER_DONE */
+ MX53_PAD_ATA_DA_1__GPIO_7_7,
+ /* USB_OTG_PWR_EN */
+ MX53_PAD_ATA_DA_2__GPIO_7_8,
+ /* SD3 */
+ MX53_PAD_ATA_DATA8__SD3_DAT0,
+ MX53_PAD_ATA_DATA9__SD3_DAT1,
+ MX53_PAD_ATA_DATA10__SD3_DAT2,
+ MX53_PAD_ATA_DATA11__SD3_DAT3,
+ MX53_PAD_ATA_DATA0__SD3_DAT4,
+ MX53_PAD_ATA_DATA1__SD3_DAT5,
+ MX53_PAD_ATA_DATA2__SD3_DAT6,
+ MX53_PAD_ATA_DATA3__SD3_DAT7,
+ MX53_PAD_ATA_IORDY__SD3_CLK,
+ MX53_PAD_ATA_RESET_B__SD3_CMD,
+ /* FEC_nINT */
+ MX53_PAD_ATA_DATA4__GPIO_2_4,
+ /* HEADPHONE DET*/
+ MX53_PAD_ATA_DATA5__GPIO_2_5,
+ /* ZigBee_INT*/
+ MX53_PAD_ATA_DATA6__GPIO_2_6,
+ /* ZigBee_RESET_B */
+ MX53_PAD_ATA_DATA7__GPIO_2_7,
+ /* GPS_RESET_B*/
+ MX53_PAD_ATA_DATA12__GPIO_2_12,
+ /* WAKEUP_ZigBee */
+ MX53_PAD_ATA_DATA13__GPIO_2_13,
+ /* KEY_VOL- */
+ MX53_PAD_ATA_DATA14__GPIO_2_14,
+ /* KEY_VOL+ */
+ MX53_PAD_ATA_DATA15__GPIO_2_15,
+ /* DOCK_DECTECT */
+ MX53_PAD_ATA_DIOR__GPIO_7_3,
+ /* AC_IN */
+ MX53_PAD_ATA_DIOW__GPIO_6_17,
+ /* PWR_GOOD */
+ MX53_PAD_ATA_DMACK__GPIO_6_18,
+ /* CABC_EN0 */
+ MX53_PAD_ATA_INTRQ__GPIO_7_2,
+ MX53_PAD_GPIO_0__SSI_EXT1_CLK,
+ MX53_PAD_GPIO_1__PWMO,
+ /* KEY_RESET */
+ MX53_PAD_GPIO_2__GPIO_1_2,
+ /* I2C3 */
+ MX53_PAD_GPIO_3__I2C3_SCL,
+ MX53_PAD_GPIO_6__I2C3_SDA,
+ /* SATA_CLK_GPEN */
+ MX53_PAD_GPIO_4__GPIO_1_4,
+ /* PMIC_FAULT */
+ MX53_PAD_GPIO_5__GPIO_1_5,
+ /* SYS_ON_OFF_CTL */
+ MX53_PAD_GPIO_7__GPIO_1_7,
+ /* PMIC_ON_OFF_REQ */
+ MX53_PAD_GPIO_8__GPIO_1_8,
+ /* CHA_ISET */
+ MX53_PAD_GPIO_12__GPIO_4_2,
+ /* SYS_EJECT */
+ MX53_PAD_GPIO_13__GPIO_4_3,
+ /* HDMI_CEC_D */
+ MX53_PAD_GPIO_14__GPIO_4_4,
+ /* PMIC_INT */
+ MX53_PAD_GPIO_16__GPIO_7_11,
+ MX53_PAD_GPIO_17__SPDIF_OUT1,
+ /* CAP_TCH_FUN1 */
+ MX53_PAD_GPIO_18__GPIO_7_13,
+ /* LVDS */
+ MX53_PAD_LVDS0_TX3_P__LVDS0_TX3,
+ MX53_PAD_LVDS0_CLK_P__LVDS0_CLK,
+ MX53_PAD_LVDS0_TX2_P__LVDS0_TX2,
+ MX53_PAD_LVDS0_TX1_P__LVDS0_TX1,
+ MX53_PAD_LVDS0_TX0_P__LVDS0_TX0,
+ MX53_PAD_LVDS1_TX3_P__LVDS1_TX3,
+ MX53_PAD_LVDS1_TX2_P__LVDS1_TX2,
+ MX53_PAD_LVDS1_CLK_P__LVDS1_CLK,
+ MX53_PAD_LVDS1_TX1_P__LVDS1_TX1,
+ MX53_PAD_LVDS1_TX0_P__LVDS1_TX0,
+};
+
+static struct fb_videomode video_modes[] = {
+ {
+ /* 800x480 @ 57 Hz , pixel clk @ 27MHz */
+ "CLAA-WVGA", 57, 800, 480, 37037, 40, 60, 10, 10, 20, 10,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ /* 1600x1200 @ 60 Hz 162M pixel clk*/
+ "UXGA", 60, 1600, 1200, 6172,
+ 304, 64,
+ 1, 46,
+ 192, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ /* 2 LVDS modes, had better remove from here */
+ {
+ "1080P60", 60, 1920, 1080, 7692,
+ 100, 40,
+ 30, 3,
+ 10, 2,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+ {
+ "XGA", 60, 1024, 768, 15385,
+ 220, 40,
+ 21, 7,
+ 60, 10,
+ 0,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct platform_pwm_backlight_data mxc_pwm_backlight_data = {
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .dft_brightness = 128,
+ .pwm_period_ns = 50000,
+};
+
+extern void mx5_ipu_reset(void);
+static struct mxc_ipu_config mxc_ipu_data = {
+ .rev = 3,
+ .reset = mx5_ipu_reset,
+};
+
+extern void mx5_vpu_reset(void);
+static struct mxc_vpu_platform_data mxc_vpu_data = {
+ .reset = mx5_vpu_reset,
+};
+
+static struct fec_platform_data fec_data = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+
+static struct mxc_spi_master mxcspi1_data = {
+ .maxchipselect = 4,
+ .spi_version = 23,
+ .chipselect_active = NULL,
+ .chipselect_inactive = NULL,
+};
+
+static struct mxc_dvfs_platform_data dvfs_core_data = {
+ .reg_id = "DA9052_BUCK_CORE",
+ .clk1_id = "cpu_clk",
+ .clk2_id = "gpc_dvfs_clk",
+ .gpc_cntr_offset = MXC_GPC_CNTR_OFFSET,
+ .gpc_vcr_offset = MXC_GPC_VCR_OFFSET,
+ .ccm_cdcr_offset = MXC_CCM_CDCR_OFFSET,
+ .ccm_cacrr_offset = MXC_CCM_CACRR_OFFSET,
+ .ccm_cdhipr_offset = MXC_CCM_CDHIPR_OFFSET,
+ .prediv_mask = 0x1F800,
+ .prediv_offset = 11,
+ .prediv_val = 3,
+ .div3ck_mask = 0xE0000000,
+ .div3ck_offset = 29,
+ .div3ck_val = 2,
+ .emac_val = 0x08,
+ .upthr_val = 25,
+ .dnthr_val = 9,
+ .pncthr_val = 33,
+ .upcnt_val = 10,
+ .dncnt_val = 10,
+ .delay_time = 30,
+};
+
+static struct mxc_bus_freq_platform_data bus_freq_data = {
+ .gp_reg_id = "DA9052_BUCK_CORE",
+ .lp_reg_id = "DA9052_BUCK_PRO",
+};
+
+static struct tve_platform_data tve_data = {
+ .dac_reg = "DA9052_LDO7",
+};
+
+static struct ldb_platform_data ldb_data = {
+ .ext_ref = 1,
+};
+
+static void mxc_iim_enable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg |= 0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static void mxc_iim_disable_fuse(void)
+{
+ u32 reg;
+
+ if (!ccm_base)
+ return;
+ /* enable fuse blown */
+ reg = readl(ccm_base + 0x64);
+ reg &= ~0x10;
+ writel(reg, ccm_base + 0x64);
+}
+
+static struct mxc_iim_data iim_data = {
+ .bank_start = MXC_IIM_MX53_BANK_START_ADDR,
+ .bank_end = MXC_IIM_MX53_BANK_END_ADDR,
+ .enable_fuse = mxc_iim_enable_fuse,
+ .disable_fuse = mxc_iim_disable_fuse,
+};
+
+static struct resource mxcfb_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct mxc_fb_platform_data fb_data[] = {
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_RGB565,
+ .mode_str = "CLAA-WVGA",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+ {
+ .interface_pix_fmt = IPU_PIX_FMT_GBR24,
+ .mode_str = "1024x768M-16@60",
+ .mode = video_modes,
+ .num_modes = ARRAY_SIZE(video_modes),
+ },
+};
+
+extern int primary_di;
+static int __init mxc_init_fb(void)
+{
+ if (!machine_is_mx53_smd())
+ return 0;
+
+ if (primary_di) {
+ printk(KERN_INFO "DI1 is primary\n");
+ /* DI1 -> DP-BG channel: */
+ mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[1].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+
+ /* DI0 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+ } else {
+ printk(KERN_INFO "DI0 is primary\n");
+
+ /* DI0 -> DP-BG channel: */
+ mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
+ mxc_fb_devices[0].resource = mxcfb_resources;
+ mxc_register_device(&mxc_fb_devices[0], &fb_data[0]);
+
+ /* DI1 -> DC channel: */
+ mxc_register_device(&mxc_fb_devices[1], &fb_data[1]);
+ }
+
+ /*
+ * DI0/1 DP-FG channel:
+ */
+ mxc_register_device(&mxc_fb_devices[2], NULL);
+
+ return 0;
+}
+device_initcall(mxc_init_fb);
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX53_SMD_HDMI_RESET_B, 0);
+ msleep(10);
+ gpio_set_value(MX53_SMD_HDMI_RESET_B, 1);
+ msleep(10);
+}
+
+static struct mxc_lcd_platform_data sii902x_hdmi_data = {
+ .reset = sii902x_hdmi_reset,
+};
+
+static struct imxi2c_platform_data mxci2c_data = {
+ .bitrate = 100000,
+};
+
+static struct mxc_camera_platform_data camera_data = {
+ .analog_regulator = "DA9052_LDO7",
+ .core_regulator = "DA9052_LDO9",
+ .mclk = 24000000,
+ .csi = 0,
+};
+
+static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
+ {
+ .type = "mma8451",
+ .addr = 0x1C,
+ },
+ {
+ .type = "ov3640",
+ .addr = 0x3C,
+ .platform_data = (void *)&camera_data,
+ },
+};
+
+static u16 smd_touchkey_martix[4] = {
+ KEY_BACK, KEY_HOME, KEY_MENU, KEY_SEARCH,
+};
+
+static struct mpr121_platform_data mpr121_keyboard_platdata = {
+ .keycount = ARRAY_SIZE(smd_touchkey_martix),
+ .vdd_uv = 3300000,
+ .matrix = smd_touchkey_martix,
+};
+
+static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "mpr121_touchkey",
+ .addr = 0x5a,
+ .irq = IOMUX_TO_IRQ_V3(MX53_SMD_KEY_INT),
+ .platform_data = &mpr121_keyboard_platdata,
+ },
+};
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake) \
+{ \
+ .gpio = gpio_num, \
+ .type = EV_KEY, \
+ .code = ev_code, \
+ .active_low = act_low, \
+ .desc = "btn " descr, \
+ .wakeup = wake, \
+}
+
+static struct gpio_keys_button smd_buttons[] = {
+ GPIO_BUTTON(MX53_SMD_KEY_VOL_UP, KEY_VOLUMEUP, 1, "volume-up", 0),
+ GPIO_BUTTON(MX53_SMD_KEY_VOL_DOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static struct gpio_keys_platform_data smd_button_data = {
+ .buttons = smd_buttons,
+ .nbuttons = ARRAY_SIZE(smd_buttons),
+};
+
+static struct platform_device smd_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &smd_button_data,
+ }
+};
+
+static void __init smd_add_device_buttons(void)
+{
+ platform_device_register(&smd_button_device);
+}
+#else
+static void __init smd_add_device_buttons(void) {}
+#endif
+
+static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
+ {
+ .type = "sii902x",
+ .addr = 0x39,
+ .irq = IOMUX_TO_IRQ_V3(MX53_SMD_HDMI_INT),
+ .platform_data = &sii902x_hdmi_data,
+ },
+};
+
+static void mx53_gpio_usbotg_driver_vbus(bool on)
+{
+ if (on)
+ gpio_set_value(MX53_SMD_USB_OTG_PWR_EN, 1);
+ else
+ gpio_set_value(MX53_SMD_USB_OTG_PWR_EN, 0);
+}
+
+static int sdhc_write_protect(struct device *dev)
+{
+ int ret = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ ret = gpio_get_value(MX53_SMD_SD1_WP);
+
+ return ret;
+}
+
+static unsigned int sdhc_get_card_det_status(struct device *dev)
+{
+ int ret = 0;
+
+ if (to_platform_device(dev)->id == 0)
+ ret = gpio_get_value(MX53_SMD_SD1_CD);
+
+ return ret;
+}
+
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 0,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 1,
+ .clock_mmc = "esdhc_clk",
+ .power_mmc = NULL,
+};
+
+static struct mxc_mmc_platform_data mmc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30
+ | MMC_VDD_31_32,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | MMC_CAP_DATA_DDR,
+ .min_clk = 400000,
+ .max_clk = 50000000,
+ .card_inserted_state = 1,
+ .clock_mmc = "esdhc_clk",
+};
+
+
+static int mxc_sgtl5000_amp_enable(int enable)
+{
+ gpio_request(MX53_SMD_AUD_AMP_STBY_B, "amp-standby");
+ if (enable)
+ gpio_direction_output(MX53_SMD_AUD_AMP_STBY_B, 1);
+ else
+ gpio_direction_output(MX53_SMD_AUD_AMP_STBY_B, 0);
+ gpio_free(MX53_SMD_AUD_AMP_STBY_B);
+ return 0;
+}
+
+static int headphone_det_status(void)
+{
+ return (gpio_get_value(MX53_SMD_HEADPHONE_DEC) == 0);
+}
+
+static int mxc_sgtl5000_init(void);
+
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 1,
+ .src_port = 2,
+ .ext_port = 5,
+ .hp_irq = IOMUX_TO_IRQ_V3(MX53_SMD_HEADPHONE_DEC),
+ .hp_status = headphone_det_status,
+ .amp_enable = mxc_sgtl5000_amp_enable,
+ .init = mxc_sgtl5000_init,
+};
+
+static int mxc_sgtl5000_init(void)
+{
+ sgtl5000_data.sysclk = 22579200;
+ return 0;
+}
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+};
+
+static struct mxc_asrc_platform_data mxc_asrc_data = {
+ .channel_bits = 4,
+ .clk_map_ver = 2,
+};
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 0, /* Souce from CKIH1 for 44.1K */
+ /* Source from CCM spdif_clk (24M) for 48k and 32k
+ * It's not accurate
+ */
+ .spdif_clk_48000 = 1,
+ .spdif_clkid = 0,
+ .spdif_clk = NULL, /* spdif bus clk */
+};
+
+static void mx53_smd_bt_reset(void)
+{
+ gpio_request(MX53_SMD_BT_RESET, "bt-reset");
+ gpio_direction_output(MX53_SMD_BT_RESET, 0);
+ /* pull down reset pin at least >5ms */
+ mdelay(6);
+ /* pull up after power supply BT */
+ gpio_set_value(MX53_SMD_BT_RESET, 1);
+ gpio_free(MX53_SMD_BT_RESET);
+ msleep(100);
+ /* Bluetooth need some time to reset */
+}
+
+static int mx53_smd_bt_power_change(int status)
+{
+ if (status)
+ mx53_smd_bt_reset();
+
+ return 0;
+}
+
+static struct platform_device mxc_bt_rfkill = {
+ .name = "mxc_bt_rfkill",
+};
+
+static struct mxc_bt_rfkill_platform_data mxc_bt_rfkill_data = {
+ .power_change = mx53_smd_bt_power_change,
+};
+
+static void mx53_smd_power_off(void)
+{
+ gpio_request(MX53_SMD_SYS_ON_OFF_CTL, "power-off");
+ gpio_set_value(MX53_SMD_SYS_ON_OFF_CTL, 0);
+}
+/*!
+ * Board specific fixup function. It is called by \b setup_arch() in
+ * setup.c file very early on during kernel starts. It allows the user to
+ * statically fill in the proper values for the passed-in parameters. None of
+ * the parameters is used currently.
+ *
+ * @param desc pointer to \b struct \b machine_desc
+ * @param tags pointer to \b struct \b tag
+ * @param cmdline pointer to the command line
+ * @param mi pointer to \b struct \b meminfo
+ */
+static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
+ char **cmdline, struct meminfo *mi)
+{
+ struct tag *t;
+ struct tag *mem_tag = 0;
+ int total_mem = SZ_1G;
+ int left_mem = 0;
+ int gpu_mem = SZ_128M;
+ int fb_mem = SZ_32M;
+ char *str;
+
+ mxc_set_cpu_type(MXC_CPU_MX53);
+
+ for_each_tag(mem_tag, tags) {
+ if (mem_tag->hdr.tag == ATAG_MEM) {
+ total_mem = mem_tag->u.mem.size;
+ left_mem = total_mem - gpu_mem - fb_mem;
+ break;
+ }
+ }
+
+ for_each_tag(t, tags) {
+ if (t->hdr.tag == ATAG_CMDLINE) {
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "mem=");
+ if (str != NULL) {
+ str += 4;
+ left_mem = memparse(str, &str);
+ if (left_mem == 0 || left_mem > total_mem)
+ left_mem = total_mem - gpu_mem - fb_mem;
+ }
+
+ str = t->u.cmdline.cmdline;
+ str = strstr(str, "gpu_memory=");
+ if (str != NULL) {
+ str += 11;
+ gpu_mem = memparse(str, &str);
+ }
+
+ break;
+ }
+ }
+
+ if (mem_tag) {
+ fb_mem = total_mem - left_mem - gpu_mem;
+ if (fb_mem < 0) {
+ gpu_mem = total_mem - left_mem;
+ fb_mem = 0;
+ }
+ mem_tag->u.mem.size = left_mem;
+
+ /*reserve memory for gpu*/
+ gpu_device.resource[5].start =
+ mem_tag->u.mem.start + left_mem;
+ gpu_device.resource[5].end =
+ gpu_device.resource[5].start + gpu_mem - 1;
+#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \
+ defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
+ if (fb_mem) {
+ mxcfb_resources[0].start =
+ gpu_device.resource[5].end + 1;
+ mxcfb_resources[0].end =
+ mxcfb_resources[0].start + fb_mem - 1;
+ } else {
+ mxcfb_resources[0].start = 0;
+ mxcfb_resources[0].end = 0;
+ }
+#endif
+ }
+}
+
+static void __init mx53_smd_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+ ARRAY_SIZE(mx53_smd_pads));
+
+ /* SD1 CD */
+ gpio_request(MX53_SMD_SD1_CD, "sd1-cd");
+ gpio_direction_input(MX53_SMD_SD1_CD);
+ /* SD1 WP */
+ gpio_request(MX53_SMD_SD1_WP, "sd1-wp");
+ gpio_direction_input(MX53_SMD_SD1_WP);
+
+ /* reset FEC PHY */
+ gpio_request(MX53_SMD_FEC_RST, "fec-rst");
+ gpio_direction_output(MX53_SMD_FEC_RST, 0);
+ gpio_set_value(MX53_SMD_FEC_RST, 0);
+ msleep(1);
+ gpio_set_value(MX53_SMD_FEC_RST, 1);
+
+ /* headphone_det_b */
+ gpio_request(MX53_SMD_HEADPHONE_DEC, "headphone-dec");
+ gpio_direction_input(MX53_SMD_HEADPHONE_DEC);
+
+ /* USB PWR enable */
+ gpio_request(MX53_SMD_USB_OTG_PWR_EN, "usb-pwr");
+ gpio_direction_output(MX53_SMD_USB_OTG_PWR_EN, 0);
+
+ /* Enable MX53_SMD_DCDC1V8_EN */
+ gpio_request(MX53_SMD_DCDC1V8_EN, "dcdc1v8-en");
+ gpio_direction_output(MX53_SMD_DCDC1V8_EN, 1);
+ gpio_set_value(MX53_SMD_DCDC1V8_EN, 1);
+
+ /* Enable OSC_CKIH1_EN for audio */
+ gpio_request(MX53_SMD_OSC_CKIH1_EN, "osc-en");
+ gpio_direction_output(MX53_SMD_OSC_CKIH1_EN, 1);
+ gpio_set_value(MX53_SMD_OSC_CKIH1_EN, 1);
+
+ /* Sii902x HDMI controller */
+ gpio_request(MX53_SMD_HDMI_RESET_B, "disp0-pwr-en");
+ gpio_direction_output(MX53_SMD_HDMI_RESET_B, 0);
+ gpio_request(MX53_SMD_HDMI_INT, "disp0-det-int");
+ gpio_direction_input(MX53_SMD_HDMI_INT);
+
+ /* MPR121 capacitive button */
+ gpio_request(MX53_SMD_KEY_INT, "cap-button-irq");
+ gpio_direction_input(MX53_SMD_KEY_INT);
+ gpio_free(MX53_SMD_KEY_INT);
+
+ /* Camera reset */
+ gpio_request(MX53_SMD_CSI0_RST, "cam-reset");
+ gpio_set_value(MX53_SMD_CSI0_RST, 1);
+
+ /* Camera power down */
+ gpio_request(MX53_SMD_CSI0_PWN, "cam-pwdn");
+ gpio_direction_output(MX53_SMD_CSI0_PWN, 1);
+ msleep(1);
+ gpio_set_value(MX53_SMD_CSI0_PWN, 0);
+
+ /* Enable WiFi/BT Power*/
+ gpio_request(MX53_SMD_WiFi_BT_PWR_EN, "bt-wifi-pwren");
+ gpio_direction_output(MX53_SMD_WiFi_BT_PWR_EN, 1);
+
+ /* WiFi Power up sequence */
+ gpio_request(MX53_SMD_WLAN_PD, "wifi-pd");
+ gpio_direction_output(MX53_SMD_WLAN_PD, 1);
+ mdelay(1);
+ gpio_set_value(MX53_SMD_WLAN_PD, 0);
+ mdelay(5);
+ gpio_set_value(MX53_SMD_WLAN_PD, 1);
+ gpio_free(MX53_SMD_WLAN_PD);
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ mxc_ipu_data.di_clk[0] = clk_get(NULL, "ipu_di0_clk");
+ mxc_ipu_data.di_clk[1] = clk_get(NULL, "ipu_di1_clk");
+ mxc_ipu_data.csi_clk[0] = clk_get(NULL, "ssi_ext1_clk");
+ mxc_spdif_data.spdif_core_clk = clk_get(NULL, "spdif_xtal_clk");
+ clk_put(mxc_spdif_data.spdif_core_clk);
+
+ mxcsdhc1_device.resource[2].start = IOMUX_TO_IRQ_V3(MX53_SMD_SD1_CD);
+ mxcsdhc1_device.resource[2].end = IOMUX_TO_IRQ_V3(MX53_SMD_SD1_CD);
+
+ mxc_cpu_common_init();
+ mx53_smd_io_init();
+
+ pm_power_off = mx53_smd_power_off;
+ mxc_register_device(&mxc_dma_device, NULL);
+ mxc_register_device(&mxc_wdt_device, NULL);
+ mxc_register_device(&mxcspi1_device, &mxcspi1_data);
+ mxc_register_device(&mxci2c_devices[0], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[1], &mxci2c_data);
+ mxc_register_device(&mxci2c_devices[2], &mxci2c_data);
+ mx53_smd_init_da9052();
+
+ mxc_register_device(&mxc_rtc_device, NULL);
+ mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
+ mxc_register_device(&mxc_ldb_device, &ldb_data);
+ mxc_register_device(&mxc_tve_device, &tve_data);
+ mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
+ mxc_register_device(&gpu_device, &z160_revision);
+ mxc_register_device(&mxcscc_device, NULL);
+ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data);
+ mxc_register_device(&busfreq_device, &bus_freq_data);
+ mxc_register_device(&mxc_iim_device, &iim_data);
+ mxc_register_device(&mxc_pwm2_device, NULL);
+ mxc_register_device(&mxc_pwm1_backlight_device, &mxc_pwm_backlight_data);
+ mxc_register_device(&mxcsdhc1_device, &mmc1_data);
+ mxc_register_device(&mxcsdhc2_device, &mmc2_data);
+ mxc_register_device(&mxcsdhc3_device, &mmc3_data);
+ mxc_register_device(&mxc_ssi1_device, NULL);
+ mxc_register_device(&mxc_ssi2_device, NULL);
+ mxc_register_device(&mxc_alsa_spdif_device, &mxc_spdif_data);
+ mxc_register_device(&ahci_fsl_device, &sata_data);
+ /* AHCI SATA PWR EN(DCDC_5V, DCDC_3V3_BB) on SATA bus */
+ gpio_request(MX53_SMD_SATA_PWR_EN, "sata-pwr-en");
+ gpio_direction_output(MX53_SMD_SATA_PWR_EN, 1);
+
+ mxc_register_device(&mxc_fec_device, &fec_data);
+ /* ASRC is only available for MX53 TO2.0 */
+ if (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1) {
+ mxc_asrc_data.asrc_core_clk = clk_get(NULL, "asrc_clk");
+ clk_put(mxc_asrc_data.asrc_core_clk);
+ mxc_asrc_data.asrc_audio_clk = clk_get(NULL, "asrc_serial_clk");
+ clk_put(mxc_asrc_data.asrc_audio_clk);
+ mxc_register_device(&mxc_asrc_device, &mxc_asrc_data);
+ }
+
+ i2c_register_board_info(0, mxc_i2c0_board_info,
+ ARRAY_SIZE(mxc_i2c0_board_info));
+ i2c_register_board_info(1, mxc_i2c1_board_info,
+ ARRAY_SIZE(mxc_i2c1_board_info));
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+
+ mxc_register_device(&mxc_sgtl5000_device, &sgtl5000_data);
+ mx5_set_otghost_vbus_func(mx53_gpio_usbotg_driver_vbus);
+ mx5_usb_dr_init();
+ mx5_usbh1_init();
+ mxc_register_device(&mxc_v4l2_device, NULL);
+ mxc_register_device(&mxc_v4l2out_device, NULL);
+ mxc_register_device(&mxc_bt_rfkill, &mxc_bt_rfkill_data);
+ smd_add_device_buttons();
+}
+
+static void __init mx53_smd_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx53_clocks_init(32768, 24000000, 22579200, 0);
+
+ uart_clk = clk_get_sys("mxcintuart.0", NULL);
+ early_console_setup(MX53_BASE_ADDR(UART1_BASE_ADDR), uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx53_smd_timer_init,
+};
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX53_SMD data structure.
+ */
+MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .fixup = fixup_mxc_board,
+ .map_io = mx5_map_io,
+ .init_irq = mx5_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/mx53_smd_pmic_da9053.c b/arch/arm/mach-mx5/mx53_smd_pmic_da9053.c
new file mode 100644
index 000000000000..e6cf9e380f30
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_smd_pmic_da9053.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+/*
+ * mx53_smd_pmic_da9053.c -- i.MX53 SMD driver for pmic da9053
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/pm.h>
+#include <linux/mfd/da9052/led.h>
+#include <linux/mfd/da9052/tsi.h>
+#include <mach/irqs.h>
+#include <mach/iomux-mx53.h>
+
+#define DA9052_LDO(max, min, rname, suspend_mv) \
+{\
+ .constraints = {\
+ .name = (rname), \
+ .max_uV = (max) * 1000,\
+ .min_uV = (min) * 1000,\
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE\
+ |REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE,\
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,\
+ .state_mem = { \
+ .uV = suspend_mv * 1000, \
+ .mode = REGULATOR_MODE_NORMAL, \
+ .enabled = (0 == suspend_mv) ? 0 : 1, \
+ .disabled = 0, \
+ }, \
+ },\
+}
+
+/* currently the suspend_mv field here takes no effects for DA9053
+preset-voltage have to be done in the latest stage during
+suspend*/
+static struct regulator_init_data da9052_regulators_init[] = {
+ DA9052_LDO(DA9052_LDO1_VOLT_UPPER,
+ DA9052_LDO1_VOLT_LOWER, "DA9052_LDO1", 1300),
+ DA9052_LDO(DA9052_LDO2_VOLT_UPPER,
+ DA9052_LDO2_VOLT_LOWER, "DA9052_LDO2", 1300),
+ DA9052_LDO(DA9052_LDO34_VOLT_UPPER,
+ DA9052_LDO34_VOLT_LOWER, "DA9052_LDO3", 3300),
+ DA9052_LDO(DA9052_LDO34_VOLT_UPPER,
+ DA9052_LDO34_VOLT_LOWER, "DA9052_LDO4", 2775),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO5", 1300),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO6", 1200),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO7", 2750),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO8", 1800),
+ DA9052_LDO(DA9052_LDO9_VOLT_UPPER,
+ DA9052_LDO9_VOLT_LOWER, "DA9052_LDO9", 2500),
+ DA9052_LDO(DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER, "DA9052_LDO10", 1200),
+
+ /* BUCKS */
+ DA9052_LDO(DA9052_BUCK_CORE_PRO_VOLT_UPPER,
+ DA9052_BUCK_CORE_PRO_VOLT_LOWER, "DA9052_BUCK_CORE", 850),
+ DA9052_LDO(DA9052_BUCK_CORE_PRO_VOLT_UPPER,
+ DA9052_BUCK_CORE_PRO_VOLT_LOWER, "DA9052_BUCK_PRO", 950),
+ DA9052_LDO(DA9052_BUCK_MEM_VOLT_UPPER,
+ DA9052_BUCK_MEM_VOLT_LOWER, "DA9052_BUCK_MEM", 1500),
+ DA9052_LDO(DA9052_BUCK_PERI_VOLT_UPPER,
+ DA9052_BUCK_PERI_VOLT_LOWER, "DA9052_BUCK_PERI", 2500)
+};
+
+
+#define MX53_SMD_WiFi_BT_PWR_EN (2*32 + 10) /*GPIO_3_10 */
+struct regulator_init_data wifi_bt_reg_initdata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+
+static struct fixed_voltage_config wifi_bt_reg_config = {
+ .supply_name = "wifi_bt",
+ .microvolts = 3300000,
+ .gpio = MX53_SMD_WiFi_BT_PWR_EN,
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &wifi_bt_reg_initdata,
+};
+
+static struct platform_device wifi_bt_reg_device = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &wifi_bt_reg_config,
+ },
+};
+
+
+static struct da9052_tsi_platform_data da9052_tsi = {
+ .pen_up_interval = 50,
+ .tsi_delay_bit_shift = 6,
+ .tsi_skip_bit_shift = 3,
+ .num_gpio_tsi_register = 3,
+ .tsi_supply_voltage = 2500,
+ /* This is the DA9052 LDO number used for powering the TSI */
+ .tsi_ref_source = 9,
+ .max_tsi_delay = TSI_DELAY_4SLOTS,
+ .max_tsi_skip_slot = TSI_SKIP_330SLOTS,
+};
+
+static struct da9052_led_platform_data da9052_gpio_led[] = {
+ {
+ .id = DA9052_LED_4,
+ .name = "LED_GPIO14",
+ },
+ {
+ .id = DA9052_LED_5,
+ .name = "LED_GPIO15",
+ },
+};
+
+static struct da9052_leds_platform_data da9052_gpio_leds = {
+ .num_leds = ARRAY_SIZE(da9052_gpio_led),
+ .led = da9052_gpio_led,
+};
+
+
+static struct da9052_bat_platform_data da9052_bat = {
+ .sw_temp_control_en = 0,
+ .monitoring_interval = 500,
+ .sw_bat_temp_threshold = 60,
+ .sw_junc_temp_threshold = 120,
+ .hysteresis_window_size = 1,
+ .current_monitoring_window = 10,
+ .bat_with_no_resistor = 62,
+ .bat_capacity_limit_low = 4,
+ .bat_capacity_full = 100,
+ .bat_capacity_limit_high = 70,
+ .chg_hysteresis_const = 89,
+ .hysteresis_reading_interval = 1000,
+ .hysteresis_no_of_reading = 10,
+ .filter_size = 4,
+ .bat_volt_cutoff = 2800,
+ .vbat_first_valid_detect_iteration = 3,
+};
+
+static void da9052_init_ssc_cache(struct da9052 *da9052)
+{
+ unsigned char cnt;
+
+ /* First initialize all registers as Non-volatile */
+ for (cnt = 0; cnt < DA9052_REG_CNT; cnt++) {
+ da9052->ssc_cache[cnt].type = NON_VOLATILE;
+ da9052->ssc_cache[cnt].status = INVALID;
+ da9052->ssc_cache[cnt].val = 0;
+ }
+
+ /* Now selectively set type for all Volatile registers */
+ /* Reg 1 - 9 */
+ da9052->ssc_cache[DA9052_STATUSA_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_STATUSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_STATUSC_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_STATUSD_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTA_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTC_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_EVENTD_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_FAULTLOG_REG].type = VOLATILE;
+
+ /* Reg 15 */
+ da9052->ssc_cache[DA9052_CONTROLB_REG].type = VOLATILE;
+ /* Reg - 17 */
+ da9052->ssc_cache[DA9052_CONTROLD_REG].type = VOLATILE;
+ /* Reg - 60 */
+ da9052->ssc_cache[DA9052_SUPPLY_REG].type = VOLATILE;
+ /* Reg - 62 */
+ da9052->ssc_cache[DA9052_CHGBUCK_REG].type = VOLATILE;
+
+ /* Reg 67 - 68 */
+ da9052->ssc_cache[DA9052_INPUTCONT_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_CHGTIME_REG].type = VOLATILE;
+
+ /* Reg - 70 */
+ da9052->ssc_cache[DA9052_BOOST_REG].type = VOLATILE;
+
+ /* Reg - 81 */
+ da9052->ssc_cache[DA9052_ADCMAN_REG].type = VOLATILE;
+
+ /* Reg - 83 - 85 */
+ da9052->ssc_cache[DA9052_ADCRESL_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_ADCRESH_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_VDDRES_REG].type = VOLATILE;
+
+ /* Reg - 87 */
+ da9052->ssc_cache[DA9052_ICHGAV_REG].type = VOLATILE;
+
+ /* Reg - 90 */
+ da9052->ssc_cache[DA9052_TBATRES_REG].type = VOLATILE;
+
+ /* Reg - 95 */
+ da9052->ssc_cache[DA9052_ADCIN4RES_REG].type = VOLATILE;
+
+ /* Reg - 98 */
+ da9052->ssc_cache[DA9052_ADCIN5RES_REG].type = VOLATILE;
+
+ /* Reg - 101 */
+ da9052->ssc_cache[DA9052_ADCIN6RES_REG].type = VOLATILE;
+
+ /* Reg - 104 */
+ da9052->ssc_cache[DA9052_TJUNCRES_REG].type = VOLATILE;
+
+ /* Reg 106 - 110 */
+ da9052->ssc_cache[DA9052_TSICONTB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSIXMSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSIYMSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSILSB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_TSIZMSB_REG].type = VOLATILE;
+
+ /* Reg 111 - 117 */
+ da9052->ssc_cache[DA9052_COUNTS_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTMI_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTH_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTD_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTMO_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_COUNTY_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_ALARMMI_REG].type = VOLATILE;
+
+ /* Reg 122 - 125 */
+ da9052->ssc_cache[DA9052_SECONDA_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_SECONDB_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_SECONDC_REG].type = VOLATILE;
+ da9052->ssc_cache[DA9052_SECONDD_REG].type = VOLATILE;
+
+ /* Following addresses are not assigned to any register */
+ da9052->ssc_cache[126].type = VOLATILE;
+ da9052->ssc_cache[127].type = VOLATILE;
+}
+
+
+#define MX53_SMD_DA9052_IRQ (6*32 + 11) /* GPIO7_11 */
+
+static int __init smd_da9052_init(struct da9052 *da9052)
+{
+ /* Configuring for DA9052 interrupt servce */
+ /* s3c_gpio_setpull(DA9052_IRQ_PIN, S3C_GPIO_PULL_UP);*/
+ int ret;
+ /* Set interrupt as LOW LEVEL interrupt source */
+ set_irq_type(IOMUX_TO_IRQ_V3(MX53_SMD_DA9052_IRQ), IRQF_TRIGGER_LOW);
+
+ da9052_init_ssc_cache(da9052);
+ ret = platform_device_register(&wifi_bt_reg_device);
+
+ return 0;
+}
+
+static struct da9052_platform_data __initdata da9052_plat = {
+ .init = smd_da9052_init,
+ .num_regulators = ARRAY_SIZE(da9052_regulators_init),
+ .regulators = da9052_regulators_init,
+ .led_data = &da9052_gpio_leds,
+ .tsi_data = &da9052_tsi,
+ .bat_data = &da9052_bat,
+ /* .gpio_base = GPIO_BOARD_START, */
+};
+
+
+static struct i2c_board_info __initdata da9052_i2c_device = {
+ I2C_BOARD_INFO(DA9052_SSC_I2C_DEVICE_NAME, DA9052_I2C_ADDR >> 1),
+ .irq = IOMUX_TO_IRQ_V3(MX53_SMD_DA9052_IRQ),
+ .platform_data = &da9052_plat,
+};
+
+int __init mx53_smd_init_da9052(void)
+{
+ return i2c_register_board_info(0, &da9052_i2c_device, 1);
+}
diff --git a/arch/arm/mach-mx5/mx53_smd_rfkill.c b/arch/arm/mach-mx5/mx53_smd_rfkill.c
new file mode 100644
index 000000000000..f0f95a839381
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_smd_rfkill.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ * @file mxc_bt_rfkill.c
+ *
+ * @brief This driver is implement a rfkill control interface of bluetooth
+ * chip on i.MX serial boards. Register the power regulator function and
+ * reset function in platform data.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/rfkill.h>
+#include <mach/hardware.h>
+#include <mach/mxc_rfkill.h>
+
+static int mxc_bt_set_block(void *rfkdata, bool blocked)
+{
+ struct mxc_bt_rfkill_platform_data *data = rfkdata;
+ int ret;
+
+ pr_info("rfkill: BT RF going to : %s\n", blocked ? "off" : "on");
+ if (!blocked)
+ ret = data->power_change(1);
+ else
+ ret = data->power_change(0);
+
+ return ret;
+}
+
+static const struct rfkill_ops mxc_bt_rfkill_ops = {
+ .set_block = mxc_bt_set_block,
+};
+
+static int mxc_bt_rfkill_probe(struct platform_device *dev)
+{
+ int rc;
+ struct rfkill *rfk;
+
+ struct mxc_bt_rfkill_platform_data *data = dev->dev.platform_data;
+
+ if (data->power_change == NULL) {
+ rc = -EINVAL;
+ dev_err(&dev->dev, "no power_change function\n");
+ goto error_check_func;
+ }
+
+ rfk = rfkill_alloc("mxc-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH,
+ &mxc_bt_rfkill_ops, data);
+
+ if (!rfk) {
+ rc = -ENOMEM;
+ goto error_rfk_alloc;
+ }
+
+ rfkill_set_led_trigger_name(rfk, "mxc_bt");
+
+ rc = rfkill_register(rfk);
+ if (rc)
+ goto error_rfkill;
+
+ platform_set_drvdata(dev, rfk);
+ printk(KERN_INFO "mxc_bt_rfkill driver success loaded\n");
+ return 0;
+
+error_rfkill:
+ rfkill_destroy(rfk);
+error_rfk_alloc:
+error_check_func:
+ return rc;
+}
+
+static int __devexit mxc_bt_rfkill_remove(struct platform_device *dev)
+{
+ struct mxc_bt_rfkill_platform_data *data = dev->dev.platform_data;
+ struct rfkill *rfk = platform_get_drvdata(dev);
+
+ platform_set_drvdata(dev, NULL);
+
+ if (rfk) {
+ rfkill_unregister(rfk);
+ rfkill_destroy(rfk);
+ }
+
+ data->power_change(0);
+
+ return 0;
+}
+
+static struct platform_driver mxc_bt_rfkill_drv = {
+ .driver = {
+ .name = "mxc_bt_rfkill",
+ },
+
+ .probe = mxc_bt_rfkill_probe,
+ .remove = __devexit_p(mxc_bt_rfkill_remove),
+};
+
+static int __init mxc_bt_rfkill_init(void)
+{
+ return platform_driver_register(&mxc_bt_rfkill_drv);
+}
+
+module_init(mxc_bt_rfkill_init);
+
+static void __exit mxc_bt_rfkill_exit(void)
+{
+ platform_driver_unregister(&mxc_bt_rfkill_drv);
+}
+
+module_exit(mxc_bt_rfkill_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("RFKill control interface of BT on MX53 SMD");
diff --git a/arch/arm/mach-mx5/mx53_wp.c b/arch/arm/mach-mx5/mx53_wp.c
new file mode 100644
index 000000000000..a09cb735c1d0
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_wp.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <mach/hardware.h>
+#include "mx53_wp.h"
+
+/*!
+ * @file mach-mx5/mx53_wp.c
+ *
+ * @brief This file contains the information about MX53 CPU working points.
+ *
+ * @ingroup MSL_MX53
+ */
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void (*set_num_cpu_wp)(int num);
+static int num_cpu_wp;
+static struct cpu_wp *cpu_wp_table;
+
+/* working point for auto*/
+static struct cpu_wp cpu_wp_aec[] = {
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1050000,},
+};
+
+/* working point for consumer 1G*/
+static struct cpu_wp cpu_wp_ces[] = {
+ {
+ .pll_rate = 1000000000,
+ .cpu_rate = 1000000000,
+ .pdf = 0,
+ .mfi = 10,
+ .mfd = 11,
+ .mfn = 5,
+ .cpu_podf = 0,
+ .cpu_voltage = 1200000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1050000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 400000000,
+ .cpu_podf = 1,
+ .cpu_voltage = 950000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 160000000,
+ .cpu_podf = 4,
+ .cpu_voltage = 900000,},
+};
+
+/* working point for consumer 1.2G*/
+static struct cpu_wp cpu_wp_ces_1_2g[] = {
+ {
+ .pll_rate = 1200000000,
+ .cpu_rate = 1200000000,
+ .pdf = 0,
+ .mfi = 12,
+ .mfd = 1,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1300000,},
+ {
+ .pll_rate = 1000000000,
+ .cpu_rate = 1000000000,
+ .pdf = 0,
+ .mfi = 10,
+ .mfd = 11,
+ .mfn = 5,
+ .cpu_podf = 0,
+ .cpu_voltage = 1200000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 800000000,
+ .pdf = 0,
+ .mfi = 8,
+ .mfd = 2,
+ .mfn = 1,
+ .cpu_podf = 0,
+ .cpu_voltage = 1050000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 400000000,
+ .cpu_podf = 1,
+ .cpu_voltage = 950000,},
+ {
+ .pll_rate = 800000000,
+ .cpu_rate = 160000000,
+ .cpu_podf = 4,
+ .cpu_voltage = 900000,},
+};
+
+
+struct cpu_wp *mx53_get_cpu_wp(int *wp)
+{
+ *wp = num_cpu_wp;
+ return cpu_wp_table;
+}
+
+void mx53_set_num_cpu_wp(int num)
+{
+ num_cpu_wp = num;
+ return;
+}
+
+void mx53_set_cpu_part_number(enum mx53_cpu_part_number part_num)
+{
+ get_cpu_wp = mx53_get_cpu_wp;
+ set_num_cpu_wp = mx53_set_num_cpu_wp;
+
+ switch (part_num) {
+ case IMX53_CEC_1_2G:
+ cpu_wp_table = cpu_wp_ces_1_2g;
+ num_cpu_wp = ARRAY_SIZE(cpu_wp_ces_1_2g);
+ break;
+ case IMX53_CEC:
+ cpu_wp_table = cpu_wp_ces;
+ num_cpu_wp = ARRAY_SIZE(cpu_wp_ces);
+ break;
+ case IMX53_AEC:
+ default:
+ cpu_wp_table = cpu_wp_aec;
+ num_cpu_wp = ARRAY_SIZE(cpu_wp_aec);
+ break;
+ }
+}
+
+
diff --git a/arch/arm/mach-mx5/mx53_wp.h b/arch/arm/mach-mx5/mx53_wp.h
new file mode 100644
index 000000000000..353b5320a1b8
--- /dev/null
+++ b/arch/arm/mach-mx5/mx53_wp.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MX53_WP_H__
+#define __ARCH_ARM_MACH_MX53_WP_H__
+#include <linux/types.h>
+
+/*!
+ * @file mach-mx5/mx53_wp.h
+ *
+ * @brief This file contains the information about MX53 CPU working points.
+ *
+ * @ingroup MSL_MX53
+ */
+enum mx53_cpu_part_number {
+ IMX53_AEC, /* automative and infotainment AP */
+ IMX53_CEC, /* Consumer AP, CPU freq is up to 1G */
+ IMX53_CEC_1_2G, /* Consumer AP, CPU freq is up to 1.2GHZ */
+};
+
+void mx53_set_cpu_part_number(enum mx53_cpu_part_number part_num);
+
+#endif /*__ARCH_ARM_MACH_MX53_WP_H__ */
+
+
+
diff --git a/arch/arm/mach-mx5/pm.c b/arch/arm/mach-mx5/pm.c
new file mode 100644
index 000000000000..f07681be3748
--- /dev/null
+++ b/arch/arm/mach-mx5/pm.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+#include <linux/regulator/machine.h>
+#include <linux/proc_fs.h>
+#include <linux/cpufreq.h>
+#include <linux/iram_alloc.h>
+#include <linux/fsl_devices.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+#include <asm/delay.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#ifdef CONFIG_ARCH_MX50
+#include <mach/iomux-mx50.h>
+#endif
+
+#define MXC_SRPG_EMPGC0_SRPGCR (IO_ADDRESS(GPC_BASE_ADDR) + 0x2C0)
+#define MXC_SRPG_EMPGC1_SRPGCR (IO_ADDRESS(GPC_BASE_ADDR) + 0x2D0)
+#define DATABAHN_CTL_REG0 0
+#define DATABAHN_CTL_REG19 0x4c
+#define DATABAHN_CTL_REG79 0x13c
+#define DATABAHN_PHY_REG25 0x264
+#define MX53_OFFSET 0x20000000
+
+static struct cpu_wp *cpu_wp_tbl;
+static int cpu_wp_nr;
+static struct clk *cpu_clk;
+static struct mxc_pm_platform_data *pm_data;
+
+#if defined(CONFIG_CPU_FREQ)
+static int org_freq;
+extern int cpufreq_suspended;
+extern int set_cpu_freq(int wp);
+#endif
+
+
+static struct device *pm_dev;
+struct clk *gpc_dvfs_clk;
+extern void cpu_do_suspend_workaround(u32 sdclk_iomux_addr);
+extern void mx50_suspend(u32 databahn_addr);
+extern struct cpu_wp *(*get_cpu_wp)(int *wp);
+extern void __iomem *databahn_base;
+extern void da9053_suspend_cmd(void);
+extern void pm_da9053_i2c_init(u32 base_addr);
+
+extern int iram_ready;
+void *suspend_iram_base;
+void (*suspend_in_iram)(void *sdclk_iomux_addr) = NULL;
+void __iomem *suspend_param1;
+
+#define TZIC_WAKEUP0_OFFSET 0x0E00
+#define TZIC_WAKEUP1_OFFSET 0x0E04
+#define TZIC_WAKEUP2_OFFSET 0x0E08
+#define TZIC_WAKEUP3_OFFSET 0x0E0C
+#define GPIO7_0_11_IRQ_BIT (0x1<<11)
+
+static void mx53_smd_loco_irq_wake_fixup(void)
+{
+ void __iomem *tzic_base;
+ tzic_base = ioremap(MX53_TZIC_BASE_ADDR, SZ_4K);
+ if (NULL == tzic_base) {
+ pr_err("fail to map MX53_TZIC_BASE_ADDR\n");
+ return;
+ }
+ __raw_writel(0, tzic_base + TZIC_WAKEUP0_OFFSET);
+ __raw_writel(0, tzic_base + TZIC_WAKEUP1_OFFSET);
+ __raw_writel(0, tzic_base + TZIC_WAKEUP2_OFFSET);
+ /* only enable irq wakeup for da9053 */
+ __raw_writel(GPIO7_0_11_IRQ_BIT, tzic_base + TZIC_WAKEUP3_OFFSET);
+ iounmap(tzic_base);
+ pr_debug("only da9053 irq is wakeup-enabled\n");
+}
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+ if (gpc_dvfs_clk == NULL)
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk");
+ /* gpc clock is needed for SRPG */
+ clk_enable(gpc_dvfs_clk);
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ mxc_cpu_lp_set(STOP_POWER_OFF);
+ break;
+ case PM_SUSPEND_STANDBY:
+ mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (tzic_enable_wake(0) != 0)
+ return -EAGAIN;
+
+ if (state == PM_SUSPEND_MEM) {
+ local_flush_tlb_all();
+ flush_cache_all();
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ if (machine_is_mx53_smd() ||
+ machine_is_mx53_loco()) {
+ mx53_smd_loco_irq_wake_fixup();
+ da9053_suspend_cmd();
+ }
+ /* Run the suspend code from iRAM. */
+ suspend_in_iram(suspend_param1);
+
+ /*clear the EMPGC0/1 bits */
+ __raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+ } else {
+ if (machine_is_mx50_rdp() && pm_data->suspend_enter)
+ pm_data->suspend_enter();
+ /* Suspend now. */
+ suspend_in_iram(databahn_base);
+ if (machine_is_mx50_rdp() && pm_data->suspend_exit)
+ pm_data->suspend_exit();
+ }
+ } else {
+ cpu_do_idle();
+ }
+ clk_disable(gpc_dvfs_clk);
+
+ return 0;
+}
+
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int mx5_suspend_prepare(void)
+{
+#if defined(CONFIG_CPU_FREQ)
+#define MX53_SUSPEND_CPU_WP 400000000
+ struct cpufreq_freqs freqs;
+ u32 suspend_wp = 0;
+ org_freq = clk_get_rate(cpu_clk);
+ /* workaround for mx53 to suspend on 400MHZ wp */
+ if (cpu_is_mx53())
+ for (suspend_wp = 0; suspend_wp < cpu_wp_nr; suspend_wp++)
+ if (cpu_wp_tbl[suspend_wp].cpu_rate
+ == MX53_SUSPEND_CPU_WP)
+ break;
+ if (suspend_wp == cpu_wp_nr)
+ suspend_wp = 0;
+ pr_info("suspend wp cpu=%d\n", cpu_wp_tbl[suspend_wp].cpu_rate);
+ freqs.old = org_freq / 1000;
+ freqs.new = cpu_wp_tbl[suspend_wp].cpu_rate / 1000;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+
+ cpufreq_suspended = 1;
+ if (clk_get_rate(cpu_clk) != cpu_wp_tbl[suspend_wp].cpu_rate) {
+ set_cpu_freq(cpu_wp_tbl[suspend_wp].cpu_rate);
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Called before devices are re-setup.
+ */
+static void mx5_suspend_finish(void)
+{
+#if defined(CONFIG_CPU_FREQ)
+ struct cpufreq_freqs freqs;
+
+ freqs.old = clk_get_rate(cpu_clk) / 1000;
+ freqs.new = org_freq / 1000;
+ freqs.cpu = 0;
+ freqs.flags = 0;
+
+ cpufreq_suspended = 0;
+
+ if (org_freq != clk_get_rate(cpu_clk)) {
+ set_cpu_freq(org_freq);
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+#endif
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static void mx5_suspend_end(void)
+{
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+ return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+struct platform_suspend_ops mx5_suspend_ops = {
+ .valid = mx5_pm_valid,
+ .prepare = mx5_suspend_prepare,
+ .enter = mx5_suspend_enter,
+ .finish = mx5_suspend_finish,
+ .end = mx5_suspend_end,
+};
+
+static int __devinit mx5_pm_probe(struct platform_device *pdev)
+{
+ pm_dev = &pdev->dev;
+ pm_data = pdev->dev.platform_data;
+
+ return 0;
+}
+
+static struct platform_driver mx5_pm_driver = {
+ .driver = {
+ .name = "mx5_pm",
+ },
+ .probe = mx5_pm_probe,
+};
+
+static int __init pm_init(void)
+{
+ unsigned long iram_paddr;
+
+ pr_info("Static Power Management for Freescale i.MX5\n");
+ if (platform_driver_register(&mx5_pm_driver) != 0) {
+ printk(KERN_ERR "mx5_pm_driver register failed\n");
+ return -ENODEV;
+ }
+ suspend_set_ops(&mx5_suspend_ops);
+ /* Move suspend routine into iRAM */
+ iram_alloc(SZ_4K, &iram_paddr);
+ /* Need to remap the area here since we want the memory region
+ to be executable. */
+ suspend_iram_base = __arm_ioremap(iram_paddr, SZ_4K,
+ MT_HIGH_VECTORS);
+
+ if (cpu_is_mx51() || cpu_is_mx53()) {
+ suspend_param1 = IO_ADDRESS(IOMUXC_BASE_ADDR + 0x4b8);
+ memcpy(suspend_iram_base, cpu_do_suspend_workaround,
+ SZ_4K);
+ } else if (cpu_is_mx50()) {
+ /*
+ * Need to run the suspend code from IRAM as the DDR needs
+ * to be put into self refresh mode manually.
+ */
+ memcpy(suspend_iram_base, mx50_suspend, SZ_4K);
+
+ suspend_param1 = databahn_base;
+ }
+ suspend_in_iram = (void *)suspend_iram_base;
+
+ cpu_wp_tbl = get_cpu_wp(&cpu_wp_nr);
+
+ cpu_clk = clk_get(NULL, "cpu_clk");
+ if (IS_ERR(cpu_clk)) {
+ printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__);
+ return PTR_ERR(cpu_clk);
+ }
+ printk(KERN_INFO "PM driver module loaded\n");
+
+ if (machine_is_mx53_smd() ||
+ machine_is_mx53_loco())
+ pm_da9053_i2c_init(I2C1_BASE_ADDR - MX53_OFFSET);
+
+ return 0;
+}
+
+
+static void __exit pm_cleanup(void)
+{
+ /* Unregister the device structure */
+ platform_driver_unregister(&mx5_pm_driver);
+}
+
+module_init(pm_init);
+module_exit(pm_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("PM driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-mx5/pm_da9053.c b/arch/arm/mach-mx5/pm_da9053.c
new file mode 100644
index 000000000000..6e24fb2823d4
--- /dev/null
+++ b/arch/arm/mach-mx5/pm_da9053.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/mfd/da9052/reg.h>
+
+#include <mach/hardware.h>
+#include <mach/i2c.h>
+
+/** Defines ********************************************************************
+*******************************************************************************/
+
+
+/* IMX I2C registers */
+#define IMX_I2C_IADR 0x00 /* i2c slave address */
+#define IMX_I2C_IFDR 0x04 /* i2c frequency divider */
+#define IMX_I2C_I2CR 0x08 /* i2c control */
+#define IMX_I2C_I2SR 0x0C /* i2c status */
+#define IMX_I2C_I2DR 0x10 /* i2c transfer data */
+
+/* Bits of IMX I2C registers */
+#define I2SR_RXAK 0x01
+#define I2SR_IIF 0x02
+#define I2SR_SRW 0x04
+#define I2SR_IAL 0x10
+#define I2SR_IBB 0x20
+#define I2SR_IAAS 0x40
+#define I2SR_ICF 0x80
+#define I2CR_RSTA 0x04
+#define I2CR_TXAK 0x08
+#define I2CR_MTX 0x10
+#define I2CR_MSTA 0x20
+#define I2CR_IIEN 0x40
+#define I2CR_IEN 0x80
+
+static void __iomem *base;
+static int stopped;
+
+/** Functions for IMX I2C adapter driver ***************************************
+*******************************************************************************/
+
+static int pm_i2c_imx_bus_busy(int for_busy)
+{
+ unsigned int temp;
+
+ while (1) {
+ temp = readb(base + IMX_I2C_I2SR);
+ if (for_busy && (temp & I2SR_IBB))
+ break;
+ if (!for_busy && !(temp & I2SR_IBB))
+ break;
+ pr_debug("waiting bus busy=%d\n", for_busy);
+ }
+
+ return 0;
+}
+
+static int pm_i2c_imx_trx_complete(void)
+{
+ unsigned int temp;
+ while (!((temp = readb(base + IMX_I2C_I2SR)) & I2SR_IIF))
+ pr_debug("waiting or I2SR_IIF\n");
+ temp &= ~I2SR_IIF;
+ writeb(temp, base + IMX_I2C_I2SR);
+
+ return 0;
+}
+
+static int pm_i2c_imx_acked(void)
+{
+ if (readb(base + IMX_I2C_I2SR) & I2SR_RXAK) {
+ pr_info("<%s> No ACK\n", __func__);
+ return -EIO; /* No ACK */
+ }
+ return 0;
+}
+
+static int pm_i2c_imx_start(void)
+{
+ unsigned int temp = 0;
+ int result;
+
+ /* Enable I2C controller */
+ writeb(0, base + IMX_I2C_I2SR);
+ writeb(I2CR_IEN, base + IMX_I2C_I2CR);
+
+ /* Wait controller to be stable */
+ udelay(50);
+
+ /* Start I2C transaction */
+ temp = readb(base + IMX_I2C_I2CR);
+ temp |= I2CR_MSTA;
+ writeb(temp, base + IMX_I2C_I2CR);
+ result = pm_i2c_imx_bus_busy(1);
+
+ temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
+ writeb(temp, base + IMX_I2C_I2CR);
+ return result;
+}
+
+static void pm_i2c_imx_stop(void)
+{
+ unsigned int temp = 0;
+
+ /* Stop I2C transaction */
+ temp = readb(base + IMX_I2C_I2CR);
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
+ writeb(temp, base + IMX_I2C_I2CR);
+
+ pm_i2c_imx_bus_busy(0);
+
+ /* Disable I2C controller */
+ writeb(0, base + IMX_I2C_I2CR);
+}
+
+static int pm_i2c_imx_write(struct i2c_msg *msgs)
+{
+ int i, result;
+
+ /* write slave address */
+ writeb(msgs->addr << 1, base + IMX_I2C_I2DR);
+ result = pm_i2c_imx_trx_complete();
+ if (result)
+ return result;
+ result = pm_i2c_imx_acked();
+ if (result)
+ return result;
+
+ /* write data */
+ for (i = 0; i < msgs->len; i++) {
+ writeb(msgs->buf[i], base + IMX_I2C_I2DR);
+ result = pm_i2c_imx_trx_complete();
+ if (result)
+ return result;
+ result = pm_i2c_imx_acked();
+ if (result)
+ return result;
+ }
+ return 0;
+}
+
+static int pm_i2c_imx_read(struct i2c_msg *msgs)
+{
+ int i, result;
+ unsigned int temp;
+
+ /* write slave address */
+ writeb((msgs->addr << 1) | 0x01, base + IMX_I2C_I2DR);
+ result = pm_i2c_imx_trx_complete();
+ if (result)
+ return result;
+ result = pm_i2c_imx_acked();
+ if (result)
+ return result;
+
+ /* setup bus to read data */
+ temp = readb(base + IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+ if (msgs->len - 1)
+ temp &= ~I2CR_TXAK;
+ writeb(temp, base + IMX_I2C_I2CR);
+ readb(base + IMX_I2C_I2DR); /* dummy read */
+
+ /* read data */
+ for (i = 0; i < msgs->len; i++) {
+ result = pm_i2c_imx_trx_complete();
+ if (result)
+ return result;
+ if (i == (msgs->len - 1)) {
+ /* It must generate STOP before read I2DR to prevent
+ controller from generating another clock cycle */
+ temp = readb(base + IMX_I2C_I2CR);
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
+ writeb(temp, base + IMX_I2C_I2CR);
+ pm_i2c_imx_bus_busy(0);
+ stopped = 1;
+ } else if (i == (msgs->len - 2)) {
+ temp = readb(base + IMX_I2C_I2CR);
+ temp |= I2CR_TXAK;
+ writeb(temp, base + IMX_I2C_I2CR);
+ }
+ msgs->buf[i] = readb(base + IMX_I2C_I2DR);
+ }
+ return 0;
+}
+
+int pm_i2c_imx_xfer(struct i2c_msg *msgs, int num)
+{
+ unsigned int i, temp;
+ int result;
+
+ /* Start I2C transfer */
+ result = pm_i2c_imx_start();
+ if (result)
+ goto fail0;
+
+ /* read/write data */
+ for (i = 0; i < num; i++) {
+ if (i) {
+ temp = readb(base + IMX_I2C_I2CR);
+ temp |= I2CR_RSTA;
+ writeb(temp, base + IMX_I2C_I2CR);
+ result = pm_i2c_imx_bus_busy(1);
+ if (result)
+ goto fail0;
+ }
+ /* write/read data */
+ if (msgs[i].flags & I2C_M_RD)
+ result = pm_i2c_imx_read(&msgs[i]);
+ else
+ result = pm_i2c_imx_write(&msgs[i]);
+ if (result)
+ goto fail0;
+ }
+
+fail0:
+ /* Stop I2C transfer */
+ pm_i2c_imx_stop();
+
+ return (result < 0) ? result : num;
+}
+
+void pm_da9053_i2c_init(u32 base_addr)
+{
+ base = ioremap(base_addr, SZ_4K);
+}
+
+void pm_da9053_i2c_deinit(void)
+{
+ iounmap(base);
+}
+
+void pm_da9053_read_reg(u8 reg, u8 *value)
+{
+ unsigned char buf[2] = {0, 0};
+ struct i2c_msg i2cmsg[2];
+ buf[0] = reg;
+ i2cmsg[0].addr = 0x48 ;
+ i2cmsg[0].len = 1;
+ i2cmsg[0].buf = &buf[0];
+
+ i2cmsg[0].flags = 0;
+
+ i2cmsg[1].addr = 0x48 ;
+ i2cmsg[1].len = 1;
+ i2cmsg[1].buf = &buf[1];
+
+ i2cmsg[1].flags = I2C_M_RD;
+
+ pm_i2c_imx_xfer(i2cmsg, 2);
+ *value = buf[1];
+}
+
+void pm_da9053_write_reg(u8 reg, u8 value)
+{
+ unsigned char buf[2] = {0, 0};
+ struct i2c_msg i2cmsg[2];
+ buf[0] = reg;
+ buf[1] = value;
+ i2cmsg[0].addr = 0x48 ;
+ i2cmsg[0].len = 2;
+ i2cmsg[0].buf = &buf[0];
+ i2cmsg[0].flags = 0;
+ pm_i2c_imx_xfer(i2cmsg, 1);
+}
+
+/* have to hard-code the preset voltage here for they share the register
+as the normal setting on Da9053 */
+/* preset buck core to 850 mv */
+#define BUCKCORE_SUSPEND_PRESET 0xCE
+/* preset buck core to 950 mv */
+#define BUCKPRO_SUSPEND_PRESET 0xD2
+/* preset ldo6 to 1200 mv */
+#define LDO6_SUSPEND_PRESET 0xC0
+/* preset ldo10 to 1200 mv */
+#define iLDO10_SUSPEND_PRESET 0xC0
+#define CONF_BIT 0x80
+
+static u8 volt_settings[DA9052_LDO10_REG - DA9052_BUCKCORE_REG + 1];
+static void pm_da9053_preset_voltage(void)
+{
+ u8 reg, data;
+ for (reg = DA9052_BUCKCORE_REG;
+ reg <= DA9052_LDO10_REG; reg++) {
+ pm_da9053_read_reg(reg, &data);
+ volt_settings[reg - DA9052_BUCKCORE_REG] = data;
+ data |= CONF_BIT;
+ pm_da9053_write_reg(reg, data);
+ }
+ pm_da9053_write_reg(DA9052_BUCKCORE_REG, BUCKCORE_SUSPEND_PRESET);
+ pm_da9053_write_reg(DA9052_BUCKPRO_REG, BUCKPRO_SUSPEND_PRESET);
+ pm_da9053_write_reg(DA9052_LDO6_REG, LDO6_SUSPEND_PRESET);
+ pm_da9053_write_reg(DA9052_LDO10_REG, iLDO10_SUSPEND_PRESET);
+}
+
+#define DA9053_SLEEP_DELAY 0x1f
+int da9053_suspend_cmd(void)
+{
+ unsigned char buf[2] = {0, 0};
+ struct clk *i2c_clk;
+ u8 data;
+ buf[0] = 29;
+
+ i2c_clk = clk_get(NULL, "i2c_clk");
+ if (IS_ERR(i2c_clk)) {
+ pr_err("unable to get i2c clk\n");
+ return PTR_ERR(i2c_clk);
+ }
+ clk_enable(i2c_clk);
+
+ pm_da9053_preset_voltage();
+
+ pm_da9053_read_reg(DA9052_ID01_REG, &data);
+ data &= ~(DA9052_ID01_DEFSUPPLY | DA9052_ID01_nRESMODE);
+ pm_da9053_write_reg(DA9052_ID01_REG, data);
+
+ pm_da9053_write_reg(DA9052_SEQB_REG, DA9053_SLEEP_DELAY);
+
+ pm_da9053_read_reg(DA9052_CONTROLB_REG, &data);
+ data |= DA9052_CONTROLB_DEEPSLEEP;
+ pm_da9053_write_reg(DA9052_CONTROLB_REG, data);
+
+ clk_disable(i2c_clk);
+ clk_put(i2c_clk);
+ return 0;
+}
+
+void da9053_restore_volt_settings(void)
+{
+ u8 reg;
+ for (reg = DA9052_BUCKCORE_REG;
+ reg <= DA9052_LDO10_REG; reg++)
+ pm_da9053_write_reg(reg,
+ volt_settings[reg - DA9052_BUCKCORE_REG]);
+}
+
+int da9053_poweroff_cmd(void)
+{
+ unsigned char buf[2] = {0, 0};
+ struct clk *i2c_clk;
+ u8 data;
+ buf[0] = 29;
+
+ i2c_clk = clk_get(NULL, "i2c_clk");
+ if (IS_ERR(i2c_clk)) {
+ pr_err("unable to get i2c clk\n");
+ return PTR_ERR(i2c_clk);
+ }
+ clk_enable(i2c_clk);
+
+ pm_da9053_read_reg(DA9052_CONTROLB_REG, &data);
+ data |= DA9052_CONTROLB_SHUTDOWN;
+ pm_da9053_write_reg(DA9052_CONTROLB_REG, data);
+
+ clk_disable(i2c_clk);
+ clk_put(i2c_clk);
+ return 0;
+}
+
diff --git a/arch/arm/mach-mx5/regs-apbh.h b/arch/arm/mach-mx5/regs-apbh.h
new file mode 100644
index 000000000000..23b9f4baa404
--- /dev/null
+++ b/arch/arm/mach-mx5/regs-apbh.h
@@ -0,0 +1,512 @@
+/*
+ * Freescale APBH Register Definitions
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This file is created by xml file. Don't Edit it.
+ *
+ * Xml Revision: 1.3
+ * Template revision: 1.3
+ */
+
+#ifndef __ARCH_ARM___APBH_H
+#define __ARCH_ARM___APBH_H
+
+
+#define HW_APBH_CTRL0 (0x00000000)
+#define HW_APBH_CTRL0_SET (0x00000004)
+#define HW_APBH_CTRL0_CLR (0x00000008)
+#define HW_APBH_CTRL0_TOG (0x0000000c)
+
+#define BM_APBH_CTRL0_SFTRST 0x80000000
+#define BM_APBH_CTRL0_CLKGATE 0x40000000
+#define BM_APBH_CTRL0_AHB_BURST8_EN 0x20000000
+#define BM_APBH_CTRL0_APB_BURST_EN 0x10000000
+#define BP_APBH_CTRL0_RSVD0 16
+#define BM_APBH_CTRL0_RSVD0 0x0FFF0000
+#define BF_APBH_CTRL0_RSVD0(v) \
+ (((v) << 16) & BM_APBH_CTRL0_RSVD0)
+#define BP_APBH_CTRL0_CLKGATE_CHANNEL 0
+#define BM_APBH_CTRL0_CLKGATE_CHANNEL 0x0000FFFF
+#define BF_APBH_CTRL0_CLKGATE_CHANNEL(v) \
+ (((v) << 0) & BM_APBH_CTRL0_CLKGATE_CHANNEL)
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND0 0x0001
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND1 0x0002
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND2 0x0004
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND3 0x0008
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND4 0x0010
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND5 0x0020
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND6 0x0040
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__NAND7 0x0080
+#define BV_APBH_CTRL0_CLKGATE_CHANNEL__SSP 0x0100
+
+#define HW_APBH_CTRL1 (0x00000010)
+#define HW_APBH_CTRL1_SET (0x00000014)
+#define HW_APBH_CTRL1_CLR (0x00000018)
+#define HW_APBH_CTRL1_TOG (0x0000001c)
+
+#define BM_APBH_CTRL1_CH15_CMDCMPLT_IRQ_EN 0x80000000
+#define BM_APBH_CTRL1_CH14_CMDCMPLT_IRQ_EN 0x40000000
+#define BM_APBH_CTRL1_CH13_CMDCMPLT_IRQ_EN 0x20000000
+#define BM_APBH_CTRL1_CH12_CMDCMPLT_IRQ_EN 0x10000000
+#define BM_APBH_CTRL1_CH11_CMDCMPLT_IRQ_EN 0x08000000
+#define BM_APBH_CTRL1_CH10_CMDCMPLT_IRQ_EN 0x04000000
+#define BM_APBH_CTRL1_CH9_CMDCMPLT_IRQ_EN 0x02000000
+#define BM_APBH_CTRL1_CH8_CMDCMPLT_IRQ_EN 0x01000000
+#define BM_APBH_CTRL1_CH7_CMDCMPLT_IRQ_EN 0x00800000
+#define BM_APBH_CTRL1_CH6_CMDCMPLT_IRQ_EN 0x00400000
+#define BM_APBH_CTRL1_CH5_CMDCMPLT_IRQ_EN 0x00200000
+#define BM_APBH_CTRL1_CH4_CMDCMPLT_IRQ_EN 0x00100000
+#define BM_APBH_CTRL1_CH3_CMDCMPLT_IRQ_EN 0x00080000
+#define BM_APBH_CTRL1_CH2_CMDCMPLT_IRQ_EN 0x00040000
+#define BM_APBH_CTRL1_CH1_CMDCMPLT_IRQ_EN 0x00020000
+#define BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ_EN 0x00010000
+#define BM_APBH_CTRL1_CH15_CMDCMPLT_IRQ 0x00008000
+#define BM_APBH_CTRL1_CH14_CMDCMPLT_IRQ 0x00004000
+#define BM_APBH_CTRL1_CH13_CMDCMPLT_IRQ 0x00002000
+#define BM_APBH_CTRL1_CH12_CMDCMPLT_IRQ 0x00001000
+#define BM_APBH_CTRL1_CH11_CMDCMPLT_IRQ 0x00000800
+#define BM_APBH_CTRL1_CH10_CMDCMPLT_IRQ 0x00000400
+#define BM_APBH_CTRL1_CH9_CMDCMPLT_IRQ 0x00000200
+#define BM_APBH_CTRL1_CH8_CMDCMPLT_IRQ 0x00000100
+#define BM_APBH_CTRL1_CH7_CMDCMPLT_IRQ 0x00000080
+#define BM_APBH_CTRL1_CH6_CMDCMPLT_IRQ 0x00000040
+#define BM_APBH_CTRL1_CH5_CMDCMPLT_IRQ 0x00000020
+#define BM_APBH_CTRL1_CH4_CMDCMPLT_IRQ 0x00000010
+#define BM_APBH_CTRL1_CH3_CMDCMPLT_IRQ 0x00000008
+#define BM_APBH_CTRL1_CH2_CMDCMPLT_IRQ 0x00000004
+#define BM_APBH_CTRL1_CH1_CMDCMPLT_IRQ 0x00000002
+#define BM_APBH_CTRL1_CH0_CMDCMPLT_IRQ 0x00000001
+
+#define HW_APBH_CTRL2 (0x00000020)
+#define HW_APBH_CTRL2_SET (0x00000024)
+#define HW_APBH_CTRL2_CLR (0x00000028)
+#define HW_APBH_CTRL2_TOG (0x0000002c)
+
+#define BM_APBH_CTRL2_CH15_ERROR_STATUS 0x80000000
+#define BV_APBH_CTRL2_CH15_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH15_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH14_ERROR_STATUS 0x40000000
+#define BV_APBH_CTRL2_CH14_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH14_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH13_ERROR_STATUS 0x20000000
+#define BV_APBH_CTRL2_CH13_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH13_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH12_ERROR_STATUS 0x10000000
+#define BV_APBH_CTRL2_CH12_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH12_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH11_ERROR_STATUS 0x08000000
+#define BV_APBH_CTRL2_CH11_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH11_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH10_ERROR_STATUS 0x04000000
+#define BV_APBH_CTRL2_CH10_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH10_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH9_ERROR_STATUS 0x02000000
+#define BV_APBH_CTRL2_CH9_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH9_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH8_ERROR_STATUS 0x01000000
+#define BV_APBH_CTRL2_CH8_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH8_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH7_ERROR_STATUS 0x00800000
+#define BV_APBH_CTRL2_CH7_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH7_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH6_ERROR_STATUS 0x00400000
+#define BV_APBH_CTRL2_CH6_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH6_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH5_ERROR_STATUS 0x00200000
+#define BV_APBH_CTRL2_CH5_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH5_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH4_ERROR_STATUS 0x00100000
+#define BV_APBH_CTRL2_CH4_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH4_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH3_ERROR_STATUS 0x00080000
+#define BV_APBH_CTRL2_CH3_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH3_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH2_ERROR_STATUS 0x00040000
+#define BV_APBH_CTRL2_CH2_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH2_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH1_ERROR_STATUS 0x00020000
+#define BV_APBH_CTRL2_CH1_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH1_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH0_ERROR_STATUS 0x00010000
+#define BV_APBH_CTRL2_CH0_ERROR_STATUS__TERMINATION 0x0
+#define BV_APBH_CTRL2_CH0_ERROR_STATUS__BUS_ERROR 0x1
+#define BM_APBH_CTRL2_CH15_ERROR_IRQ 0x00008000
+#define BM_APBH_CTRL2_CH14_ERROR_IRQ 0x00004000
+#define BM_APBH_CTRL2_CH13_ERROR_IRQ 0x00002000
+#define BM_APBH_CTRL2_CH12_ERROR_IRQ 0x00001000
+#define BM_APBH_CTRL2_CH11_ERROR_IRQ 0x00000800
+#define BM_APBH_CTRL2_CH10_ERROR_IRQ 0x00000400
+#define BM_APBH_CTRL2_CH9_ERROR_IRQ 0x00000200
+#define BM_APBH_CTRL2_CH8_ERROR_IRQ 0x00000100
+#define BM_APBH_CTRL2_CH7_ERROR_IRQ 0x00000080
+#define BM_APBH_CTRL2_CH6_ERROR_IRQ 0x00000040
+#define BM_APBH_CTRL2_CH5_ERROR_IRQ 0x00000020
+#define BM_APBH_CTRL2_CH4_ERROR_IRQ 0x00000010
+#define BM_APBH_CTRL2_CH3_ERROR_IRQ 0x00000008
+#define BM_APBH_CTRL2_CH2_ERROR_IRQ 0x00000004
+#define BM_APBH_CTRL2_CH1_ERROR_IRQ 0x00000002
+#define BM_APBH_CTRL2_CH0_ERROR_IRQ 0x00000001
+
+#define HW_APBH_CHANNEL_CTRL (0x00000030)
+#define HW_APBH_CHANNEL_CTRL_SET (0x00000034)
+#define HW_APBH_CHANNEL_CTRL_CLR (0x00000038)
+#define HW_APBH_CHANNEL_CTRL_TOG (0x0000003c)
+
+#define BP_APBH_CHANNEL_CTRL_RESET_CHANNEL 16
+#define BM_APBH_CHANNEL_CTRL_RESET_CHANNEL 0xFFFF0000
+#define BF_APBH_CHANNEL_CTRL_RESET_CHANNEL(v) \
+ (((v) << 16) & BM_APBH_CHANNEL_CTRL_RESET_CHANNEL)
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND0 0x0001
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND1 0x0002
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND2 0x0004
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND3 0x0008
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND4 0x0010
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND5 0x0020
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND6 0x0040
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__NAND7 0x0080
+#define BV_APBH_CHANNEL_CTRL_RESET_CHANNEL__SSP 0x0100
+#define BP_APBH_CHANNEL_CTRL_FREEZE_CHANNEL 0
+#define BM_APBH_CHANNEL_CTRL_FREEZE_CHANNEL 0x0000FFFF
+#define BF_APBH_CHANNEL_CTRL_FREEZE_CHANNEL(v) \
+ (((v) << 0) & BM_APBH_CHANNEL_CTRL_FREEZE_CHANNEL)
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND0 0x0001
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND1 0x0002
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND2 0x0004
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND3 0x0008
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND4 0x0010
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND5 0x0020
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND6 0x0040
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__NAND7 0x0080
+#define BV_APBH_CHANNEL_CTRL_FREEZE_CHANNEL__SSP 0x0100
+
+#define HW_APBH_DEVSEL (0x00000040)
+
+#define BP_APBH_DEVSEL_CH15 30
+#define BM_APBH_DEVSEL_CH15 0xC0000000
+#define BF_APBH_DEVSEL_CH15(v) \
+ (((v) << 30) & BM_APBH_DEVSEL_CH15)
+#define BP_APBH_DEVSEL_CH14 28
+#define BM_APBH_DEVSEL_CH14 0x30000000
+#define BF_APBH_DEVSEL_CH14(v) \
+ (((v) << 28) & BM_APBH_DEVSEL_CH14)
+#define BP_APBH_DEVSEL_CH13 26
+#define BM_APBH_DEVSEL_CH13 0x0C000000
+#define BF_APBH_DEVSEL_CH13(v) \
+ (((v) << 26) & BM_APBH_DEVSEL_CH13)
+#define BP_APBH_DEVSEL_CH12 24
+#define BM_APBH_DEVSEL_CH12 0x03000000
+#define BF_APBH_DEVSEL_CH12(v) \
+ (((v) << 24) & BM_APBH_DEVSEL_CH12)
+#define BP_APBH_DEVSEL_CH11 22
+#define BM_APBH_DEVSEL_CH11 0x00C00000
+#define BF_APBH_DEVSEL_CH11(v) \
+ (((v) << 22) & BM_APBH_DEVSEL_CH11)
+#define BP_APBH_DEVSEL_CH10 20
+#define BM_APBH_DEVSEL_CH10 0x00300000
+#define BF_APBH_DEVSEL_CH10(v) \
+ (((v) << 20) & BM_APBH_DEVSEL_CH10)
+#define BP_APBH_DEVSEL_CH9 18
+#define BM_APBH_DEVSEL_CH9 0x000C0000
+#define BF_APBH_DEVSEL_CH9(v) \
+ (((v) << 18) & BM_APBH_DEVSEL_CH9)
+#define BP_APBH_DEVSEL_CH8 16
+#define BM_APBH_DEVSEL_CH8 0x00030000
+#define BF_APBH_DEVSEL_CH8(v) \
+ (((v) << 16) & BM_APBH_DEVSEL_CH8)
+#define BP_APBH_DEVSEL_CH7 14
+#define BM_APBH_DEVSEL_CH7 0x0000C000
+#define BF_APBH_DEVSEL_CH7(v) \
+ (((v) << 14) & BM_APBH_DEVSEL_CH7)
+#define BP_APBH_DEVSEL_CH6 12
+#define BM_APBH_DEVSEL_CH6 0x00003000
+#define BF_APBH_DEVSEL_CH6(v) \
+ (((v) << 12) & BM_APBH_DEVSEL_CH6)
+#define BP_APBH_DEVSEL_CH5 10
+#define BM_APBH_DEVSEL_CH5 0x00000C00
+#define BF_APBH_DEVSEL_CH5(v) \
+ (((v) << 10) & BM_APBH_DEVSEL_CH5)
+#define BP_APBH_DEVSEL_CH4 8
+#define BM_APBH_DEVSEL_CH4 0x00000300
+#define BF_APBH_DEVSEL_CH4(v) \
+ (((v) << 8) & BM_APBH_DEVSEL_CH4)
+#define BP_APBH_DEVSEL_CH3 6
+#define BM_APBH_DEVSEL_CH3 0x000000C0
+#define BF_APBH_DEVSEL_CH3(v) \
+ (((v) << 6) & BM_APBH_DEVSEL_CH3)
+#define BP_APBH_DEVSEL_CH2 4
+#define BM_APBH_DEVSEL_CH2 0x00000030
+#define BF_APBH_DEVSEL_CH2(v) \
+ (((v) << 4) & BM_APBH_DEVSEL_CH2)
+#define BP_APBH_DEVSEL_CH1 2
+#define BM_APBH_DEVSEL_CH1 0x0000000C
+#define BF_APBH_DEVSEL_CH1(v) \
+ (((v) << 2) & BM_APBH_DEVSEL_CH1)
+#define BP_APBH_DEVSEL_CH0 0
+#define BM_APBH_DEVSEL_CH0 0x00000003
+#define BF_APBH_DEVSEL_CH0(v) \
+ (((v) << 0) & BM_APBH_DEVSEL_CH0)
+
+#define HW_APBH_DMA_BURST_SIZE (0x00000050)
+
+#define BP_APBH_DMA_BURST_SIZE_CH15 30
+#define BM_APBH_DMA_BURST_SIZE_CH15 0xC0000000
+#define BF_APBH_DMA_BURST_SIZE_CH15(v) \
+ (((v) << 30) & BM_APBH_DMA_BURST_SIZE_CH15)
+#define BP_APBH_DMA_BURST_SIZE_CH14 28
+#define BM_APBH_DMA_BURST_SIZE_CH14 0x30000000
+#define BF_APBH_DMA_BURST_SIZE_CH14(v) \
+ (((v) << 28) & BM_APBH_DMA_BURST_SIZE_CH14)
+#define BP_APBH_DMA_BURST_SIZE_CH13 26
+#define BM_APBH_DMA_BURST_SIZE_CH13 0x0C000000
+#define BF_APBH_DMA_BURST_SIZE_CH13(v) \
+ (((v) << 26) & BM_APBH_DMA_BURST_SIZE_CH13)
+#define BP_APBH_DMA_BURST_SIZE_CH12 24
+#define BM_APBH_DMA_BURST_SIZE_CH12 0x03000000
+#define BF_APBH_DMA_BURST_SIZE_CH12(v) \
+ (((v) << 24) & BM_APBH_DMA_BURST_SIZE_CH12)
+#define BP_APBH_DMA_BURST_SIZE_CH11 22
+#define BM_APBH_DMA_BURST_SIZE_CH11 0x00C00000
+#define BF_APBH_DMA_BURST_SIZE_CH11(v) \
+ (((v) << 22) & BM_APBH_DMA_BURST_SIZE_CH11)
+#define BP_APBH_DMA_BURST_SIZE_CH10 20
+#define BM_APBH_DMA_BURST_SIZE_CH10 0x00300000
+#define BF_APBH_DMA_BURST_SIZE_CH10(v) \
+ (((v) << 20) & BM_APBH_DMA_BURST_SIZE_CH10)
+#define BP_APBH_DMA_BURST_SIZE_CH9 18
+#define BM_APBH_DMA_BURST_SIZE_CH9 0x000C0000
+#define BF_APBH_DMA_BURST_SIZE_CH9(v) \
+ (((v) << 18) & BM_APBH_DMA_BURST_SIZE_CH9)
+#define BP_APBH_DMA_BURST_SIZE_CH8 16
+#define BM_APBH_DMA_BURST_SIZE_CH8 0x00030000
+#define BF_APBH_DMA_BURST_SIZE_CH8(v) \
+ (((v) << 16) & BM_APBH_DMA_BURST_SIZE_CH8)
+#define BV_APBH_DMA_BURST_SIZE_CH8__BURST0 0x0
+#define BV_APBH_DMA_BURST_SIZE_CH8__BURST4 0x1
+#define BV_APBH_DMA_BURST_SIZE_CH8__BURST8 0x2
+#define BP_APBH_DMA_BURST_SIZE_CH7 14
+#define BM_APBH_DMA_BURST_SIZE_CH7 0x0000C000
+#define BF_APBH_DMA_BURST_SIZE_CH7(v) \
+ (((v) << 14) & BM_APBH_DMA_BURST_SIZE_CH7)
+#define BP_APBH_DMA_BURST_SIZE_CH6 12
+#define BM_APBH_DMA_BURST_SIZE_CH6 0x00003000
+#define BF_APBH_DMA_BURST_SIZE_CH6(v) \
+ (((v) << 12) & BM_APBH_DMA_BURST_SIZE_CH6)
+#define BP_APBH_DMA_BURST_SIZE_CH5 10
+#define BM_APBH_DMA_BURST_SIZE_CH5 0x00000C00
+#define BF_APBH_DMA_BURST_SIZE_CH5(v) \
+ (((v) << 10) & BM_APBH_DMA_BURST_SIZE_CH5)
+#define BP_APBH_DMA_BURST_SIZE_CH4 8
+#define BM_APBH_DMA_BURST_SIZE_CH4 0x00000300
+#define BF_APBH_DMA_BURST_SIZE_CH4(v) \
+ (((v) << 8) & BM_APBH_DMA_BURST_SIZE_CH4)
+#define BP_APBH_DMA_BURST_SIZE_CH3 6
+#define BM_APBH_DMA_BURST_SIZE_CH3 0x000000C0
+#define BF_APBH_DMA_BURST_SIZE_CH3(v) \
+ (((v) << 6) & BM_APBH_DMA_BURST_SIZE_CH3)
+#define BP_APBH_DMA_BURST_SIZE_CH2 4
+#define BM_APBH_DMA_BURST_SIZE_CH2 0x00000030
+#define BF_APBH_DMA_BURST_SIZE_CH2(v) \
+ (((v) << 4) & BM_APBH_DMA_BURST_SIZE_CH2)
+#define BP_APBH_DMA_BURST_SIZE_CH1 2
+#define BM_APBH_DMA_BURST_SIZE_CH1 0x0000000C
+#define BF_APBH_DMA_BURST_SIZE_CH1(v) \
+ (((v) << 2) & BM_APBH_DMA_BURST_SIZE_CH1)
+#define BP_APBH_DMA_BURST_SIZE_CH0 0
+#define BM_APBH_DMA_BURST_SIZE_CH0 0x00000003
+#define BF_APBH_DMA_BURST_SIZE_CH0(v) \
+ (((v) << 0) & BM_APBH_DMA_BURST_SIZE_CH0)
+
+#define HW_APBH_DEBUG (0x00000060)
+
+#define BP_APBH_DEBUG_RSVD 1
+#define BM_APBH_DEBUG_RSVD 0xFFFFFFFE
+#define BF_APBH_DEBUG_RSVD(v) \
+ (((v) << 1) & BM_APBH_DEBUG_RSVD)
+#define BM_APBH_DEBUG_GPMI_ONE_FIFO 0x00000001
+
+/*
+ * multi-register-define name HW_APBH_CHn_CURCMDAR
+ * base 0x00000100
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_CURCMDAR(n) (0x00000100 + (n) * 0x70)
+#define BP_APBH_CHn_CURCMDAR_CMD_ADDR 0
+#define BM_APBH_CHn_CURCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBH_CHn_CURCMDAR_CMD_ADDR(v) (v)
+
+/*
+ * multi-register-define name HW_APBH_CHn_NXTCMDAR
+ * base 0x00000110
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_NXTCMDAR(n) (0x00000110 + (n) * 0x70)
+#define BP_APBH_CHn_NXTCMDAR_CMD_ADDR 0
+#define BM_APBH_CHn_NXTCMDAR_CMD_ADDR 0xFFFFFFFF
+#define BF_APBH_CHn_NXTCMDAR_CMD_ADDR(v) (v)
+
+/*
+ * multi-register-define name HW_APBH_CHn_CMD
+ * base 0x00000120
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_CMD(n) (0x00000120 + (n) * 0x70)
+#define BP_APBH_CHn_CMD_XFER_COUNT 16
+#define BM_APBH_CHn_CMD_XFER_COUNT 0xFFFF0000
+#define BF_APBH_CHn_CMD_XFER_COUNT(v) \
+ (((v) << 16) & BM_APBH_CHn_CMD_XFER_COUNT)
+#define BP_APBH_CHn_CMD_CMDWORDS 12
+#define BM_APBH_CHn_CMD_CMDWORDS 0x0000F000
+#define BF_APBH_CHn_CMD_CMDWORDS(v) \
+ (((v) << 12) & BM_APBH_CHn_CMD_CMDWORDS)
+#define BP_APBH_CHn_CMD_RSVD1 9
+#define BM_APBH_CHn_CMD_RSVD1 0x00000E00
+#define BF_APBH_CHn_CMD_RSVD1(v) \
+ (((v) << 9) & BM_APBH_CHn_CMD_RSVD1)
+#define BM_APBH_CHn_CMD_HALTONTERMINATE 0x00000100
+#define BM_APBH_CHn_CMD_WAIT4ENDCMD 0x00000080
+#define BM_APBH_CHn_CMD_SEMAPHORE 0x00000040
+#define BM_APBH_CHn_CMD_NANDWAIT4READY 0x00000020
+#define BM_APBH_CHn_CMD_NANDLOCK 0x00000010
+#define BM_APBH_CHn_CMD_IRQONCMPLT 0x00000008
+#define BM_APBH_CHn_CMD_CHAIN 0x00000004
+#define BP_APBH_CHn_CMD_COMMAND 0
+#define BM_APBH_CHn_CMD_COMMAND 0x00000003
+#define BF_APBH_CHn_CMD_COMMAND(v) \
+ (((v) << 0) & BM_APBH_CHn_CMD_COMMAND)
+#define BV_APBH_CHn_CMD_COMMAND__NO_DMA_XFER 0x0
+#define BV_APBH_CHn_CMD_COMMAND__DMA_WRITE 0x1
+#define BV_APBH_CHn_CMD_COMMAND__DMA_READ 0x2
+#define BV_APBH_CHn_CMD_COMMAND__DMA_SENSE 0x3
+
+/*
+ * multi-register-define name HW_APBH_CHn_BAR
+ * base 0x00000130
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_BAR(n) (0x00000130 + (n) * 0x70)
+#define BP_APBH_CHn_BAR_ADDRESS 0
+#define BM_APBH_CHn_BAR_ADDRESS 0xFFFFFFFF
+#define BF_APBH_CHn_BAR_ADDRESS(v) (v)
+
+/*
+ * multi-register-define name HW_APBH_CHn_SEMA
+ * base 0x00000140
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_SEMA(n) (0x00000140 + (n) * 0x70)
+#define BP_APBH_CHn_SEMA_RSVD2 24
+#define BM_APBH_CHn_SEMA_RSVD2 0xFF000000
+#define BF_APBH_CHn_SEMA_RSVD2(v) \
+ (((v) << 24) & BM_APBH_CHn_SEMA_RSVD2)
+#define BP_APBH_CHn_SEMA_PHORE 16
+#define BM_APBH_CHn_SEMA_PHORE 0x00FF0000
+#define BF_APBH_CHn_SEMA_PHORE(v) \
+ (((v) << 16) & BM_APBH_CHn_SEMA_PHORE)
+#define BP_APBH_CHn_SEMA_RSVD1 8
+#define BM_APBH_CHn_SEMA_RSVD1 0x0000FF00
+#define BF_APBH_CHn_SEMA_RSVD1(v) \
+ (((v) << 8) & BM_APBH_CHn_SEMA_RSVD1)
+#define BP_APBH_CHn_SEMA_INCREMENT_SEMA 0
+#define BM_APBH_CHn_SEMA_INCREMENT_SEMA 0x000000FF
+#define BF_APBH_CHn_SEMA_INCREMENT_SEMA(v) \
+ (((v) << 0) & BM_APBH_CHn_SEMA_INCREMENT_SEMA)
+
+/*
+ * multi-register-define name HW_APBH_CHn_DEBUG1
+ * base 0x00000150
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_DEBUG1(n) (0x00000150 + (n) * 0x70)
+#define BM_APBH_CHn_DEBUG1_REQ 0x80000000
+#define BM_APBH_CHn_DEBUG1_BURST 0x40000000
+#define BM_APBH_CHn_DEBUG1_KICK 0x20000000
+#define BM_APBH_CHn_DEBUG1_END 0x10000000
+#define BM_APBH_CHn_DEBUG1_SENSE 0x08000000
+#define BM_APBH_CHn_DEBUG1_READY 0x04000000
+#define BM_APBH_CHn_DEBUG1_LOCK 0x02000000
+#define BM_APBH_CHn_DEBUG1_NEXTCMDADDRVALID 0x01000000
+#define BM_APBH_CHn_DEBUG1_RD_FIFO_EMPTY 0x00800000
+#define BM_APBH_CHn_DEBUG1_RD_FIFO_FULL 0x00400000
+#define BM_APBH_CHn_DEBUG1_WR_FIFO_EMPTY 0x00200000
+#define BM_APBH_CHn_DEBUG1_WR_FIFO_FULL 0x00100000
+#define BP_APBH_CHn_DEBUG1_RSVD1 5
+#define BM_APBH_CHn_DEBUG1_RSVD1 0x000FFFE0
+#define BF_APBH_CHn_DEBUG1_RSVD1(v) \
+ (((v) << 5) & BM_APBH_CHn_DEBUG1_RSVD1)
+#define BP_APBH_CHn_DEBUG1_STATEMACHINE 0
+#define BM_APBH_CHn_DEBUG1_STATEMACHINE 0x0000001F
+#define BF_APBH_CHn_DEBUG1_STATEMACHINE(v) \
+ (((v) << 0) & BM_APBH_CHn_DEBUG1_STATEMACHINE)
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__IDLE 0x00
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__REQ_CMD1 0x01
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__REQ_CMD3 0x02
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__REQ_CMD2 0x03
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__XFER_DECODE 0x04
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__REQ_WAIT 0x05
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__REQ_CMD4 0x06
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__PIO_REQ 0x07
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__READ_FLUSH 0x08
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__READ_WAIT 0x09
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__WRITE 0x0C
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__READ_REQ 0x0D
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__CHECK_CHAIN 0x0E
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__XFER_COMPLETE 0x0F
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__TERMINATE 0x14
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__WAIT_END 0x15
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__WRITE_WAIT 0x1C
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__HALT_AFTER_TERM 0x1D
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__CHECK_WAIT 0x1E
+#define BV_APBH_CHn_DEBUG1_STATEMACHINE__WAIT_READY 0x1F
+
+/*
+ * multi-register-define name HW_APBH_CHn_DEBUG2
+ * base 0x00000160
+ * count 16
+ * offset 0x70
+ */
+#define HW_APBH_CHn_DEBUG2(n) (0x00000160 + (n) * 0x70)
+#define BP_APBH_CHn_DEBUG2_APB_BYTES 16
+#define BM_APBH_CHn_DEBUG2_APB_BYTES 0xFFFF0000
+#define BF_APBH_CHn_DEBUG2_APB_BYTES(v) \
+ (((v) << 16) & BM_APBH_CHn_DEBUG2_APB_BYTES)
+#define BP_APBH_CHn_DEBUG2_AHB_BYTES 0
+#define BM_APBH_CHn_DEBUG2_AHB_BYTES 0x0000FFFF
+#define BF_APBH_CHn_DEBUG2_AHB_BYTES(v) \
+ (((v) << 0) & BM_APBH_CHn_DEBUG2_AHB_BYTES)
+
+#define HW_APBH_VERSION (0x00000800)
+
+#define BP_APBH_VERSION_MAJOR 24
+#define BM_APBH_VERSION_MAJOR 0xFF000000
+#define BF_APBH_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_APBH_VERSION_MAJOR)
+#define BP_APBH_VERSION_MINOR 16
+#define BM_APBH_VERSION_MINOR 0x00FF0000
+#define BF_APBH_VERSION_MINOR(v) \
+ (((v) << 16) & BM_APBH_VERSION_MINOR)
+#define BP_APBH_VERSION_STEP 0
+#define BM_APBH_VERSION_STEP 0x0000FFFF
+#define BF_APBH_VERSION_STEP(v) \
+ (((v) << 0) & BM_APBH_VERSION_STEP)
+#endif /* __ARCH_ARM___APBH_H */
diff --git a/arch/arm/mach-mx5/sdma_script_code_mx50.h b/arch/arm/mach-mx5/sdma_script_code_mx50.h
new file mode 100644
index 000000000000..49a79213c54b
--- /dev/null
+++ b/arch/arm/mach-mx5/sdma_script_code_mx50.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ * @file sdma_script_code.h
+ * @brief This file contains functions of SDMA scripts code initialization
+ *
+ * The file was generated automatically. Based on sdma scripts library.
+ *
+ * @ingroup SDMA
+ */
+/*******************************************************************************
+
+ SDMA RELEASE LABEL: "SDMA_CODEX.01.00.00"
+
+*******************************************************************************/
+
+#ifndef SDMA_SCRIPT_CODE_MX50_H
+#define SDMA_SCRIPT_CODE_MX50_H
+
+
+/*!
+* SDMA ROM scripts start addresses and sizes
+*/
+
+#define start_ADDR_MX50 0
+#define start_SIZE_MX50 18
+
+#define core_ADDR_MX50 80
+#define core_SIZE_MX50 232
+
+#define common_ADDR_MX50 312
+#define common_SIZE_MX50 330
+
+#define ap_2_ap_ADDR_MX50 642
+#define ap_2_ap_SIZE_MX50 41
+
+#define app_2_mcu_ADDR_MX50 683
+#define app_2_mcu_SIZE_MX50 64
+
+#define mcu_2_app_ADDR_MX50 747
+#define mcu_2_app_SIZE_MX50 70
+
+#define uart_2_mcu_ADDR_MX50 817
+#define uart_2_mcu_SIZE_MX50 74
+
+#define shp_2_mcu_ADDR_MX50 891
+#define shp_2_mcu_SIZE_MX50 69
+
+#define mcu_2_shp_ADDR_MX50 960
+#define mcu_2_shp_SIZE_MX50 72
+
+#define uartsh_2_mcu_ADDR_MX50 1032
+#define uartsh_2_mcu_SIZE_MX50 68
+
+#define loop_DMAs_routines_ADDR_MX50 1100
+#define loop_DMAs_routines_SIZE_MX50 227
+
+#define test_ADDR_MX50 1327
+#define test_SIZE_MX50 63
+
+#define signature_ADDR_MX50 1023
+#define signature_SIZE_MX50 1
+
+/*!
+* SDMA RAM scripts start addresses and sizes
+*/
+
+#define mcu_2_ssiapp_ADDR_MX50 6144
+#define mcu_2_ssiapp_SIZE_MX50 96
+
+#define mcu_2_ssish_ADDR_MX50 6240
+#define mcu_2_ssish_SIZE_MX50 95
+
+/*!
+* SDMA RAM image start address and size
+*/
+
+#define RAM_CODE_START_ADDR_MX50 6144
+#define RAM_CODE_SIZE_MX50 191
+
+/*!
+* Buffer that holds the SDMA RAM image
+*/
+__attribute__ ((__aligned__(4)))
+static const short sdma_code_mx50[] = {
+0xc1e3, 0x57db, 0x52f3, 0x6a01, 0x008f, 0x00d5, 0x7d01, 0x008d,
+0x05a0, 0x5deb, 0x0478, 0x7d03, 0x0479, 0x7d2c, 0x7c36, 0x0479,
+0x7c1f, 0x56ee, 0x0f00, 0x0660, 0x7d05, 0x6509, 0x7e43, 0x620a,
+0x7e41, 0x981e, 0x620a, 0x7e3e, 0x6509, 0x7e3c, 0x0512, 0x0512,
+0x02ad, 0x0760, 0x7d03, 0x55fb, 0x6dd3, 0x9829, 0x55fb, 0x1d04,
+0x6dd3, 0x6ac8, 0x7f2f, 0x1f01, 0x2003, 0x4800, 0x7ce4, 0x9851,
+0x55fb, 0x6dd7, 0x0015, 0x7805, 0x6209, 0x6ac8, 0x6209, 0x6ac8,
+0x6dd7, 0x9850, 0x55fb, 0x6dd7, 0x0015, 0x0015, 0x7805, 0x620a,
+0x6ac8, 0x620a, 0x6ac8, 0x6dd7, 0x9850, 0x55fb, 0x6dd7, 0x0015,
+0x0015, 0x0015, 0x7805, 0x620b, 0x6ac8, 0x620b, 0x6ac8, 0x6dd7,
+0x7c09, 0x6ddf, 0x7f07, 0x0000, 0x55eb, 0x4d00, 0x7d07, 0xc1fa,
+0x57db, 0x9804, 0x0007, 0x68cc, 0x680c, 0xc213, 0xc20a, 0x9801,
+0xc1d9, 0xc1e3, 0x57db, 0x52f3, 0x6a21, 0x008f, 0x00d5, 0x7d01,
+0x008d, 0x05a0, 0x5deb, 0x56fb, 0x0478, 0x7d03, 0x0479, 0x7d32,
+0x7c39, 0x0479, 0x7c28, 0x0b70, 0x0311, 0x53eb, 0x0f00, 0x0360,
+0x7d05, 0x6509, 0x7e3f, 0x620a, 0x7e3d, 0x9882, 0x620a, 0x7e3a,
+0x6509, 0x7e38, 0x0512, 0x0512, 0x02ad, 0x0760, 0x7d0a, 0x5a06,
+0x7f31, 0x1f01, 0x2003, 0x4800, 0x7cea, 0x0b70, 0x0311, 0x5313,
+0x98b3, 0x5a26, 0x7f27, 0x1f01, 0x2003, 0x4800, 0x7ce0, 0x0b70,
+0x0311, 0x5313, 0x98b3, 0x0015, 0x7804, 0x6209, 0x5a06, 0x6209,
+0x5a26, 0x98b2, 0x0015, 0x0015, 0x7804, 0x620a, 0x5a06, 0x620a,
+0x5a26, 0x98b2, 0x0015, 0x0015, 0x0015, 0x7804, 0x620b, 0x5a06,
+0x620b, 0x5a26, 0x7c07, 0x0000, 0x55eb, 0x4d00, 0x7d06, 0xc1fa,
+0x57db, 0x9865, 0x0007, 0x680c, 0xc213, 0xc20a, 0x9862
+};
+#endif
diff --git a/arch/arm/mach-mx5/sdma_script_code_mx51.h b/arch/arm/mach-mx5/sdma_script_code_mx51.h
new file mode 100644
index 000000000000..9a396c92ebea
--- /dev/null
+++ b/arch/arm/mach-mx5/sdma_script_code_mx51.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*!
+ * @file sdma_script_code.h
+ * @brief This file contains functions of SDMA scripts code initialization
+ *
+ * The file was generated automatically. Based on sdma scripts library.
+ *
+ * @ingroup SDMA
+ */
+/*******************************************************************************
+
+ SDMA RELEASE LABEL: "SS15_ELVIS V1.1"
+
+*******************************************************************************/
+
+#ifndef __SDMA_SCRIPT_CODE_H__
+#define __SDMA_SCRIPT_CODE_H__
+
+/*!
+* SDMA ROM scripts start addresses and sizes
+*/
+
+#define start_ADDR_MX51 0
+#define start_SIZE_MX51 24
+
+#define core_ADDR_MX51 80
+#define core_SIZE_MX51 232
+
+#define common_ADDR_MX51 312
+#define common_SIZE_MX51 330
+
+#define ap_2_ap_ADDR_MX51 642
+#define ap_2_ap_SIZE_MX51 41
+
+#define app_2_mcu_ADDR_MX51 683
+#define app_2_mcu_SIZE_MX51 64
+
+#define mcu_2_app_ADDR_MX51 747
+#define mcu_2_app_SIZE_MX51 70
+
+#define uart_2_mcu_ADDR_MX51 817
+#define uart_2_mcu_SIZE_MX51 75
+
+#define shp_2_mcu_ADDR_MX51 892
+#define shp_2_mcu_SIZE_MX51 69
+
+#define mcu_2_shp_ADDR_MX51 961
+#define mcu_2_shp_SIZE_MX51 72
+
+#define app_2_per_ADDR_MX51 1033
+#define app_2_per_SIZE_MX51 66
+
+#define per_2_app_ADDR_MX51 1099
+#define per_2_app_SIZE_MX51 74
+
+#define per_2_shp_ADDR_MX51 1173
+#define per_2_shp_SIZE_MX51 78
+
+#define shp_2_per_ADDR_MX51 1251
+#define shp_2_per_SIZE_MX51 72
+
+#define uartsh_2_mcu_ADDR_MX51 1323
+#define uartsh_2_mcu_SIZE_MX51 69
+
+#define mcu_2_ata_ADDR_MX51 1392
+#define mcu_2_ata_SIZE_MX51 81
+
+#define ata_2_mcu_ADDR_MX51 1473
+#define ata_2_mcu_SIZE_MX51 96
+
+#define loop_DMAs_routines_ADDR_MX51 1569
+#define loop_DMAs_routines_SIZE_MX51 227
+
+#define test_ADDR_MX51 1796
+#define test_SIZE_MX51 63
+
+#define signature_ADDR_MX51 1023
+#define signature_SIZE_MX51 1
+
+/*!
+* SDMA RAM scripts start addresses and sizes
+*/
+
+#define ext_mem__ipu_ram_ADDR_MX51 6144
+#define ext_mem__ipu_ram_SIZE_MX51 123
+
+#define firi_2_mcu_ADDR_MX51 6267
+#define firi_2_mcu_SIZE_MX51 97
+
+#define mcu_2_firi_ADDR_MX51 6364
+#define mcu_2_firi_SIZE_MX51 79
+
+#define mcu_2_spdif_ADDR_MX51 6443
+#define mcu_2_spdif_SIZE_MX51 59
+
+#define mcu_2_ssiapp_ADDR_MX51 6502
+#define mcu_2_ssiapp_SIZE_MX51 98
+
+#define mcu_2_ssish_ADDR_MX51 6600
+#define mcu_2_ssish_SIZE_MX51 89
+
+#define ssiapp_2_mcu_ADDR_MX51 6689
+#define ssiapp_2_mcu_SIZE_MX51 94
+
+#define ssish_2_mcu_ADDR_MX51 6783
+#define ssish_2_mcu_SIZE_MX51 84
+
+#define uart_2_per_ADDR_MX51 6867
+#define uart_2_per_SIZE_MX51 73
+
+#define uartsh_2_per_ADDR_MX51 6940
+#define uartsh_2_per_SIZE_MX51 67
+
+/*!
+* SDMA RAM image start address and size
+*/
+
+#define RAM_CODE_START_ADDR_MX51 6144
+#define RAM_CODE_SIZE_MX51 863
+
+/*!
+* Buffer that holds the SDMA RAM image
+*/
+__attribute__ ((__aligned__(4)))
+#ifndef CONFIG_XIP_KERNEL
+const
+#endif
+static const short sdma_code_mx51[] = {
+0x0e70, 0x0611, 0x5616, 0xc13c, 0x7d2a, 0x5ade, 0x008e, 0xc14e,
+0x7c26, 0x5be0, 0x5ef0, 0x5ce8, 0x0688, 0x08ff, 0x0011, 0x28ff,
+0x00bc, 0x53f6, 0x05df, 0x7d0b, 0x6dc5, 0x03df, 0x7d03, 0x6bd5,
+0xd84f, 0x982b, 0x6b05, 0xc681, 0x7e27, 0x7f29, 0x982b, 0x6d01,
+0x03df, 0x7d05, 0x6bd5, 0xc6ab, 0x7e18, 0x7f1a, 0x982b, 0x6b05,
+0xc621, 0x7e07, 0x7f06, 0x52de, 0x53e6, 0xc159, 0x7dd7, 0x0200,
+0x9803, 0x0007, 0x6004, 0x680c, 0x53f6, 0x028e, 0x00a3, 0xc256,
+0x048b, 0x0498, 0x0454, 0x068a, 0x982b, 0x0207, 0x680c, 0x6ddf,
+0x0107, 0x68ff, 0x60d0, 0x9834, 0x0207, 0x68ff, 0x6d28, 0x0107,
+0x6004, 0x680c, 0x9834, 0x0007, 0x68ff, 0x60d0, 0x9834, 0x0288,
+0x03a5, 0x3b03, 0x3d03, 0x4d00, 0x7d0a, 0x0804, 0x00a5, 0x00da,
+0x7d1a, 0x02a0, 0x7b01, 0x65d8, 0x7eee, 0x65ff, 0x7eec, 0x0804,
+0x02d0, 0x7d11, 0x4b00, 0x7c0f, 0x008a, 0x3003, 0x6dcf, 0x6bdf,
+0x0015, 0x0015, 0x7b02, 0x65d8, 0x0000, 0x7edd, 0x63ff, 0x7edb,
+0x3a03, 0x6dcd, 0x6bdd, 0x008a, 0x7b02, 0x65d8, 0x0000, 0x7ed3,
+0x65ff, 0x7ed1, 0x0006, 0x2618, 0x1e10, 0x0b70, 0x0311, 0x5313,
+0x58d3, 0x008b, 0x5efb, 0xc13c, 0x7d55, 0x5ac0, 0x5bc8, 0xc14e,
+0x7c51, 0x0388, 0x6d04, 0x0dff, 0x0511, 0x1dff, 0x05bc, 0x56fb,
+0x6ec3, 0x62c8, 0x7e38, 0x0264, 0x7d0b, 0x0212, 0x3aff, 0x02df,
+0x7c05, 0x008f, 0x05a0, 0x0015, 0x0015, 0xd8b5, 0x0400, 0x988f,
+0x56fb, 0x6ec3, 0x62c8, 0x0212, 0x3aff, 0x008a, 0x4800, 0x7d02,
+0x05a0, 0xd8c0, 0x6a28, 0x7f24, 0x008b, 0x52c0, 0x53c8, 0x04a5,
+0xc159, 0x7dd4, 0x0401, 0x0200, 0x9886, 0x1e08, 0x6ec3, 0x7802,
+0x62c8, 0x6a0b, 0x7e10, 0x6a28, 0x7f13, 0x0000, 0x2608, 0x0006,
+0x1e08, 0x6ec1, 0x7802, 0x62c8, 0x6a09, 0x7e05, 0x6a28, 0x7f08,
+0x0000, 0x2608, 0x0006, 0x0007, 0x68cc, 0x6a28, 0x7f01, 0x98d9,
+0x0007, 0x6a0c, 0x6a0c, 0x6204, 0x6a04, 0x6a2b, 0x6a28, 0x0007,
+0x680c, 0x0454, 0x0200, 0x9883, 0x0b70, 0x0311, 0x5313, 0x58d3,
+0x008b, 0x5efb, 0xc13c, 0x7d45, 0x5ac0, 0x5bc8, 0xc14e, 0x56f8,
+0x7c40, 0x6ed1, 0x0388, 0x6d00, 0x0dff, 0x0511, 0x1dff, 0x05bc,
+0x4d00, 0x7d2f, 0x0e70, 0x0611, 0x522e, 0x02b9, 0x4a00, 0x7c09,
+0x52fe, 0x50d3, 0x02b8, 0x4a00, 0x7c04, 0x62ff, 0x7e1c, 0x0400,
+0x98f2, 0x008f, 0x00d5, 0x7d0b, 0x008d, 0x05a0, 0x56fb, 0x6ed1,
+0x7802, 0x6209, 0x6ac8, 0x0000, 0x7e11, 0x7f0d, 0x98f0, 0x05a0,
+0x0015, 0x0015, 0x56fb, 0x6ed3, 0x7802, 0x620b, 0x6ac8, 0x0000,
+0x7e05, 0x7f01, 0x98f0, 0x0007, 0x68cc, 0x9920, 0x0007, 0x6a0c,
+0x0454, 0x62ff, 0x7efb, 0x008b, 0x52c0, 0x53c8, 0xc159, 0x7dbd,
+0x0401, 0x0200, 0x98e2, 0xc1d9, 0xc1e3, 0x57db, 0x52f3, 0x6a01,
+0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x56fb, 0x0478,
+0x7d28, 0x0479, 0x7c16, 0x0015, 0x0015, 0x0388, 0x620a, 0x0808,
+0x7801, 0x0217, 0x5a06, 0x7f1d, 0x620a, 0x0808, 0x7801, 0x0217,
+0x5a26, 0x7f17, 0x2301, 0x4b00, 0x7cf1, 0x0b70, 0x0311, 0x5313,
+0x995a, 0x0015, 0x0015, 0x0015, 0x7804, 0x620b, 0x5a06, 0x620b,
+0x5a26, 0x7c07, 0x0000, 0x55eb, 0x4d00, 0x7d06, 0xc1fa, 0x57db,
+0x9930, 0x0007, 0x680c, 0xc213, 0xc20a, 0x992d, 0xc1e3, 0x57db,
+0x5fe3, 0x57e3, 0x52f3, 0x6a01, 0x008f, 0x00d5, 0x7d01, 0x008d,
+0x05a0, 0x5deb, 0x0478, 0x7d03, 0x0479, 0x7d2c, 0x7c36, 0x0479,
+0x7c1f, 0x56ee, 0x0f00, 0x0660, 0x7d05, 0x6509, 0x7e43, 0x620a,
+0x7e41, 0x9986, 0x620a, 0x7e3e, 0x6509, 0x7e3c, 0x0512, 0x0512,
+0x02ad, 0x0760, 0x7d03, 0x55fb, 0x6dd3, 0x9991, 0x55fb, 0x1d04,
+0x6dd3, 0x6ac8, 0x7f2f, 0x1f01, 0x2003, 0x4800, 0x7ce4, 0x99b9,
+0x55fb, 0x6dd7, 0x0015, 0x7805, 0x6209, 0x6ac8, 0x6209, 0x6ac8,
+0x6dd7, 0x99b8, 0x55fb, 0x6dd7, 0x0015, 0x0015, 0x7805, 0x620a,
+0x6ac8, 0x620a, 0x6ac8, 0x6dd7, 0x99b8, 0x55fb, 0x6dd7, 0x0015,
+0x0015, 0x0015, 0x7805, 0x620b, 0x6ac8, 0x620b, 0x6ac8, 0x6dd7,
+0x7c09, 0x6ddf, 0x7f07, 0x0000, 0x55eb, 0x4d00, 0x7d07, 0xc1fa,
+0x57e3, 0x996c, 0x0007, 0x68cc, 0x680c, 0xc213, 0xc20a, 0x9969,
+0xc1d9, 0xc1e3, 0x57db, 0x5fe3, 0x57e3, 0x52f3, 0x6a21, 0x008f,
+0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x56fb, 0x0478, 0x7d03,
+0x0479, 0x7d2a, 0x7c31, 0x0479, 0x7c20, 0x0b70, 0x0311, 0x53eb,
+0x0f00, 0x0360, 0x7d05, 0x6509, 0x7e37, 0x620a, 0x7e35, 0x99ec,
+0x620a, 0x7e32, 0x6509, 0x7e30, 0x0512, 0x0512, 0x02ad, 0x0760,
+0x7c02, 0x5a06, 0x99f4, 0x5a26, 0x7f27, 0x1f01, 0x2003, 0x4800,
+0x7ce8, 0x0b70, 0x0311, 0x5313, 0x9a15, 0x0015, 0x7804, 0x6209,
+0x5a06, 0x6209, 0x5a26, 0x9a14, 0x0015, 0x0015, 0x7804, 0x620a,
+0x5a06, 0x620a, 0x5a26, 0x9a14, 0x0015, 0x0015, 0x0015, 0x7804,
+0x620b, 0x5a06, 0x620b, 0x5a26, 0x7c07, 0x0000, 0x55eb, 0x4d00,
+0x7d06, 0xc1fa, 0x57e3, 0x99cf, 0x0007, 0x680c, 0xc213, 0xc20a,
+0x99cc, 0xc1e3, 0x57db, 0x52fb, 0x6ac3, 0x52f3, 0x6a05, 0x008f,
+0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x0478, 0x7d03, 0x0479,
+0x7d2b, 0x7c1e, 0x0479, 0x7c33, 0x56ee, 0x0f00, 0x55fb, 0x0760,
+0x7d02, 0x6dc3, 0x9a3d, 0x1d04, 0x6dc3, 0x62c8, 0x7e3c, 0x0660,
+0x7d02, 0x0210, 0x0212, 0x6a09, 0x7f36, 0x0212, 0x6a09, 0x7f33,
+0x0212, 0x6a09, 0x7f30, 0x1f01, 0x2003, 0x4800, 0x7ce7, 0x9a71,
+0x55fb, 0x6dc7, 0x0015, 0x0015, 0x0015, 0x7805, 0x62c8, 0x6a0b,
+0x62c8, 0x6a0b, 0x6dc7, 0x9a70, 0x55fb, 0x6dc7, 0x0015, 0x0015,
+0x7805, 0x62c8, 0x6a0a, 0x62c8, 0x6a0a, 0x6dc7, 0x9a70, 0x55fb,
+0x6dc7, 0x0015, 0x7805, 0x62c8, 0x6a09, 0x62c8, 0x6a09, 0x6dc7,
+0x7c0a, 0x6a28, 0x57db, 0x7f07, 0x0000, 0x55eb, 0x4d00, 0x7d05,
+0xc1fa, 0x57db, 0x9a27, 0xc277, 0x0454, 0xc20a, 0x9a22, 0xc1d9,
+0xc1e3, 0x57db, 0x52f3, 0x6a05, 0x008f, 0x00d5, 0x7d01, 0x008d,
+0x05a0, 0x56fb, 0x0478, 0x7d03, 0x0479, 0x7d29, 0x7c1f, 0x0479,
+0x7c2e, 0x5de3, 0x0d70, 0x0511, 0x55ed, 0x0f00, 0x0760, 0x7d02,
+0x5206, 0x9a9b, 0x5226, 0x7e33, 0x0560, 0x7d02, 0x0210, 0x0212,
+0x6a09, 0x7f2d, 0x0212, 0x6a09, 0x7f2a, 0x0212, 0x6a09, 0x7f27,
+0x1f01, 0x2003, 0x4800, 0x7cea, 0x55e3, 0x9ac6, 0x0015, 0x0015,
+0x0015, 0x7804, 0x5206, 0x6a0b, 0x5226, 0x6a0b, 0x9ac5, 0x0015,
+0x0015, 0x7804, 0x5206, 0x6a0a, 0x5226, 0x6a0a, 0x9ac5, 0x0015,
+0x7804, 0x5206, 0x6a09, 0x5226, 0x6a09, 0x7c09, 0x6a28, 0x7f07,
+0x0000, 0x57db, 0x4d00, 0x7d05, 0xc1fa, 0x57db, 0x9a84, 0xc277,
+0x0454, 0xc20a, 0x9a81, 0xc1e3, 0x57db, 0x52f3, 0x6ad5, 0x56fb,
+0x028e, 0x1a94, 0x6ac3, 0x62c8, 0x0269, 0x7d1e, 0x1e94, 0x6ee3,
+0x62d0, 0x5aeb, 0x62c8, 0x0248, 0x6ed3, 0x6ac8, 0x2694, 0x52eb,
+0x6ad5, 0x6ee3, 0x62c8, 0x026e, 0x7d27, 0x6ac8, 0x7f23, 0x2501,
+0x4d00, 0x7d26, 0x028e, 0x1a98, 0x6ac3, 0x62c8, 0x6ec3, 0x0260,
+0x7df1, 0x62d0, 0xc27a, 0x9b18, 0x6ee3, 0x008f, 0x2001, 0x00d5,
+0x7d01, 0x008d, 0x05a0, 0x62c8, 0x026e, 0x7d0e, 0x6ac8, 0x7f0a,
+0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, 0x4d00, 0x7d09, 0xc1fa,
+0x57db, 0x9ad7, 0x0007, 0x6aff, 0x62d0, 0xc27a, 0x0458, 0x0454,
+0x6add, 0x7ff8, 0xc20a, 0x9ad4, 0xc1d9, 0xc1e3, 0x57db, 0x52f3,
+0x6ad5, 0x56fb, 0x028e, 0x1a94, 0x5202, 0x0269, 0x7d17, 0x1e94,
+0x5206, 0x0248, 0x5a06, 0x2694, 0x5206, 0x026e, 0x7d26, 0x6ac8,
+0x7f22, 0x2501, 0x4d00, 0x7d27, 0x028e, 0x1a98, 0x5202, 0x0260,
+0x7df3, 0x6add, 0x7f18, 0x62d0, 0xc27a, 0x9b5b, 0x008f, 0x2001,
+0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5206, 0x026e, 0x7d0e, 0x6ac8,
+0x7f0a, 0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, 0x4d00, 0x7d0b,
+0xc1fa, 0x57db, 0x9b21, 0x0007, 0x6aff, 0x6add, 0x7ffc, 0x62d0,
+0xc27a, 0x0458, 0x0454, 0x6add, 0x7ff6, 0xc20a, 0x9b1e
+};
+#endif
+
diff --git a/arch/arm/mach-mx5/sdma_script_code_mx53.h b/arch/arm/mach-mx5/sdma_script_code_mx53.h
new file mode 100644
index 000000000000..bfdf74736dcb
--- /dev/null
+++ b/arch/arm/mach-mx5/sdma_script_code_mx53.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*!
+ * @file sdma_script_code.h
+ * @brief This file contains functions of SDMA scripts code initialization
+ *
+ * The file was generated automatically. Based on sdma scripts library.
+ *
+ * @ingroup SDMA
+ */
+/************************************************************************************
+
+ SDMA RELEASE LABEL: "SDMA_RITA.01.01.00"
+
+*************************************************************************************/
+
+#ifndef SDMA_SCRIPT_CODE_H
+#define SDMA_SCRIPT_CODE_H
+
+
+/*!
+* SDMA ROM scripts start addresses and sizes
+*/
+
+#define start_ADDR_MX53 0
+#define start_SIZE_MX53 22
+
+#define core_ADDR_MX53 80
+#define core_SIZE_MX53 232
+
+#define common_ADDR_MX53 312
+#define common_SIZE_MX53 330
+
+#define ap_2_ap_ADDR_MX53 642
+#define ap_2_ap_SIZE_MX53 41
+
+#define app_2_mcu_ADDR_MX53 683
+#define app_2_mcu_SIZE_MX53 64
+
+#define mcu_2_app_ADDR_MX53 747
+#define mcu_2_app_SIZE_MX53 70
+
+#define uart_2_mcu_ADDR_MX53 817
+#define uart_2_mcu_SIZE_MX53 74
+
+#define shp_2_mcu_ADDR_MX53 891
+#define shp_2_mcu_SIZE_MX53 69
+
+#define mcu_2_shp_ADDR_MX53 960
+#define mcu_2_shp_SIZE_MX53 72
+
+#define uartsh_2_mcu_ADDR_MX53 1032
+#define uartsh_2_mcu_SIZE_MX53 68
+
+#define spdif_2_mcu_ADDR_MX53 1100
+#define spdif_2_mcu_SIZE_MX53 34
+
+#define mcu_2_spdif_ADDR_MX53 1134
+#define mcu_2_spdif_SIZE_MX53 59
+
+#define firi_2_mcu_ADDR_MX53 1193
+#define firi_2_mcu_SIZE_MX53 97
+
+#define mcu_2_firi_ADDR_MX53 1290
+#define mcu_2_firi_SIZE_MX53 79
+
+#define loop_DMAs_routines_ADDR_MX53 1369
+#define loop_DMAs_routines_SIZE_MX53 227
+
+#define test_ADDR_MX53 1596
+#define test_SIZE_MX53 63
+
+#define signature_ADDR_MX53 1023
+#define signature_SIZE_MX53 1
+
+/*!
+* SDMA RAM scripts start addresses and sizes
+*/
+
+#define mcu_2_ssiapp_ADDR_MX53 6144
+#define mcu_2_ssiapp_SIZE_MX53 98
+
+#define mcu_2_ssish_ADDR_MX53 6242
+#define mcu_2_ssish_SIZE_MX53 89
+
+#define p_2_p_ADDR_MX53 6331
+#define p_2_p_SIZE_MX53 254
+
+#define ssiapp_2_mcu_ADDR_MX53 6585
+#define ssiapp_2_mcu_SIZE_MX53 94
+
+#define ssish_2_mcu_ADDR_MX53 6679
+#define ssish_2_mcu_SIZE_MX53 84
+
+/*!
+* SDMA RAM image start address and size
+*/
+
+#define RAM_CODE_START_ADDR_MX53 6144
+#define RAM_CODE_SIZE_MX53 619
+
+/*!
+* Buffer that holds the SDMA RAM image
+*/
+__attribute__ ((__aligned__(4)))
+#ifndef CONFIG_XIP_KERNEL
+const
+#endif
+static const short sdma_code_mx53[] = {
+0xc1e3, 0x57db, 0x5fe3, 0x57e3, 0x52f3, 0x6a01, 0x008f, 0x00d5,
+0x7d01, 0x008d, 0x05a0, 0x5deb, 0x0478, 0x7d03, 0x0479, 0x7d2c,
+0x7c36, 0x0479, 0x7c1f, 0x56ee, 0x0f00, 0x0660, 0x7d05, 0x6509,
+0x7e43, 0x620a, 0x7e41, 0x9820, 0x620a, 0x7e3e, 0x6509, 0x7e3c,
+0x0512, 0x0512, 0x02ad, 0x0760, 0x7d03, 0x55fb, 0x6dd3, 0x982b,
+0x55fb, 0x1d04, 0x6dd3, 0x6ac8, 0x7f2f, 0x1f01, 0x2003, 0x4800,
+0x7ce4, 0x9853, 0x55fb, 0x6dd7, 0x0015, 0x7805, 0x6209, 0x6ac8,
+0x6209, 0x6ac8, 0x6dd7, 0x9852, 0x55fb, 0x6dd7, 0x0015, 0x0015,
+0x7805, 0x620a, 0x6ac8, 0x620a, 0x6ac8, 0x6dd7, 0x9852, 0x55fb,
+0x6dd7, 0x0015, 0x0015, 0x0015, 0x7805, 0x620b, 0x6ac8, 0x620b,
+0x6ac8, 0x6dd7, 0x7c09, 0x6ddf, 0x7f07, 0x0000, 0x55eb, 0x4d00,
+0x7d07, 0xc1fa, 0x57e3, 0x9806, 0x0007, 0x68cc, 0x680c, 0xc213,
+0xc20a, 0x9803, 0xc1d9, 0xc1e3, 0x57db, 0x5fe3, 0x57e3, 0x52f3,
+0x6a21, 0x008f, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x56fb,
+0x0478, 0x7d03, 0x0479, 0x7d2a, 0x7c31, 0x0479, 0x7c20, 0x0b70,
+0x0311, 0x53eb, 0x0f00, 0x0360, 0x7d05, 0x6509, 0x7e37, 0x620a,
+0x7e35, 0x9886, 0x620a, 0x7e32, 0x6509, 0x7e30, 0x0512, 0x0512,
+0x02ad, 0x0760, 0x7c02, 0x5a06, 0x988e, 0x5a26, 0x7f27, 0x1f01,
+0x2003, 0x4800, 0x7ce8, 0x0b70, 0x0311, 0x5313, 0x98af, 0x0015,
+0x7804, 0x6209, 0x5a06, 0x6209, 0x5a26, 0x98ae, 0x0015, 0x0015,
+0x7804, 0x620a, 0x5a06, 0x620a, 0x5a26, 0x98ae, 0x0015, 0x0015,
+0x0015, 0x7804, 0x620b, 0x5a06, 0x620b, 0x5a26, 0x7c07, 0x0000,
+0x55eb, 0x4d00, 0x7d06, 0xc1fa, 0x57e3, 0x9869, 0x0007, 0x680c,
+0xc213, 0xc20a, 0x9866, 0x0b70, 0x0311, 0x5313, 0x076c, 0x7c01,
+0xc1d9, 0x5efb, 0x068a, 0x076b, 0x7c01, 0xc1d9, 0x5ef3, 0x59db,
+0x58d3, 0x018f, 0x0110, 0x390f, 0x008b, 0xc13c, 0x7d2b, 0x5ac0,
+0x5bc8, 0xc14e, 0x7c27, 0x0388, 0x0689, 0x5ce3, 0x0dff, 0x0511,
+0x1dff, 0x05bc, 0x073e, 0x4d00, 0x7d18, 0x0870, 0x0011, 0x077e,
+0x7d09, 0x077d, 0x7d02, 0x5228, 0x98e6, 0x52f8, 0x54db, 0x02bc,
+0x02cc, 0x7c09, 0x077c, 0x7d02, 0x5228, 0x98ef, 0x52f8, 0x54d3,
+0x02bc, 0x02cc, 0x7d09, 0x0400, 0x98dd, 0x008b, 0x52c0, 0x53c8,
+0xc159, 0x7dd6, 0x0200, 0x98cd, 0x08ff, 0x00bf, 0x077f, 0x7d15,
+0x0488, 0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x028f, 0x0212,
+0x0212, 0x3aff, 0x05da, 0x7c02, 0x073e, 0x9918, 0x02a4, 0x02dd,
+0x7d02, 0x073e, 0x9918, 0x075e, 0x9918, 0x55eb, 0x0598, 0x5deb,
+0x52f3, 0x54fb, 0x076a, 0x7d26, 0x076c, 0x7d01, 0x9955, 0x076b,
+0x7c57, 0x0769, 0x7d04, 0x0768, 0x7d02, 0x0e01, 0x992f, 0x5893,
+0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802,
+0x5502, 0x5d04, 0x7c1d, 0x4e00, 0x7c08, 0x0769, 0x7d03, 0x5502,
+0x7e17, 0x993c, 0x5d04, 0x7f14, 0x0689, 0x5093, 0x4800, 0x7d01,
+0x9927, 0x99a0, 0x0015, 0x7806, 0x5502, 0x5d04, 0x074f, 0x5502,
+0x5d24, 0x072f, 0x7c01, 0x99a0, 0x0017, 0x076f, 0x7c01, 0x2001,
+0x5593, 0x009d, 0x0007, 0xd9a7, 0x98f5, 0x6cd3, 0x0769, 0x7d04,
+0x0768, 0x7d02, 0x0e01, 0x9964, 0x5893, 0x00d6, 0x7d01, 0x008e,
+0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802, 0x5502, 0x6dc8, 0x7c0f,
+0x4e00, 0x7c08, 0x0769, 0x7d03, 0x5502, 0x7e09, 0x9971, 0x6dc8,
+0x7f06, 0x0689, 0x5093, 0x4800, 0x7d01, 0x995c, 0x99a0, 0x999a,
+0x6ac3, 0x0769, 0x7d04, 0x0768, 0x7d02, 0x0e01, 0x9987, 0x5893,
+0x00d6, 0x7d01, 0x008e, 0x5593, 0x05a0, 0x5d93, 0x06a0, 0x7802,
+0x65c8, 0x5d04, 0x7c0f, 0x4e00, 0x7c08, 0x0769, 0x7d03, 0x65c8,
+0x7e09, 0x9994, 0x5d04, 0x7f06, 0x0689, 0x5093, 0x4800, 0x7d01,
+0x997f, 0x99a0, 0x5593, 0x009d, 0x0007, 0x6cff, 0xd9a7, 0x98f5,
+0x0000, 0x54e3, 0x55eb, 0x4d00, 0x7c01, 0x98f5, 0x98dd, 0x54e3,
+0x55eb, 0x0aff, 0x0211, 0x1aff, 0x077f, 0x7c02, 0x05a0, 0x99b4,
+0x009d, 0x058c, 0x05ba, 0x05a0, 0x0210, 0x04ba, 0x04ad, 0x0454,
+0x0006, 0xc1e3, 0x57db, 0x52fb, 0x6ac3, 0x52f3, 0x6a05, 0x008f,
+0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5deb, 0x0478, 0x7d03, 0x0479,
+0x7d2b, 0x7c1e, 0x0479, 0x7c33, 0x56ee, 0x0f00, 0x55fb, 0x0760,
+0x7d02, 0x6dc3, 0x99d5, 0x1d04, 0x6dc3, 0x62c8, 0x7e3c, 0x0660,
+0x7d02, 0x0210, 0x0212, 0x6a09, 0x7f36, 0x0212, 0x6a09, 0x7f33,
+0x0212, 0x6a09, 0x7f30, 0x1f01, 0x2003, 0x4800, 0x7ce7, 0x9a09,
+0x55fb, 0x6dc7, 0x0015, 0x0015, 0x0015, 0x7805, 0x62c8, 0x6a0b,
+0x62c8, 0x6a0b, 0x6dc7, 0x9a08, 0x55fb, 0x6dc7, 0x0015, 0x0015,
+0x7805, 0x62c8, 0x6a0a, 0x62c8, 0x6a0a, 0x6dc7, 0x9a08, 0x55fb,
+0x6dc7, 0x0015, 0x7805, 0x62c8, 0x6a09, 0x62c8, 0x6a09, 0x6dc7,
+0x7c0a, 0x6a28, 0x57db, 0x7f07, 0x0000, 0x55eb, 0x4d00, 0x7d05,
+0xc1fa, 0x57db, 0x99bf, 0xc277, 0x0454, 0xc20a, 0x99ba, 0xc1d9,
+0xc1e3, 0x57db, 0x52f3, 0x6a05, 0x008f, 0x00d5, 0x7d01, 0x008d,
+0x05a0, 0x56fb, 0x0478, 0x7d03, 0x0479, 0x7d29, 0x7c1f, 0x0479,
+0x7c2e, 0x5de3, 0x0d70, 0x0511, 0x55ed, 0x0f00, 0x0760, 0x7d02,
+0x5206, 0x9a33, 0x5226, 0x7e33, 0x0560, 0x7d02, 0x0210, 0x0212,
+0x6a09, 0x7f2d, 0x0212, 0x6a09, 0x7f2a, 0x0212, 0x6a09, 0x7f27,
+0x1f01, 0x2003, 0x4800, 0x7cea, 0x55e3, 0x9a5e, 0x0015, 0x0015,
+0x0015, 0x7804, 0x5206, 0x6a0b, 0x5226, 0x6a0b, 0x9a5d, 0x0015,
+0x0015, 0x7804, 0x5206, 0x6a0a, 0x5226, 0x6a0a, 0x9a5d, 0x0015,
+0x7804, 0x5206, 0x6a09, 0x5226, 0x6a09, 0x7c09, 0x6a28, 0x7f07,
+0x0000, 0x57db, 0x4d00, 0x7d05, 0xc1fa, 0x57db, 0x9a1c, 0xc277,
+0x0454, 0xc20a, 0x9a19
+};
+#endif
+
diff --git a/arch/arm/mach-mx5/sdram_autogating.c b/arch/arm/mach-mx5/sdram_autogating.c
new file mode 100644
index 000000000000..0b05d791c4f9
--- /dev/null
+++ b/arch/arm/mach-mx5/sdram_autogating.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file sdram_autogating.c
+ *
+ * @brief Enable auto clock gating of the EMI_FAST clock using M4IF.
+ *
+ * The APIs are for enabling and disabling automatic clock gating of EMI_FAST.
+ *
+ * @ingroup PM
+ */
+#include <asm/io.h>
+#include <linux/proc_fs.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <mach/sdram_autogating.h>
+#include "crm_regs.h"
+
+static struct device *sdram_autogating_dev;
+#define M4IF_CNTL_REG0 0x8c
+#define M4IF_CNTL_REG1 0x90
+
+/* Flag used to indicate if SDRAM M4IF autoclock gating feature is active. */
+static int sdram_autogating_is_active;
+static int sdram_autogating_paused;
+static void __iomem *m4if_base;
+
+void start_sdram_autogating(void);
+void stop_sdram_autogating(void);
+int sdram_autogating_active(void);
+
+static void enable(void)
+{
+ u32 reg;
+
+ /* Set the Fast arbitration Power saving timer */
+ reg = __raw_readl(m4if_base + M4IF_CNTL_REG1);
+ reg &= ~0xFF;
+ reg |= 0x09;
+ __raw_writel(reg, m4if_base + M4IF_CNTL_REG1);
+ /*Allow for automatic gating of the EMI internal clock.
+ * If this is done, emi_intr CCGR bits should be set to 11.
+ */
+ reg = __raw_readl(m4if_base + M4IF_CNTL_REG0);
+ reg &= ~0x5;
+ __raw_writel(reg, m4if_base + M4IF_CNTL_REG0);
+
+ sdram_autogating_is_active = 1;
+}
+
+static void disable(void)
+{
+ u32 reg;
+
+ reg = __raw_readl(m4if_base + M4IF_CNTL_REG0);
+ reg |= 0x4;
+ __raw_writel(reg, m4if_base + M4IF_CNTL_REG0);
+ sdram_autogating_is_active = 0;
+}
+
+int sdram_autogating_active()
+{
+ return sdram_autogating_is_active;
+}
+
+void start_sdram_autogating()
+{
+ if (cpu_is_mx50())
+ return;
+ if (sdram_autogating_paused) {
+ enable();
+ sdram_autogating_paused = 0;
+ }
+}
+
+void stop_sdram_autogating()
+{
+ if (cpu_is_mx50())
+ return;
+
+ if (sdram_autogating_is_active) {
+ sdram_autogating_paused = 1;
+ disable();
+ }
+}
+
+static ssize_t sdram_autogating_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (sdram_autogating_is_active)
+ return sprintf(buf,
+ "M4IF autoclock gating for EMI_FAST enabled\n");
+ else
+ return sprintf(buf,
+ "M4IF autoclock gating for EMI_FAST disabled\n");
+}
+
+static ssize_t sdram_autogating_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ if (strstr(buf, "1") != NULL)
+ enable();
+ else if (strstr(buf, "0") != NULL) {
+ if (sdram_autogating_is_active)
+ disable();
+ }
+ return size;
+}
+
+static DEVICE_ATTR(enable, 0644, sdram_autogating_enable_show,
+ sdram_autogating_enable_store);
+
+/*!
+ * This is the probe routine for the auto clockgating of sdram driver.
+ *
+ * @param pdev The platform device structure
+ *
+ * @return The function returns 0 on success
+ *
+ */
+static int __devinit sdram_autogating_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int err = 0;
+
+ sdram_autogating_dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ return -ENOMEM;
+ }
+ m4if_base = ioremap(res->start, res->end - res->start + 1);
+
+ err = sysfs_create_file(&sdram_autogating_dev->kobj,
+ &dev_attr_enable.attr);
+ if (err) {
+ printk(KERN_ERR
+ "Unable to register sysdev entry for sdram_autogating");
+ return err;
+ }
+
+ sdram_autogating_is_active = 0;
+
+ return 0;
+}
+
+static struct platform_driver sdram_autogating_driver = {
+ .driver = {
+ .name = "sdram_autogating",
+ },
+ .probe = sdram_autogating_probe,
+};
+
+/*!
+ * Initialise the sdram_autogating_driver.
+ *
+ * @return The function always returns 0.
+ */
+
+static int __init sdram_autogating_init(void)
+{
+ if (platform_driver_register(&sdram_autogating_driver) != 0) {
+ printk(KERN_ERR "sdram_autogating_driver register failed\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "sdram autogating driver module loaded\n");
+ return 0;
+}
+
+static void __exit sdram_autogating_cleanup(void)
+{
+ sysfs_remove_file(&sdram_autogating_dev->kobj, &dev_attr_enable.attr);
+
+ /* Unregister the device structure */
+ platform_driver_unregister(&sdram_autogating_driver);
+}
+
+module_init(sdram_autogating_init);
+module_exit(sdram_autogating_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("sdram_autogating driver");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/arm/mach-mx5/serial.c b/arch/arm/mach-mx5/serial.c
new file mode 100644
index 000000000000..18dfcfb6d696
--- /dev/null
+++ b/arch/arm/mach-mx5/serial.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/*!
+ * @file mach-mx51/serial.c
+ *
+ * @brief This file contains the UART initiliazation.
+ *
+ * @ingroup MSL_MX51
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <mach/hardware.h>
+#include <mach/mxc_uart.h>
+#include "serial.h"
+
+#if defined(CONFIG_SERIAL_MXC) || defined(CONFIG_SERIAL_MXC_MODULE)
+
+/*!
+ * This is an array where each element holds information about a UART port,
+ * like base address of the UART, interrupt numbers etc. This structure is
+ * passed to the serial_core.c file. Based on which UART is used, the core file
+ * passes back the appropriate port structure as an argument to the control
+ * functions.
+ */
+static uart_mxc_port mxc_ports[] = {
+ [0] = {
+ .port = {
+ .iotype = SERIAL_IO_MEM,
+ .fifosize = 32,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
+ },
+ .ints_muxed = 1,
+ .mode = MODE_DCE,
+ .ir_mode = NO_IRDA,
+ .enabled = 1,
+ .cts_threshold = UART1_UCR4_CTSTL,
+ .dma_enabled = UART1_DMA_ENABLE,
+ .dma_rxbuf_size = UART1_DMA_RXBUFSIZE,
+ .rx_threshold = UART1_UFCR_RXTL,
+ .tx_threshold = UART1_UFCR_TXTL,
+ .dma_tx_id = MXC_DMA_UART1_TX,
+ .dma_rx_id = MXC_DMA_UART1_RX,
+ .rxd_mux = MXC_UART_RXDMUX,
+ },
+ [1] = {
+ .port = {
+ .iotype = SERIAL_IO_MEM,
+ .fifosize = 32,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 1,
+ },
+ .ints_muxed = 1,
+ .mode = MODE_DCE,
+ .ir_mode = NO_IRDA,
+ .enabled = 1,
+ .cts_threshold = UART2_UCR4_CTSTL,
+ .dma_enabled = UART2_DMA_ENABLE,
+ .dma_rxbuf_size = UART2_DMA_RXBUFSIZE,
+ .rx_threshold = UART2_UFCR_RXTL,
+ .tx_threshold = UART2_UFCR_TXTL,
+ .dma_tx_id = MXC_DMA_UART2_TX,
+ .dma_rx_id = MXC_DMA_UART2_RX,
+ .rxd_mux = MXC_UART_RXDMUX,
+ },
+ [2] = {
+ .port = {
+ .iotype = SERIAL_IO_MEM,
+ .fifosize = 32,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 2,
+ },
+ .ints_muxed = 1,
+ .mode = MODE_DCE,
+ .ir_mode = NO_IRDA,
+ .enabled = 1,
+ .cts_threshold = UART3_UCR4_CTSTL,
+ .dma_enabled = UART3_DMA_ENABLE,
+ .dma_rxbuf_size = UART3_DMA_RXBUFSIZE,
+ .rx_threshold = UART3_UFCR_RXTL,
+ .tx_threshold = UART3_UFCR_TXTL,
+ .dma_tx_id = MXC_DMA_UART3_TX,
+ .dma_rx_id = MXC_DMA_UART3_RX,
+ .rxd_mux = MXC_UART_RXDMUX,
+ },
+ [3] = {
+ .port = {
+ .iotype = SERIAL_IO_MEM,
+ .fifosize = 32,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 3,
+ },
+ .ints_muxed = 1,
+ .mode = MODE_DCE,
+ .ir_mode = NO_IRDA,
+ .enabled = 1,
+ .cts_threshold = UART4_UCR4_CTSTL,
+ .dma_enabled = UART4_DMA_ENABLE,
+ .dma_rxbuf_size = UART4_DMA_RXBUFSIZE,
+ .rx_threshold = UART4_UFCR_RXTL,
+ .tx_threshold = UART4_UFCR_TXTL,
+ .dma_tx_id = MXC_DMA_UART4_TX,
+ .dma_rx_id = MXC_DMA_UART4_RX,
+ .rxd_mux = MXC_UART_RXDMUX,
+ },
+ [4] = {
+ .port = {
+ .iotype = SERIAL_IO_MEM,
+ .fifosize = 32,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 4,
+ },
+ .ints_muxed = 1,
+ .mode = MODE_DCE,
+ .ir_mode = NO_IRDA,
+ .enabled = 1,
+ .cts_threshold = UART5_UCR4_CTSTL,
+ .dma_enabled = UART5_DMA_ENABLE,
+ .dma_rxbuf_size = UART5_DMA_RXBUFSIZE,
+ .rx_threshold = UART5_UFCR_RXTL,
+ .tx_threshold = UART5_UFCR_TXTL,
+ .dma_tx_id = MXC_DMA_UART5_TX,
+ .dma_rx_id = MXC_DMA_UART5_RX,
+ .rxd_mux = MXC_UART_RXDMUX,
+ },
+};
+
+static struct resource mxc_uart_resources1[] = {
+ {
+ .start = UART1_BASE_ADDR,
+ .end = UART1_BASE_ADDR + 0x0B5,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_UART1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mxc_uart_device1 = {
+ .name = "mxcintuart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_uart_resources1),
+ .resource = mxc_uart_resources1,
+ .dev = {
+ .platform_data = &mxc_ports[0],
+ },
+};
+
+static struct resource mxc_uart_resources2[] = {
+ {
+ .start = UART2_BASE_ADDR,
+ .end = UART2_BASE_ADDR + 0x0B5,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_UART2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mxc_uart_device2 = {
+ .name = "mxcintuart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mxc_uart_resources2),
+ .resource = mxc_uart_resources2,
+ .dev = {
+ .platform_data = &mxc_ports[1],
+ },
+};
+
+static struct resource mxc_uart_resources3[] = {
+ {
+ .start = UART3_BASE_ADDR,
+ .end = UART3_BASE_ADDR + 0x0B5,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mxc_uart_device3 = {
+ .name = "mxcintuart",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(mxc_uart_resources3),
+ .resource = mxc_uart_resources3,
+ .dev = {
+ .platform_data = &mxc_ports[2],
+ },
+};
+
+static struct resource mxc_uart_resources4[] = {
+ {
+ .start = UART4_BASE_ADDR,
+ .end = UART4_BASE_ADDR + 0x0B5,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_UART4,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mxc_uart_device4 = {
+ .name = "mxcintuart",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(mxc_uart_resources4),
+ .resource = mxc_uart_resources4,
+ .dev = {
+ .platform_data = &mxc_ports[3],
+ },
+};
+
+static struct resource mxc_uart_resources5[] = {
+ {
+ .start = UART5_BASE_ADDR,
+ .end = UART5_BASE_ADDR + 0x0B5,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_INT_UART5,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mxc_uart_device5 = {
+ .name = "mxcintuart",
+ .id = 4,
+ .num_resources = ARRAY_SIZE(mxc_uart_resources5),
+ .resource = mxc_uart_resources5,
+ .dev = {
+ .platform_data = &mxc_ports[4],
+ },
+};
+
+static int __init mxc_init_uart(void)
+{
+ if (cpu_is_mx53() || cpu_is_mx50()) {
+ mxc_uart_resources1[0].start -= 0x20000000;
+ mxc_uart_resources1[0].end -= 0x20000000;
+ mxc_uart_resources2[0].start -= 0x20000000;
+ mxc_uart_resources2[0].end -= 0x20000000;
+ mxc_uart_resources3[0].start -= 0x20000000;
+ mxc_uart_resources3[0].end -= 0x20000000;
+ mxc_uart_resources4[0].start -= 0x20000000;
+ mxc_uart_resources4[0].end -= 0x20000000;
+ mxc_uart_resources5[0].start -= 0x20000000;
+ mxc_uart_resources5[0].end -= 0x20000000;
+ }
+
+ /* Register all the MXC UART platform device structures */
+ platform_device_register(&mxc_uart_device1);
+ platform_device_register(&mxc_uart_device2);
+ platform_device_register(&mxc_uart_device3);
+ if (cpu_is_mx53()) {
+ platform_device_register(&mxc_uart_device4);
+ platform_device_register(&mxc_uart_device5);
+ }
+ return 0;
+}
+
+#else
+static int __init mxc_init_uart(void)
+{
+ return 0;
+}
+#endif
+
+arch_initcall(mxc_init_uart);
diff --git a/arch/arm/mach-mx5/serial.h b/arch/arm/mach-mx5/serial.h
new file mode 100644
index 000000000000..9fbb0b33e4eb
--- /dev/null
+++ b/arch/arm/mach-mx5/serial.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ARCH_ARM_MACH_MX51_SERIAL_H__
+#define __ARCH_ARM_MACH_MX51_SERIAL_H__
+
+/* UART 1 configuration */
+/*!
+ * This specifies the threshold at which the CTS pin is deasserted by the
+ * RXFIFO. Set this value in Decimal to anything from 0 to 32 for
+ * hardware-driven hardware flow control. Read the HW spec while specifying
+ * this value. When using interrupt-driven software controlled hardware
+ * flow control set this option to -1.
+ */
+#define UART1_UCR4_CTSTL 16
+/*!
+ * Specify the size of the DMA receive buffer. The minimum buffer size is 512
+ * bytes. The buffer size should be a multiple of 256.
+ */
+#define UART1_DMA_RXBUFSIZE 1024
+/*!
+ * Specify the MXC UART's Receive Trigger Level. This controls the threshold at
+ * which a maskable interrupt is generated by the RxFIFO. Set this value in
+ * Decimal to anything from 0 to 32. Read the HW spec while specifying this
+ * value.
+ */
+#define UART1_UFCR_RXTL 16
+/*!
+ * Specify the MXC UART's Transmit Trigger Level. This controls the threshold at
+ * which a maskable interrupt is generated by the TxFIFO. Set this value in
+ * Decimal to anything from 0 to 32. Read the HW spec while specifying this
+ * value.
+ */
+#define UART1_UFCR_TXTL 16
+#define UART1_DMA_ENABLE 0
+/* UART 2 configuration */
+#define UART2_UCR4_CTSTL -1
+#define UART2_DMA_ENABLE 1
+#define UART2_DMA_RXBUFSIZE 512
+#define UART2_UFCR_RXTL 16
+#define UART2_UFCR_TXTL 16
+/* UART 3 configuration */
+#define UART3_UCR4_CTSTL 16
+#define UART3_DMA_ENABLE 0
+#define UART3_DMA_RXBUFSIZE 1024
+#define UART3_UFCR_RXTL 16
+#define UART3_UFCR_TXTL 16
+/* UART 4 configuration */
+#define UART4_UCR4_CTSTL -1
+#define UART4_DMA_ENABLE 0
+#define UART4_DMA_RXBUFSIZE 512
+#define UART4_UFCR_RXTL 16
+#define UART4_UFCR_TXTL 16
+/* UART 5 configuration */
+#define UART5_UCR4_CTSTL -1
+#define UART5_DMA_ENABLE 0
+#define UART5_DMA_RXBUFSIZE 512
+#define UART5_UFCR_RXTL 16
+#define UART5_UFCR_TXTL 16
+
+#endif /* __ARCH_ARM_MACH_MX51_SERIAL_H__ */
diff --git a/arch/arm/mach-mx5/suspend.S b/arch/arm/mach-mx5/suspend.S
new file mode 100644
index 000000000000..f5aa1cc2f668
--- /dev/null
+++ b/arch/arm/mach-mx5/suspend.S
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+
+#define ARM_CTRL_DCACHE 1 << 2
+#define ARM_CTRL_ICACHE 1 << 12
+#define ARM_AUXCR_L2EN 1 << 1
+
+
+/*
+ * cpu_do_suspend_workaround()
+ *
+ * Suspend the processor (eg, wait for interrupt).
+ *
+ * IRQs are already disabled.
+ */
+ENTRY(cpu_do_suspend_workaround)
+ stmfd sp!, {r4,r5,r6,r7,r9,r10,r11} @ Save registers
+
+ mov r6, r0 @save iomux address
+ /* Disable L1 caches */
+ mrc p15, 0, r0, c1, c0, 0 @ R0 = system control reg
+ bic r0, r0, #ARM_CTRL_ICACHE @ Disable ICache
+ bic r0, r0, #ARM_CTRL_DCACHE @ Disable DCache
+ mcr p15, 0, r0, c1, c0, 0 @ Update system control reg
+
+ mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR
+ ands r3, r0, #0x7000000 @ Isolate level of coherency
+ mov r3, r3, lsr #23 @ Cache level value (naturally aligned)
+ beq FinishedClean
+ mov r10, #0
+Loop1Clean:
+ add r2, r10, r10, lsr #1 @ Work out cache level
+ mov r1, r0, lsr r2 @ R0 bottom 3 bits = Cache Type for this level
+ and r1, r1, #7 @ Get those 3 bits alone
+ cmp r1, #2
+ blt SkipClean @ No cache or only instruction cache at this level
+ mcr p15, 2, r10, c0, c0, 0 @ Write the Cache Size selection register
+ mov r1, #0
+ .long 0xF57FF06F @ ISB
+ mrc p15, 1, r1, c0, c0, 0 @ Reads current Cache Size ID register
+ and r2, r1, #7 @ Extract the line length field
+ add r2, r2, #4 @ Add 4 for the line length offset (log2 16 bytes)
+ ldr r4, =0x3FF
+ ands r4, r4, r1, lsr #3 @ R4 is the max number on the way size (right aligned)
+ clz r5, r4 @ R5 is the bit position of the way size increment
+ ldr r7, =0x00007FFF
+ ands r7, r7, r1, lsr #13 @ R7 is the max number of the index size (right aligned)
+Loop2Clean:
+ mov r9, r4 @ R9 working copy of the max way size (right aligned)
+Loop3Clean:
+ orr r11, r10, r9, lsl r5 @ Factor in the way number and cache number into R11
+ orr r11, r11, r7, lsl r2 @ Factor in the index number
+ mcr p15, 0, r11, c7, c14, 2 @ Clean and invalidate by set/way
+ subs r9, r9, #1 @ Decrement the way number
+ bge Loop3Clean
+ subs r7, r7, #1 @ Decrement the index
+ bge Loop2Clean
+SkipClean:
+ add r10, r10, #2 @ Increment the cache number
+ cmp r3, r10
+ bgt Loop1Clean
+
+FinishedClean:
+
+ /* Disable L2 cache */
+ mrc p15, 0, r0, c1, c0, 1 @ R0 = auxiliary control reg
+ bic r0, r0, #ARM_AUXCR_L2EN @ Disable L2 cache
+ mcr p15, 0, r0, c1, c0, 1 @ Update aux control reg
+
+ /*Set the DDR drive strength to low */
+ ldr r10, [r6]
+ and r10, r10, #0xF1 @ clear bits 2-1
+ str r10, [r6]
+
+ .long 0xe320f003 @ Opcode for WFI
+
+ /*Set the DDR drive strength to max */
+ orr r10, r10, #0x06 @ set bits 2-1
+ str r10, [r6]
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0 @ Invalidate inst cache
+
+ /* Invalidate data caches */
+ mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR
+ ands r3, r0, #0x7000000 @ Isolate level of coherency
+ mov r3, r3, lsr #23 @ Cache level value (naturally aligned)
+ beq FinishedInvalidate
+ mov r10, #0
+Loop1Invalidate:
+ add r2, r10, r10, lsr #1 @ Work out cache level
+ mov r1, r0, lsr r2 @ R0 bottom 3 bits = Cache Type for this level
+ and r1, r1, #7 @ Get those 3 bits alone
+ cmp r1, #2
+ blt SkipInvalidate @ No cache or only instruction cache at this level
+ mcr p15, 2, r10, c0, c0, 0 @ Write the Cache Size selection register
+ mov r1, #0
+ .long 0xF57FF06F @ ISB
+ mrc p15, 1, r1, c0, c0, 0 @ Reads current Cache Size ID register
+ and r2, r1, #7 @ Extract the line length field
+ add r2, r2, #4 @ Add 4 for the line length offset (log2 16 bytes)
+ ldr r4, =0x3FF
+ ands r4, r4, r1, lsr #3 @ R4 is the max number on the way size (right aligned)
+ clz r5, r4 @ R5 is the bit position of the way size increment
+ ldr r7, =0x00007FFF
+ ands r7, r7, r1, lsr #13 @ R7 is the max number of the index size (right aligned)
+Loop2Invalidate:
+ mov r9, r4 @ R9 working copy of the max way size (right aligned)
+Loop3Invalidate:
+ orr r11, r10, r9, lsl r5 @ Factor in the way number and cache number into R11
+ orr r11, r11, r7, lsl r2 @ Factor in the index number
+ mcr p15, 0, r11, c7, c6, 2 @ Invalidate by set/way
+ subs r9, r9, #1 @ Decrement the way number
+ bge Loop3Invalidate
+ subs r7, r7, #1 @ Decrement the index
+ bge Loop2Invalidate
+SkipInvalidate:
+ add r10, r10, #2 @ Increment the cache number
+ cmp r3, r10
+ bgt Loop1Invalidate
+
+FinishedInvalidate:
+
+ /* Enable L2 cache */
+ mrc p15, 0, r0, c1, c0, 1 @ R0 = auxiliary control reg
+ orr r0, r0, #ARM_AUXCR_L2EN @ Enable L2 cache
+ mcr p15, 0, r0, c1, c0, 1 @ Update aux control reg
+
+ /* Enable L1 caches */
+ mrc p15, 0, r0, c1, c0, 0 @ R0 = system control reg
+ orr r0, r0, #ARM_CTRL_ICACHE @ Enable ICache
+ orr r0, r0, #ARM_CTRL_DCACHE @ Enable DCache
+ mcr p15, 0, r0, c1, c0, 0 @ Update system control reg
+
+ /* Restore registers */
+ ldmfd sp!, {r4,r5,r6,r7,r9,r10,r11}
+ mov pc, lr
+
+ .type cpu_do_suspend, #object
+ENTRY(cpu_do_suspend)
+ .word cpu_do_suspend_workaround
+ .size cpu_do_suspend_workaround, . - cpu_do_suspend_workaround
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
new file mode 100644
index 000000000000..a04962f64275
--- /dev/null
+++ b/arch/arm/mach-mx5/system.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pmic_external.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/clock.h>
+#include <asm/proc-fns.h>
+#include <asm/system.h>
+#include "crm_regs.h"
+
+/*!
+ * @defgroup MSL_MX51 i.MX51 Machine Specific Layer (MSL)
+ */
+
+/*!
+ * @file mach-mx51/system.c
+ * @brief This file contains idle and reset functions.
+ *
+ * @ingroup MSL_MX51
+ */
+
+extern int mxc_jtag_enabled;
+extern int iram_ready;
+extern int dvfs_core_is_active;
+extern void __iomem *ccm_base;
+extern void __iomem *databahn_base;
+extern int low_bus_freq_mode;
+extern void (*wait_in_iram)(void *ccm_addr, void *databahn_addr);
+extern void mx50_wait(u32 ccm_base, u32 databahn_addr);
+extern void stop_dvfs(void);
+extern void *wait_in_iram_base;
+extern void __iomem *apll_base;
+
+static struct clk *gpc_dvfs_clk;
+static struct regulator *vpll;
+static struct clk *pll1_sw_clk;
+static struct clk *osc;
+static struct clk *pll1_main_clk;
+static struct clk *ddr_clk ;
+static int dvfs_core_paused;
+
+/* set cpu low power mode before WFI instruction */
+void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+ u32 plat_lpc, arm_srpgcr, ccm_clpcr;
+ u32 empgc0, empgc1;
+ int stop_mode = 0;
+
+ /* always allow platform to issue a deep sleep mode request */
+ plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+ ~(MXC_CORTEXA8_PLAT_LPC_DSM);
+ ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+ arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
+ empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
+ empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+
+ switch (mode) {
+ case WAIT_CLOCKED:
+ break;
+ case WAIT_UNCLOCKED:
+ ccm_clpcr |= (0x1 << MXC_CCM_CLPCR_LPM_OFFSET);
+ break;
+ case WAIT_UNCLOCKED_POWER_OFF:
+ case STOP_POWER_OFF:
+ plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
+ | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
+ if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+ ccm_clpcr |= (0x1 << MXC_CCM_CLPCR_LPM_OFFSET);
+ ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+ stop_mode = 0;
+ } else {
+ ccm_clpcr |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET);
+ ccm_clpcr |= (0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET);
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+ stop_mode = 1;
+ }
+
+ arm_srpgcr |= MXC_SRPGCR_PCR;
+ if (stop_mode) {
+ empgc0 |= MXC_SRPGCR_PCR;
+ empgc1 |= MXC_SRPGCR_PCR;
+ }
+
+ if (tzic_enable_wake(1) != 0)
+ return;
+ break;
+ case STOP_POWER_ON:
+ ccm_clpcr |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET);
+ break;
+ default:
+ printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+ return;
+ }
+
+ __raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
+ __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+ if (cpu_is_mx51() || (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1)
+ || cpu_is_mx50_rev(CHIP_REV_1_1) >= 1)
+ __raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
+ /* Enable NEON SRPG for all but MX50TO1.0. */
+ if (!(cpu_is_mx50_rev(CHIP_REV_1_0) == 1))
+ __raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+ if (stop_mode) {
+ __raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
+ __raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+ }
+}
+
+void mxc_pg_enable(struct platform_device *pdev)
+{
+ if (pdev == NULL)
+ return;
+
+ if (strcmp(pdev->name, "mxc_ipu") == 0) {
+ __raw_writel(MXC_PGCR_PCR, MXC_PGC_IPU_PGCR);
+ __raw_writel(MXC_PGSR_PSR, MXC_PGC_IPU_PGSR);
+ } else if (strcmp(pdev->name, "mxc_vpu") == 0) {
+ __raw_writel(MXC_PGCR_PCR, MXC_PGC_VPU_PGCR);
+ __raw_writel(MXC_PGSR_PSR, MXC_PGC_VPU_PGSR);
+ }
+}
+
+EXPORT_SYMBOL(mxc_pg_enable);
+
+void mxc_pg_disable(struct platform_device *pdev)
+{
+ if (pdev == NULL)
+ return;
+
+ if (strcmp(pdev->name, "mxc_ipu") == 0) {
+ __raw_writel(0x0, MXC_PGC_IPU_PGCR);
+ if (__raw_readl(MXC_PGC_IPU_PGSR) & MXC_PGSR_PSR)
+ dev_dbg(&pdev->dev, "power gating successful\n");
+ __raw_writel(MXC_PGSR_PSR, MXC_PGC_IPU_PGSR);
+ } else if (strcmp(pdev->name, "mxc_vpu") == 0) {
+ __raw_writel(0x0, MXC_PGC_VPU_PGCR);
+ if (__raw_readl(MXC_PGC_VPU_PGSR) & MXC_PGSR_PSR)
+ dev_dbg(&pdev->dev, "power gating successful\n");
+ __raw_writel(MXC_PGSR_PSR, MXC_PGC_VPU_PGSR);
+ }
+}
+
+EXPORT_SYMBOL(mxc_pg_disable);
+
+/* To change the idle power mode, need to set arch_idle_mode to a different
+ * power mode as in enum mxc_cpu_pwr_mode.
+ * May allow dynamically changing the idle mode.
+ */
+static int arch_idle_mode = WAIT_UNCLOCKED_POWER_OFF;
+/*!
+ * This function puts the CPU into idle mode. It is called by default_idle()
+ * in process.c file.
+ */
+void arch_idle(void)
+{
+ if (likely(!mxc_jtag_enabled)) {
+ if (ddr_clk == NULL)
+ ddr_clk = clk_get(NULL, "ddr_clk");
+ if (gpc_dvfs_clk == NULL)
+ gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs_clk");
+ /* gpc clock is needed for SRPG */
+ clk_enable(gpc_dvfs_clk);
+ mxc_cpu_lp_set(arch_idle_mode);
+
+ if (cpu_is_mx50() && (clk_get_usecount(ddr_clk) == 0)) {
+ memcpy(wait_in_iram_base, mx50_wait, SZ_4K);
+ wait_in_iram = (void *)wait_in_iram_base;
+ if (low_bus_freq_mode) {
+ u32 reg, cpu_podf;
+
+ reg = __raw_readl(apll_base + 0x50);
+ reg = 0x120490;
+ __raw_writel(reg, apll_base + 0x50);
+ reg = __raw_readl(apll_base + 0x80);
+ reg |= 1;
+ __raw_writel(reg, apll_base + 0x80);
+
+ /* Move ARM to be sourced from 24MHz XTAL.
+ * when ARM is in WFI.
+ */
+ if (pll1_sw_clk == NULL)
+ pll1_sw_clk = clk_get(NULL,
+ "pll1_sw_clk");
+ if (osc == NULL)
+ osc = clk_get(NULL, "lp_apm");
+ if (pll1_main_clk == NULL)
+ pll1_main_clk = clk_get(NULL,
+ "pll1_main_clk");
+
+ clk_set_parent(pll1_sw_clk, osc);
+ /* Set the ARM-PODF divider to 1. */
+ cpu_podf = __raw_readl(MXC_CCM_CACRR);
+ __raw_writel(0x01, MXC_CCM_CACRR);
+
+ wait_in_iram(ccm_base, databahn_base);
+
+ /* Set the ARM-POD divider back
+ * to the original.
+ */
+ __raw_writel(cpu_podf, MXC_CCM_CACRR);
+ clk_set_parent(pll1_sw_clk, pll1_main_clk);
+ } else
+ wait_in_iram(ccm_base, databahn_base);
+ } else
+ cpu_do_idle();
+ clk_disable(gpc_dvfs_clk);
+ clk_put(ddr_clk);
+ }
+}
+
+static int __mxs_reset_block(void __iomem *hwreg, int just_enable)
+{
+ u32 c;
+ int timeout;
+
+ /* the process of software reset of IP block is done
+ in several steps:
+
+ - clear SFTRST and wait for block is enabled;
+ - clear clock gating (CLKGATE bit);
+ - set the SFTRST again and wait for block is in reset;
+ - clear SFTRST and wait for reset completion.
+ */
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 31); /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1 << 31)) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when enabling\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 30); /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+
+ if (!just_enable) {
+ c = __raw_readl(hwreg);
+ c |= (1 << 31); /* now again set SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* poll until CLKGATE set */
+ if (__raw_readl(hwreg) & (1 << 30))
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when resetting\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 31); /* clear SFTRST */
+ __raw_writel(c, hwreg);
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1 << 31)) == 0)
+ break;
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when enabling "
+ "after reset\n", __func__, hwreg);
+ return -ETIME;
+ }
+
+ c = __raw_readl(hwreg);
+ c &= ~(1 << 30); /* clear CLKGATE */
+ __raw_writel(c, hwreg);
+ }
+ for (timeout = 1000000; timeout > 0; timeout--)
+ /* still in SFTRST state ? */
+ if ((__raw_readl(hwreg) & (1 << 30)) == 0)
+ break;
+
+ if (timeout <= 0) {
+ printk(KERN_ERR "%s(%p): timeout when unclockgating\n",
+ __func__, hwreg);
+ return -ETIME;
+ }
+
+ return 0;
+}
+
+int mxs_reset_block(void __iomem *hwreg, int just_enable)
+{
+ int try = 10;
+ int r;
+
+ while (try--) {
+ r = __mxs_reset_block(hwreg, just_enable);
+ if (!r)
+ break;
+ pr_debug("%s: try %d failed\n", __func__, 10 - try);
+ }
+ return r;
+}
+
diff --git a/arch/arm/mach-mx5/usb.h b/arch/arm/mach-mx5/usb.h
new file mode 100644
index 000000000000..6115d3375c05
--- /dev/null
+++ b/arch/arm/mach-mx5/usb.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <mach/common.h>
+#include "devices.h"
+
+extern int usbotg_init(struct platform_device *pdev);
+extern void usbotg_uninit(struct fsl_usb2_platform_data *pdata);
+extern int gpio_usbotg_hs_active(void);
+extern void gpio_usbotg_hs_inactive(void);
+extern struct platform_device *host_pdev_register(struct resource *res,
+ int n_res, struct fsl_usb2_platform_data *config);
+
+extern int fsl_usb_host_init(struct platform_device *pdev);
+extern void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata);
+extern int gpio_usbotg_utmi_active(void);
+extern void gpio_usbotg_utmi_inactive(void);
+
+extern void __init mx5_usb_dr_init(void);
+extern void __init mx5_usbh1_init(void);
+extern void __init mx5_usbh2_init(void);
+
+typedef void (*driver_vbus_func)(bool);
+extern void mx5_set_host1_vbus_func(driver_vbus_func);
+extern void mx5_set_otghost_vbus_func(driver_vbus_func);
+/*
+ * Used to set pdata->operating_mode before registering the platform_device.
+ * If OTG is configured, the controller operates in OTG mode,
+ * otherwise it's either host or device.
+ */
+#ifdef CONFIG_USB_OTG
+#define DR_UDC_MODE FSL_USB2_DR_OTG
+#define DR_HOST_MODE FSL_USB2_DR_OTG
+#else
+#define DR_UDC_MODE FSL_USB2_DR_DEVICE
+#define DR_HOST_MODE FSL_USB2_DR_HOST
+#endif
+
diff --git a/arch/arm/mach-mx5/usb_dr.c b/arch/arm/mach-mx5/usb_dr.c
new file mode 100644
index 000000000000..d0dba3a3bf38
--- /dev/null
+++ b/arch/arm/mach-mx5/usb_dr.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <mach/arc_otg.h>
+#include <mach/hardware.h>
+#include <asm/delay.h>
+#include "usb.h"
+static int usbotg_init_ext(struct platform_device *pdev);
+static void usbotg_uninit_ext(struct fsl_usb2_platform_data *pdata);
+static void usbotg_clock_gate(bool on);
+
+static struct clk *usb_phy1_clk;
+static struct clk *usb_oh3_clk;
+static struct clk *usb_ahb_clk;
+static void usbotg_wakeup_event_clear(void);
+extern int clk_get_usecount(struct clk *clk);
+
+/* Beginning of Common operation for DR port */
+
+/*
+ * platform data structs
+ * - Which one to use is determined by CONFIG options in usb.h
+ * - operating_mode plugged at run time
+ */
+static struct fsl_usb2_platform_data dr_utmi_config = {
+ .name = "DR",
+ .platform_init = usbotg_init_ext,
+ .platform_uninit = usbotg_uninit_ext,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+ .power_budget = 500, /* 500 mA max power */
+ .gpio_usb_active = gpio_usbotg_hs_active,
+ .gpio_usb_inactive = gpio_usbotg_hs_inactive,
+ .usb_clock_for_pm = usbotg_clock_gate,
+ .transceiver = "utmi",
+};
+
+/* Platform data for wakeup operation */
+static struct fsl_usb2_wakeup_platform_data dr_wakeup_config = {
+ .name = "DR wakeup",
+ .usb_clock_for_pm = usbotg_clock_gate,
+ .usb_wakeup_exhandle = usbotg_wakeup_event_clear,
+};
+/* Notes: configure USB clock*/
+static int usbotg_init_ext(struct platform_device *pdev)
+{
+ struct clk *usb_clk;
+
+ /* the usb_ahb_clk will be enabled in usb_otg_init */
+ usb_ahb_clk = clk_get(NULL, "usb_ahb_clk");
+
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+
+ usb_clk = clk_get(NULL, "usb_phy1_clk");
+ clk_enable(usb_clk);
+ usb_phy1_clk = usb_clk;
+
+ return usbotg_init(pdev);
+}
+
+static void usbotg_uninit_ext(struct fsl_usb2_platform_data *pdata)
+{
+ clk_disable(usb_phy1_clk);
+ clk_put(usb_phy1_clk);
+
+ clk_disable(usb_oh3_clk);
+ clk_put(usb_oh3_clk);
+
+ /* usb_ahb_clk will be disabled at usb_common.c */
+ usbotg_uninit(pdata);
+ clk_put(usb_ahb_clk);
+}
+
+/* Below two macros are used at otg mode to indicate usb mode*/
+#define ENABLED_BY_HOST (0x1 << 0)
+#define ENABLED_BY_DEVICE (0x1 << 1)
+static u32 wakeup_irq_enable_src; /* only useful at otg mode */
+static void __wakeup_irq_enable(bool on, int source)
+ {
+ /* otg host and device share the OWIE bit, only when host and device
+ * all enable the wakeup irq, we can enable the OWIE bit
+ */
+ if (on) {
+#ifdef CONFIG_USB_OTG
+ wakeup_irq_enable_src |= source;
+ if (wakeup_irq_enable_src == (ENABLED_BY_HOST | ENABLED_BY_DEVICE)) {
+ USBCTRL |= UCTRL_OWIE;
+ USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_CONF2;
+ }
+#else
+ USBCTRL |= UCTRL_OWIE;
+ USB_PHY_CTR_FUNC |= USB_UTMI_PHYCTRL_CONF2;
+#endif
+ } else {
+ USB_PHY_CTR_FUNC &= ~USB_UTMI_PHYCTRL_CONF2;
+ USBCTRL &= ~UCTRL_OWIE;
+ wakeup_irq_enable_src &= ~source;
+ /* The interrupt must be disabled for at least 3 clock
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static u32 low_power_enable_src; /* only useful at otg mode */
+static void __phy_lowpower_suspend(bool enable, int source)
+{
+ if (enable) {
+ low_power_enable_src |= source;
+#ifdef CONFIG_USB_OTG
+ if (low_power_enable_src == (ENABLED_BY_HOST | ENABLED_BY_DEVICE)) {
+ pr_debug("phy lowpower enabled\n");
+ UOG_PORTSC1 |= PORTSC_PHCD;
+ }
+#else
+ UOG_PORTSC1 |= PORTSC_PHCD;
+#endif
+ } else {
+ pr_debug("phy lowpower disable\n");
+ UOG_PORTSC1 &= ~PORTSC_PHCD;
+ low_power_enable_src &= ~source;
+ }
+}
+
+static void usbotg_clock_gate(bool on)
+{
+ pr_debug("%s: on is %d\n", __func__, on);
+ if (on) {
+ clk_enable(usb_ahb_clk);
+ clk_enable(usb_oh3_clk);
+ clk_enable(usb_phy1_clk);
+ } else {
+ clk_disable(usb_phy1_clk);
+ clk_disable(usb_oh3_clk);
+ clk_disable(usb_ahb_clk);
+ }
+ pr_debug("usb_ahb_ref_count:%d, usb_phy_clk1_ref_count:%d\n", clk_get_usecount(usb_ahb_clk), clk_get_usecount(usb_phy1_clk));
+}
+
+void mx5_set_otghost_vbus_func(driver_vbus_func driver_vbus)
+{
+ dr_utmi_config.platform_driver_vbus = driver_vbus;
+}
+
+/* The wakeup operation for DR port, it will clear the wakeup irq status
+ * and re-enable the wakeup
+ */
+static void usbotg_wakeup_event_clear(void)
+{
+ int wakeup_req = USBCTRL & UCTRL_OWIR;
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC);
+ /* Disable OWIE to clear OWIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USBCTRL &= ~UCTRL_OWIE;
+ udelay(100);
+ USBCTRL |= UCTRL_OWIE;
+ }
+}
+/* End of Common operation for DR port */
+
+
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+extern void fsl_usb_recover_hcd(struct platform_device *pdev);
+/* Beginning of host related operation for DR port */
+static void _host_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ __wakeup_irq_enable(enable, ENABLED_BY_HOST);
+ /* host only care the ID change wakeup event */
+ if (enable) {
+ pr_debug("host wakeup enable\n");
+ USBCTRL_HOST2 |= UCTRL_H2OIDWK_EN;
+ } else {
+ pr_debug("host wakeup disable\n");
+ USBCTRL_HOST2 &= ~UCTRL_H2OIDWK_EN;
+ /* The interrupt must be disabled for at least 3 clock
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void _host_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ __phy_lowpower_suspend(enable, ENABLED_BY_HOST);
+}
+
+static enum usb_wakeup_event _is_host_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ int wakeup_req = USBCTRL & UCTRL_OWIR;
+ int otgsc = UOG_OTGSC;
+
+ /* if ID change sts, it is a host wakeup event */
+ if (wakeup_req && (otgsc & OTGSC_IS_USB_ID)) {
+ printk(KERN_INFO "otg host ID wakeup\n");
+ /* if host ID wakeup, we must clear the b session change sts */
+ UOG_OTGSC = otgsc & (~OTGSC_IS_USB_ID);
+ return WAKEUP_EVENT_ID;
+ }
+ if (wakeup_req && (!(otgsc & OTGSC_STS_USB_ID))) {
+ printk(KERN_INFO "otg host Remote wakeup\n");
+ return WAKEUP_EVENT_DPDM;
+ }
+
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void host_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _host_wakeup_enable(pdata, false);
+ _host_phy_lowpower_suspend(pdata, false);
+ fsl_usb_recover_hcd(&mxc_usbdr_host_device);
+}
+/* End of host related operation for DR port */
+#endif /* CONFIG_USB_EHCI_ARC_OTG */
+
+
+#ifdef CONFIG_USB_GADGET_ARC
+/* Beginning of device related operation for DR port */
+static void _device_wakeup_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ __wakeup_irq_enable(enable, ENABLED_BY_DEVICE);
+ /* if udc is not used by any gadget, we can not enable the vbus wakeup */
+ if (!pdata->port_enables) {
+ USBCTRL_HOST2 &= ~UCTRL_H2OVBWK_EN;
+ return;
+ }
+ if (enable) {
+ pr_debug("device wakeup enable\n");
+ USBCTRL_HOST2 |= UCTRL_H2OVBWK_EN;
+ } else {
+ pr_debug("device wakeup disable\n");
+ USBCTRL_HOST2 &= ~UCTRL_H2OVBWK_EN;
+ }
+}
+
+static void _device_phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ __phy_lowpower_suspend(enable, ENABLED_BY_DEVICE);
+}
+
+static enum usb_wakeup_event _is_device_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ int wakeup_req = USBCTRL & UCTRL_OWIR;
+
+ if (wakeup_req && (UOG_OTGSC & OTGSC_STS_USB_ID) && (UOG_OTGSC & OTGSC_IS_B_SESSION_VALID)) {
+ printk(KERN_INFO "otg udc wakeup\n");
+ return WAKEUP_EVENT_VBUS;
+ }
+ return WAKEUP_EVENT_INVALID;
+
+}
+
+static void device_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _device_wakeup_enable(pdata, false);
+ _device_phy_lowpower_suspend(pdata, false);
+}
+
+/* end of device related operation for DR port */
+#endif /* CONFIG_USB_GADGET_ARC */
+
+
+void __init mx5_usb_dr_init(void)
+{
+#ifdef CONFIG_USB_OTG
+ /* wake_up_enalbe is useless, just for usb_register_remote_wakeup execution*/
+ dr_utmi_config.wake_up_enable = _device_wakeup_enable;
+ dr_utmi_config.operating_mode = FSL_USB2_DR_OTG;
+ dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ platform_device_add_data(&mxc_usbdr_otg_device, &dr_utmi_config, sizeof(dr_utmi_config));
+ platform_device_register(&mxc_usbdr_otg_device);
+ dr_wakeup_config.usb_pdata[0] = mxc_usbdr_otg_device.dev.platform_data;
+#endif
+#ifdef CONFIG_USB_EHCI_ARC_OTG
+ dr_utmi_config.operating_mode = DR_HOST_MODE;
+ dr_utmi_config.wake_up_enable = _host_wakeup_enable;
+ dr_utmi_config.phy_lowpower_suspend = _host_phy_lowpower_suspend;
+ dr_utmi_config.is_wakeup_event = _is_host_wakeup;
+ dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ dr_utmi_config.wakeup_handler = host_wakeup_handler;
+ platform_device_add_data(&mxc_usbdr_host_device, &dr_utmi_config, sizeof(dr_utmi_config));
+ platform_device_register(&mxc_usbdr_host_device);
+ dr_wakeup_config.usb_pdata[1] = mxc_usbdr_host_device.dev.platform_data;
+#endif
+#ifdef CONFIG_USB_GADGET_ARC
+ dr_utmi_config.operating_mode = DR_UDC_MODE;
+ dr_utmi_config.wake_up_enable = _device_wakeup_enable;
+ dr_utmi_config.phy_lowpower_suspend = _device_phy_lowpower_suspend;
+ dr_utmi_config.is_wakeup_event = _is_device_wakeup;
+ dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
+ dr_utmi_config.wakeup_handler = device_wakeup_handler;
+ platform_device_add_data(&mxc_usbdr_udc_device, &dr_utmi_config, sizeof(dr_utmi_config));
+ platform_device_register(&mxc_usbdr_udc_device);
+ dr_wakeup_config.usb_pdata[2] = mxc_usbdr_udc_device.dev.platform_data;
+#endif
+ mxc_register_device(&mxc_usbdr_wakeup_device, &dr_wakeup_config);
+}
diff --git a/arch/arm/mach-mx5/usb_h1.c b/arch/arm/mach-mx5/usb_h1.c
new file mode 100644
index 000000000000..197947cfcb3c
--- /dev/null
+++ b/arch/arm/mach-mx5/usb_h1.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <asm/delay.h>
+#include <mach/arc_otg.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include "usb.h"
+#include "iomux.h"
+#include "mx51_pins.h"
+static struct clk *usb_phy2_clk;
+static struct clk *usb_oh3_clk;
+static struct clk *usb_ahb_clk;
+extern int clk_get_usecount(struct clk *clk);
+
+#ifdef CONFIG_USB_EHCI_ARC
+extern void fsl_usb_recover_hcd(struct platform_device *pdev);
+#else
+static void fsl_usb_recover_hcd(struct platform_device *pdev)
+{; }
+#endif
+/*
+ * USB Host1 HS port
+ */
+static int gpio_usbh1_active(void)
+{
+ /* Set USBH1_STP to GPIO and toggle it */
+ mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_GPIO |
+ IOMUX_CONFIG_SION);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), "usbh1_stp");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP), 1);
+
+ /* Signal only used on MX51-3DS for reset to PHY.*/
+ if (machine_is_mx51_3ds()) {
+ mxc_request_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_ALT1);
+ mxc_iomux_set_pad(MX51_PIN_EIM_D17, PAD_CTL_DRV_HIGH |
+ PAD_CTL_HYS_NONE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_100K_PU | PAD_CTL_ODE_OPENDRAIN_NONE |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), "eim_d17");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_D17), 1);
+ }
+
+ msleep(100);
+
+ return 0;
+}
+
+static void gpio_usbh1_inactive(void)
+{
+ /* Signal only used on MX51-3DS for reset to PHY.*/
+ if (machine_is_mx51_3ds()) {
+ gpio_free(IOMUX_TO_GPIO(MX51_PIN_EIM_D17));
+ mxc_free_iomux(MX51_PIN_EIM_D17, IOMUX_CONFIG_GPIO);
+ }
+
+ mxc_free_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_GPIO);
+ gpio_free(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP));
+}
+
+static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ pr_debug("host1, %s, enable is %d\n", __func__, enable);
+ if (enable)
+ USBCTRL |= UCTRL_H1WIE;
+ else {
+ USBCTRL &= ~UCTRL_H1WIE;
+ /* The interrupt must be disabled for at least 3
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ pr_debug("host1, %s, enable is %d\n", __func__, enable);
+ if (enable) {
+ UH1_PORTSC1 |= PORTSC_PHCD;
+ } else {
+ UH1_PORTSC1 &= ~PORTSC_PHCD;
+ }
+}
+
+static void usbh1_clock_gate(bool on)
+{
+ pr_debug("%s: on is %d\n", __func__, on);
+ if (on) {
+ clk_enable(usb_ahb_clk);
+ clk_enable(usb_oh3_clk);
+ clk_enable(usb_phy2_clk);
+ } else {
+ clk_disable(usb_phy2_clk);
+ clk_disable(usb_oh3_clk);
+ clk_disable(usb_ahb_clk);
+ }
+}
+
+static enum usb_wakeup_event _is_usbh1_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ int wakeup_req = USBCTRL & UCTRL_H1WIR;
+
+ if (wakeup_req)
+ return !WAKEUP_EVENT_INVALID;
+
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void h1_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+ fsl_usb_recover_hcd(&mxc_usbh1_device);
+}
+
+static void usbh1_wakeup_event_clear(void)
+{
+ int wakeup_req = USBCTRL & UCTRL_H1WIR;
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC);
+ /* Disable H1WIE to clear H1WIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USBCTRL &= ~UCTRL_H1WIE;
+ udelay(100);
+ USBCTRL |= UCTRL_H1WIE;
+ }
+}
+static int fsl_usb_host_init_ext(struct platform_device *pdev)
+{
+ int ret;
+ struct clk *usb_clk;
+
+ /* the usb_ahb_clk will be enabled in usb_otg_init */
+ usb_ahb_clk = clk_get(NULL, "usb_ahb_clk");
+
+ if (cpu_is_mx53()) {
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+
+ usb_clk = clk_get(NULL, "usb_phy2_clk");
+ clk_enable(usb_clk);
+ usb_phy2_clk = usb_clk;
+ } else if (cpu_is_mx50()) {
+ usb_clk = clk_get(NULL, "usb_phy2_clk");
+ clk_enable(usb_clk);
+ usb_phy2_clk = usb_clk;
+ } else if (cpu_is_mx51()) {
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ usb_oh3_clk = usb_clk;
+ }
+
+ ret = fsl_usb_host_init(pdev);
+ if (ret)
+ return ret;
+
+ if (cpu_is_mx51()) {
+ /* setback USBH1_STP to be function */
+ mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0);
+ mxc_iomux_set_pad(MX51_PIN_USBH1_STP, PAD_CTL_SRE_FAST |
+ PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE |
+ PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE |
+ PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS |
+ PAD_CTL_DRV_VOT_LOW);
+ gpio_free(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP));
+ }
+
+ /* disable remote wakeup irq */
+ USBCTRL &= ~UCTRL_H1WIE;
+ return 0;
+}
+
+static void fsl_usb_host_uninit_ext(struct fsl_usb2_platform_data *pdata)
+{
+ if (cpu_is_mx53()) {
+ clk_disable(usb_oh3_clk);
+ clk_put(usb_oh3_clk);
+
+ clk_disable(usb_phy2_clk);
+ clk_put(usb_phy2_clk);
+ } else if (cpu_is_mx50()) {
+ clk_disable(usb_phy2_clk);
+ clk_put(usb_phy2_clk);
+ } else if (cpu_is_mx51()) {
+ clk_disable(usb_oh3_clk);
+ clk_put(usb_oh3_clk);
+ }
+
+ fsl_usb_host_uninit(pdata);
+ /* usb_ahb_clk will be disabled at usb_common.c */
+ clk_put(usb_ahb_clk);
+}
+
+static struct fsl_usb2_platform_data usbh1_config = {
+ .name = "Host 1",
+ .platform_init = fsl_usb_host_init_ext,
+ .platform_uninit = fsl_usb_host_uninit_ext,
+ .operating_mode = FSL_USB2_MPH_HOST,
+ .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
+ .power_budget = 500, /* 500 mA max power */
+ .wake_up_enable = _wake_up_enable,
+ .usb_clock_for_pm = usbh1_clock_gate,
+ .phy_lowpower_suspend = _phy_lowpower_suspend,
+ .is_wakeup_event = _is_usbh1_wakeup,
+ .wakeup_handler = h1_wakeup_handler,
+ .transceiver = "utmi",
+};
+static struct fsl_usb2_wakeup_platform_data usbh1_wakeup_config = {
+ .name = "USBH1 wakeup",
+ .usb_clock_for_pm = usbh1_clock_gate,
+ .usb_pdata = {&usbh1_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh1_wakeup_event_clear,
+};
+
+void mx5_set_host1_vbus_func(driver_vbus_func driver_vbus)
+{
+ usbh1_config.platform_driver_vbus = driver_vbus;
+}
+
+void __init mx5_usbh1_init(void)
+{
+ if (cpu_is_mx51()) {
+ usbh1_config.phy_mode = FSL_USB2_PHY_ULPI;
+ usbh1_config.transceiver = "isp1504";
+ usbh1_config.gpio_usb_active = gpio_usbh1_active;
+ usbh1_config.gpio_usb_inactive = gpio_usbh1_inactive;
+ }
+ mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+ usbh1_config.wakeup_pdata = &usbh1_wakeup_config;
+ mxc_register_device(&mxc_usbh1_wakeup_device, &usbh1_wakeup_config);
+}
+
diff --git a/arch/arm/mach-mx5/usb_h2.c b/arch/arm/mach-mx5/usb_h2.c
new file mode 100644
index 000000000000..516c62dea814
--- /dev/null
+++ b/arch/arm/mach-mx5/usb_h2.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <mach/arc_otg.h>
+#include "usb.h"
+#include "iomux.h"
+#include "mx51_pins.h"
+
+#ifdef CONFIG_USB_EHCI_ARC
+extern void fsl_usb_recover_hcd(struct platform_device *pdev);
+#else
+static void fsl_usb_recover_hcd(struct platform_device *pdev)
+{; }
+#endif
+/*
+ * USB Host2 HS port
+ */
+static int gpio_usbh2_active(void)
+{
+ /* Set USBH2_STP to GPIO and toggle it */
+ mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_GPIO);
+ gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), "eim_a26");
+ gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), 0);
+ gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_EIM_A26), 1);
+
+ msleep(100);
+
+ return 0;
+}
+
+static void gpio_usbh2_inactive(void)
+{
+ gpio_free(IOMUX_TO_GPIO(MX51_PIN_EIM_A26));
+ mxc_free_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_GPIO);
+}
+
+static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ printk(KERN_DEBUG "host2, %s, enable is %d\n", __func__, enable);
+ if (enable)
+ USBCTRL_HOST2 |= UCTRL_H2WIE;
+ else {
+ USBCTRL_HOST2 &= ~UCTRL_H2WIE;
+ /* The interrupt must be disabled for at least 3
+ * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
+ udelay(100);
+ }
+}
+
+static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
+{
+ printk(KERN_DEBUG "host2, %s, enable is %d\n", __func__, enable);
+ if (enable) {
+ UH2_PORTSC1 |= PORTSC_PHCD;
+ } else {
+ UH2_PORTSC1 &= ~PORTSC_PHCD;
+ }
+}
+
+static void fsl_usbh2_clock_gate(bool on)
+{
+ struct clk *usb_clk;
+ if (on) {
+ usb_clk = clk_get(NULL, "usb_ahb_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+ } else {
+ usb_clk = clk_get(NULL, "usb_ahb_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+ }
+}
+
+static enum usb_wakeup_event _is_usbh2_wakeup(struct fsl_usb2_platform_data *pdata)
+{
+ int wakeup_req = USBCTRL & UCTRL_H2WIR;
+
+ if (wakeup_req)
+ return !WAKEUP_EVENT_INVALID;
+
+ return WAKEUP_EVENT_INVALID;
+}
+
+static void h2_wakeup_handler(struct fsl_usb2_platform_data *pdata)
+{
+ _wake_up_enable(pdata, false);
+ _phy_lowpower_suspend(pdata, false);
+ fsl_usb_recover_hcd(&mxc_usbh2_device);
+}
+
+static void usbh2_wakeup_event_clear(void)
+{
+ int wakeup_req = USBCTRL & UCTRL_H2WIR;
+
+ if (wakeup_req != 0) {
+ printk(KERN_INFO "Unknown wakeup.(OTGSC 0x%x)\n", UOG_OTGSC);
+ /* Disable H2WIE to clear H2WIR, wait 3 clock
+ * cycles of standly clock(32KHz)
+ */
+ USBCTRL &= ~UCTRL_H2WIE;
+ udelay(100);
+ USBCTRL |= UCTRL_H2WIE;
+ }
+}
+static int fsl_usb_host_init_ext(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct clk *usb_clk;
+
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+
+ /* on mx53, there is a hardware limitation that when switch the host2's clk mode
+ * ,usb phy1 clk must be on, after finish switching this clk can be off */
+ if (cpu_is_mx53()) {
+ usb_clk = clk_get(NULL, "usb_phy1_clk");
+ clk_enable(usb_clk);
+ clk_put(usb_clk);
+ }
+
+ ret = fsl_usb_host_init(pdev);
+
+ if (cpu_is_mx53()) {
+ usb_clk = clk_get(NULL, "usb_phy1_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+ }
+
+ /* setback USBH2_STP to be function */
+ mxc_request_iomux(MX51_PIN_EIM_A26, IOMUX_CONFIG_ALT2);
+
+ return ret;
+}
+
+static void fsl_usb_host_uninit_ext(struct fsl_usb2_platform_data *pdata)
+{
+ struct clk *usb_clk;
+
+ usb_clk = clk_get(NULL, "usboh3_clk");
+ clk_disable(usb_clk);
+ clk_put(usb_clk);
+
+ fsl_usb_host_uninit(pdata);
+}
+
+static struct fsl_usb2_platform_data usbh2_config = {
+ .name = "Host 2",
+ .platform_init = fsl_usb_host_init_ext,
+ .platform_uninit = fsl_usb_host_uninit_ext,
+ .operating_mode = FSL_USB2_MPH_HOST,
+ .phy_mode = FSL_USB2_PHY_ULPI,
+ .power_budget = 500, /* 500 mA max power */
+ .wake_up_enable = _wake_up_enable,
+ .usb_clock_for_pm = fsl_usbh2_clock_gate,
+ .phy_lowpower_suspend = _phy_lowpower_suspend,
+ .gpio_usb_active = gpio_usbh2_active,
+ .gpio_usb_inactive = gpio_usbh2_inactive,
+ .is_wakeup_event = _is_usbh2_wakeup,
+ .wakeup_handler = h2_wakeup_handler,
+ .transceiver = "isp1504",
+};
+static struct fsl_usb2_wakeup_platform_data usbh2_wakeup_config = {
+ .name = "USBH2 wakeup",
+ .usb_clock_for_pm = fsl_usbh2_clock_gate,
+ .usb_pdata = {&usbh2_config, NULL, NULL},
+ .usb_wakeup_exhandle = usbh2_wakeup_event_clear,
+};
+void __init mx5_usbh2_init(void)
+{
+ usbh2_config.wakeup_pdata = &usbh2_wakeup_config;
+ mxc_register_device(&mxc_usbh2_device, &usbh2_config);
+ mxc_register_device(&mxc_usbh2_wakeup_device, &usbh2_wakeup_config);
+}
diff --git a/arch/arm/mach-mx5/wfi.S b/arch/arm/mach-mx5/wfi.S
new file mode 100644
index 000000000000..a6e373f4e08b
--- /dev/null
+++ b/arch/arm/mach-mx5/wfi.S
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/linkage.h>
+
+#define ARM_CTRL_DCACHE 1 << 2
+#define ARM_AUXCR_L2EN 1 << 1
+/*
+ * cpu_cortexa8_do_idle()
+ *
+ * Idle the processor (eg, wait for interrupt).
+ *
+ * IRQs are already disabled.
+ */
+ENTRY(cpu_cortexa8_do_idle)
+
+ mrc p15, 0, r1, c1, c0, 1 @ R1 = auxiliary control reg
+ ands r2, r1, #ARM_AUXCR_L2EN @ Check if L2 is disabled
+ beq SkipL2Access
+
+ mrc p15, 0, r2, c1, c0, 0 @ R2 = system control reg
+ bic r2, r2, #ARM_CTRL_DCACHE @ Disable DCache
+ mcr p15, 0, r2, c1, c0, 0 @ Update system control reg
+
+ bic r1, r1, #ARM_AUXCR_L2EN @ Disable L2 cache
+ mcr p15, 0, r1, c1, c0, 1 @ Update aux control reg
+
+ ldr r1, =(0x0 << 6) @ A[6] = 0
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x00] @ Save tag info
+
+ ldr r1, =(0x1 << 6) @ A[6] = 1
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x04] @ Save tag info
+
+ ldr r1, =(0x0 << 3) @ A[6:3] = b0000
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x08] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x0C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x10] @ Store data info
+
+ ldr r1, =(0x1 << 3) @ A[6:3] = b0001
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x14] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x18] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x1C] @ Store data info
+
+ ldr r1, =(0x2 << 3) @ A[6:3] = b0010
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x20] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x24] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x28] @ Store data info
+
+ ldr r1, =(0x3 << 3) @ A[6:3] = b0011
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x2C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x30] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x34] @ Store data info
+
+ ldr r1, =(0x4 << 3) @ A[6:3] = b0100
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x38] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x3C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x40] @ Store data info
+
+ ldr r1, =(0x5 << 3) @ A[6:3] = b0101
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x44] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x48] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x4C] @ Store data info
+
+ ldr r1, =(0x6 << 3) @ A[6:3] = b0110
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x50] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x54] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x58] @ Store data info
+
+ ldr r1, =(0x7 << 3) @ A[6:3] = b0111
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x5C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x60] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x64] @ Store data info
+
+ ldr r1, =(0x8 << 3) @ A[6:3] = b1000
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x68] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x6C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x70] @ Store data info
+
+ ldr r1, =(0x9 << 3) @ A[6:3] = b1001
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x74] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x78] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x7C] @ Store data info
+
+ ldr r1, =(0xA << 3) @ A[6:3] = b1010
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x80] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x84] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x88] @ Store data info
+
+ ldr r1, =(0xB << 3) @ A[6:3] = b1011
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x8C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x90] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0x94] @ Store data info
+
+ ldr r1, =(0xC << 3) @ A[6:3] = b1100
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0x98] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0x9C] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0xA0] @ Store data info
+
+ ldr r1, =(0xD << 3) @ A[6:3] = b1101
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xA4] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0xA8] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0xAC] @ Store data info
+
+ ldr r1, =(0xE << 3) @ A[6:3] = b1110
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xB0] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0xB4] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0xB8] @ Store data info
+
+ ldr r1, =(0xF << 3) @ A[6:3] = b1111
+ mcr p15, 0, r1, c15, c9, 3 @ Read L2 Data RAM into L2 data 0-2 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xBC] @ Store data info
+ mrc p15, 0, r2, c15, c8, 1 @ Move L2 data 1 register to R2
+ str r2, [r0, #0xC0] @ Store data info
+ mrc p15, 0, r2, c15, c8, 5 @ Move L2 data 2 register to R2
+ str r2, [r0, #0xC4] @ Store data info
+
+ ldr r1, =(0x2 << 29) | (0x0 << 6) @ WAY = A[31:29] = 2, A[6] = 0
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xC8] @ Save tag info
+
+ ldr r1, =(0x2 << 29) | (0x1 << 6) @ WAY = A[31:29] = 2, A[6] = 1
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xCC] @ Save tag info
+
+ ldr r1, =(0x4 << 29) | (0x0 << 6) @ WAY = A[31:29] = 4, A[6] = 0
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xD0] @ Save tag info
+
+ ldr r1, =(0x4 << 29) | (0x1 << 6) @ WAY = A[31:29] = 4, A[6] = 1
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xD4] @ Save tag info
+
+ ldr r1, =(0x6 << 29) | (0x0 << 6) @ WAY = A[31:29] = 6, A[6] = 0
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xD8] @ Save tag info
+
+ ldr r1, =(0x6 << 29) | (0x1 << 6) @ WAY = A[31:29] = 6, A[6] = 1
+ mcr p15, 0, r1, c15, c9, 2 @ Read L2 tag RAM into L2 data 0 register
+ mrc p15, 0, r2, c15, c8, 0 @ Move L2 data 0 register to R2
+ str r2, [r0, #0xDC] @ Save tag info
+
+ .long 0xe320f003 @ Opcode for WFI
+
+ ldr r1, =(0x0 << 6) @ A[6] = 0
+ ldr r2, [r0, #0x00] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x1 << 6) @ A[6] = 1
+ ldr r2, [r0, #0x04] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x0 << 3) @ A[6:3] = b0000
+ ldr r2, [r0, #0x08] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x0C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x10] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x1 << 3) @ A[6:3] = b0001
+ ldr r2, [r0, #0x14] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x18] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x1C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x2 << 3) @ A[6:3] = b0010
+ ldr r2, [r0, #0x20] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x24] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x28] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x3 << 3) @ A[6:3] = b0011
+ ldr r2, [r0, #0x2C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x30] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x34] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x4 << 3) @ A[6:3] = b0100
+ ldr r2, [r0, #0x38] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x3C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x40] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x5 << 3) @ A[6:3] = b0101
+ ldr r2, [r0, #0x44] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x48] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x4C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x6 << 3) @ A[6:3] = b0110
+ ldr r2, [r0, #0x50] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x54] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x58] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x7 << 3) @ A[6:3] = b0111
+ ldr r2, [r0, #0x5C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x60] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x64] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x8 << 3) @ A[6:3] = b1000
+ ldr r2, [r0, #0x68] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x6C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x70] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x9 << 3) @ A[6:3] = b1001
+ ldr r2, [r0, #0x74] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x78] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x7C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0xA << 3) @ A[6:3] = b1010
+ ldr r2, [r0, #0x80] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x84] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x88] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0xB << 3) @ A[6:3] = b1011
+ ldr r2, [r0, #0x8C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x90] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0x94] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0xC << 3) @ A[6:3] = b1100
+ ldr r2, [r0, #0x98] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0x9C] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0xA0] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0xD << 3) @ A[6:3] = b1101
+ ldr r2, [r0, #0xA4] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0xA8] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0xAC] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0xE << 3) @ A[6:3] = b1110
+ ldr r2, [r0, #0xB0] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0xB4] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0xB8] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0xF << 3) @ A[6:3] = b1111
+ ldr r2, [r0, #0xBC] @ Load data info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ ldr r2, [r0, #0xC0] @ Load data info
+ mcr p15, 0, r2, c15, c8, 1 @ Move R2 to L2 data 1 register
+ ldr r2, [r0, #0xC4] @ Load data info
+ mcr p15, 0, r2, c15, c8, 5 @ Move R2 to L2 data 2 register
+ mcr p15, 0, r1, c15, c8, 3 @ Write L2 data 0-2 registers to L2 data RAM
+
+ ldr r1, =(0x2 << 29) | (0x0 << 6) @ WAY = A[31:29] = 2, A[6] = 0
+ ldr r2, [r0, #0xC8] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x2 << 29) | (0x1 << 6) @ WAY = A[31:29] = 2, A[6] = 1
+ ldr r2, [r0, #0xCC] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x4 << 29) | (0x0 << 6) @ WAY = A[31:29] = 4, A[6] = 0
+ ldr r2, [r0, #0xD0] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x4 << 29) | (0x1 << 6) @ WAY = A[31:29] = 4, A[6] = 1
+ ldr r2, [r0, #0xD4] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x6 << 29) | (0x0 << 6) @ WAY = A[31:29] = 6, A[6] = 0
+ ldr r2, [r0, #0xD8] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ ldr r1, =(0x6 << 29) | (0x1 << 6) @ WAY = A[31:29] = 6, A[6] = 1
+ ldr r2, [r0, #0xDC] @ Load tag info
+ mcr p15, 0, r2, c15, c8, 0 @ Move R2 to L2 data 0 register
+ mcr p15, 0, r1, c15, c8, 2 @ Write L2 data 0 register to L2 tag RAM
+
+ mrc p15, 0, r1, c1, c0, 1 @ R1 = auxiliary control reg
+ orr r1, r1, #ARM_AUXCR_L2EN @ Enable L2 cache
+ mcr p15, 0, r1, c1, c0, 1 @ Update aux control reg
+
+ mrc p15, 0, r2, c1, c0, 0 @ R2 = system control reg
+ orr r2, r2, #ARM_CTRL_DCACHE @ Enable DCache
+ mcr p15, 0, r2, c1, c0, 0 @ Update system control reg
+
+ b Done
+
+SkipL2Access:
+ .long 0xe320f003 @ Opcode for WFI
+
+Done:
+ mov pc, lr
+
+ .type cortexa8_idle_workaround, #object
+ENTRY(cortexa8_idle_workaround)
+ .word cpu_cortexa8_do_idle
+ .size cortexa8_idle_workaround, . - cortexa8_idle_workaround