summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx25/mx25_3stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx25/mx25_3stack.c')
-rw-r--r--arch/arm/mach-mx25/mx25_3stack.c848
1 files changed, 848 insertions, 0 deletions
diff --git a/arch/arm/mach-mx25/mx25_3stack.c b/arch/arm/mach-mx25/mx25_3stack.c
new file mode 100644
index 000000000000..dc528dd5d130
--- /dev/null
+++ b/arch/arm/mach-mx25/mx25_3stack.c
@@ -0,0 +1,848 @@
+/*
+ * 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/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/nodemask.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/fec.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 <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach/keypad.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <mach/memory.h>
+#include <mach/gpio.h>
+#include <mach/mmc.h>
+
+#include "board-mx25_3stack.h"
+#include "crm_regs.h"
+#include "iomux.h"
+#include "devices.h"
+
+/*!
+ * @file mach-mx25/mx25_3stack.c
+ *
+ * @brief This file contains the board specific initialization routines.
+ *
+ * @ingroup MSL_MX25
+ */
+
+unsigned int mx25_3stack_board_io;
+
+/* working point(wp): 0 - 399MHz; 1 - 266MHz; 2 - 133MHz; */
+/* 24MHz input clock table */
+static struct cpu_wp cpu_wp_mx25[] = {
+ {
+ .pll_rate = 399000000,
+ .cpu_rate = 399000000,
+ .cpu_podf = 0x0,
+ .cpu_voltage = 1450000},
+ {
+ .pll_rate = 532000000,
+ .cpu_rate = 266000000,
+ .cpu_podf = 0x1,
+ .cpu_voltage = 1340000},
+ {
+ .pll_rate = 532000000,
+ .cpu_rate = 133000000,
+ .cpu_podf = 0x3,
+ .cpu_voltage = 1340000},
+};
+struct cpu_wp *get_cpu_wp(int *wp)
+{
+ *wp = 3;
+ return cpu_wp_mx25;
+}
+
+static void mxc_nop_release(struct device *dev)
+{
+ /* Nothing */
+}
+
+#if defined(CONFIG_KEYBOARD_MXC) || defined(CONFIG_KEYBOARD_MXC_MODULE)
+static u16 keymapping[16] = {
+ KEY_UP, KEY_DOWN, KEY_VOLUMEDOWN, KEY_HOME,
+ KEY_RIGHT, KEY_LEFT, KEY_ENTER, KEY_VOLUMEUP,
+ KEY_F6, KEY_F8, KEY_F9, KEY_F10,
+ KEY_F1, KEY_F2, KEY_F3, KEY_POWER,
+};
+
+static struct resource mxc_kpp_resources[] = {
+ [0] = {
+ .start = MX25_INT_KPP,
+ .end = MX25_INT_KPP,
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ .start = MX25_KPP_BASE_ADDR,
+ .end = MX25_KPP_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct keypad_data keypad_plat_data = {
+ .rowmax = 4,
+ .colmax = 4,
+ .learning = 0,
+ .delay = 2,
+ .matrix = keymapping,
+};
+
+/* mxc keypad driver */
+struct platform_device mxc_keypad_device = {
+ .name = "mxc_keypad",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mxc_kpp_resources),
+ .resource = mxc_kpp_resources,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &keypad_plat_data,
+ },
+};
+
+static void mxc_init_keypad(void)
+{
+ (void)platform_device_register(&mxc_keypad_device);
+}
+#else
+static inline void mxc_init_keypad(void)
+{
+}
+#endif
+
+/* MTD NAND flash */
+
+#if defined(CONFIG_MTD_NAND_MXC_V2) || defined(CONFIG_MTD_NAND_MXC_V2_MODULE)
+
+static struct mtd_partition mxc_nand_partitions[] = {
+ {
+ .name = "nand.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.configure",
+ .offset = MTDPART_OFS_APPEND,
+ .size = 8 * 1024 * 1024},
+ {
+ .name = "nand.userfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL},
+};
+
+static struct resource mxc_nand_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ .name = "NFC_AXI_BASE",
+ .start = MX25_NFC_BASE_ADDR,
+ .end = MX25_NFC_BASE_ADDR + SZ_8K - 1,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ .start = MX25_INT_NANDFC,
+ .end = MX25_INT_NANDFC,
+ },
+};
+
+
+static struct flash_platform_data mxc_nand_data = {
+ .parts = mxc_nand_partitions,
+ .nr_parts = ARRAY_SIZE(mxc_nand_partitions),
+ .width = 1,
+};
+
+static struct platform_device mxc_nand_mtd_device = {
+ .name = "mxc_nandv2_flash",
+ .id = 0,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &mxc_nand_data,
+ },
+ .resource = mxc_nand_resources,
+ .num_resources = ARRAY_SIZE(mxc_nand_resources),
+};
+
+static void mxc_init_nand_mtd(void)
+{
+ if (__raw_readl(MXC_CCM_RCSR) & MXC_CCM_RCSR_NF16B)
+ mxc_nand_data.width = 2;
+
+ platform_device_register(&mxc_nand_mtd_device);
+}
+#else
+static inline void mxc_init_nand_mtd(void)
+{
+}
+#endif
+
+#if defined(CONFIG_FB_MXC_SYNC_PANEL) || \
+ defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE)
+static const char fb_default_mode[] = "CPT-VGA";
+
+/* mxc lcd driver */
+static struct platform_device mxc_fb_device = {
+ .name = "mxc_sdc_fb",
+ .id = 0,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &fb_default_mode,
+ .coherent_dma_mask = 0xFFFFFFFF,
+ },
+};
+
+/*
+ * Power on/off CPT VGA panel.
+ */
+void board_power_lcd(int on)
+{
+ if (on) {
+ /* Enable HSYNC bit of touch screen */
+ imx_adc_set_hsync(1);
+ mx2fb_set_brightness(MXC_DEFAULT_INTENSITY);
+ } else {
+ /* disable HSYNC bit of touchscreen */
+ imx_adc_set_hsync(0);
+ mx2fb_set_brightness(MXC_INTENSITY_OFF);
+ }
+}
+EXPORT_SYMBOL_GPL(board_power_lcd);
+
+static void mxc_init_fb(void)
+{
+ (void)platform_device_register(&mxc_fb_device);
+}
+#else
+static inline void mxc_init_fb(void)
+{
+}
+#endif
+
+#if defined(CONFIG_BACKLIGHT_MXC)
+static struct platform_device mxcbl_devices[] = {
+#if defined(CONFIG_BACKLIGHT_MXC_LCDC) || \
+ defined(CONFIG_BACKLIGHT_MXC_LCDC_MODULE)
+ {
+ .name = "mxc_lcdc_bl",
+ .id = 0,
+ },
+#endif
+};
+
+static inline void mxc_init_bl(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mxcbl_devices); i++)
+ platform_device_register(&mxcbl_devices[i]);
+}
+#else
+static inline void mxc_init_bl(void)
+{
+}
+#endif
+
+/*!
+ * Power Key interrupt handler.
+ */
+static irqreturn_t power_key_int(int irq, void *dev_id)
+{
+ pr_info("on-off key pressed\n");
+ return 0;
+}
+
+/*!
+ * Power Key initialization.
+ */
+static int __init mxc_init_power_key(void)
+{
+ /*Set power key as wakeup resource */
+ int irq, ret;
+
+ mxc_request_iomux(MX25_PIN_A25, MUX_CONFIG_ALT5);
+ mxc_iomux_set_pad(MX25_PIN_A25, PAD_CTL_DRV_NORMAL);
+ gpio_request(IOMUX_TO_GPIO(MX25_PIN_A25), NULL);
+ gpio_direction_input(IOMUX_TO_GPIO(MX25_PIN_A25));
+
+ irq = IOMUX_TO_IRQ(MX25_PIN_A25);
+ set_irq_type(irq, IRQF_TRIGGER_RISING);
+ ret = request_irq(irq, power_key_int, 0, "power_key", 0);
+ if (ret)
+ pr_info("register on-off key interrupt failed\n");
+ else
+ enable_irq_wake(irq);
+
+ return ret;
+}
+
+late_initcall(mxc_init_power_key);
+
+static struct spi_board_info mxc_spi_board_info[] __initdata = {
+ {
+ .modalias = "cpld_spi",
+ .max_speed_hz = 18000000,
+ .bus_num = 1,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ },
+ {
+ .modalias = "wm8580_spi",
+ .max_speed_hz = 8000000, /* max spi SCK clock speed in HZ */
+ .bus_num = 1,
+ .chip_select = 1,
+ },
+};
+
+static struct mxc_camera_platform_data camera_data = {
+ .core_regulator = NULL,
+ .io_regulator = NULL,
+ .analog_regulator = NULL,
+ .gpo_regulator = NULL,
+ .mclk = 24000000,
+};
+
+static struct i2c_board_info mxc_i2c_board_info[] __initdata = {
+ {
+ .type = "sgtl5000-i2c",
+ .addr = 0x0a,
+ },
+ {
+ .type = "ak5702-i2c",
+ .addr = 0x13,
+ },
+ {
+ .type = "ov2640",
+ .addr = 0x30,
+ .platform_data = (void *)&camera_data,
+ },
+};
+
+#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) \
+ || defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE)
+static struct mxc_audio_platform_data sgtl5000_data = {
+ .ssi_num = 2,
+ .src_port = 1,
+ .ext_port = 4,
+ .hp_irq = IOMUX_TO_IRQ(MX25_PIN_A10),
+ .hp_status = headphone_det_status,
+ .sysclk = 8300000,
+};
+
+static struct platform_device mxc_sgtl5000_device = {
+ .name = "imx-3stack-sgtl5000",
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &sgtl5000_data,
+ },
+};
+
+static void mxc_init_sgtl5000(void)
+{
+ struct clk *cko1, *parent;
+ unsigned long rate;
+
+ /* cko1 clock */
+ mxc_request_iomux(MX25_PIN_CLKO, MUX_CONFIG_FUNC);
+
+ cko1 = clk_get(NULL, "clko_clk");
+ if (IS_ERR(cko1))
+ return;
+ parent = clk_get(NULL, "ipg_clk");
+ if (IS_ERR(parent))
+ return;
+ clk_set_parent(cko1, parent);
+ rate = clk_round_rate(cko1, 13000000);
+ if (rate < 8000000 || rate > 27000000) {
+ pr_err("Error: SGTL5000 mclk freq %ld out of range!\n", rate);
+ clk_put(parent);
+ clk_put(cko1);
+ return;
+ }
+ clk_set_rate(cko1, rate);
+ clk_enable(cko1);
+ sgtl5000_data.sysclk = rate;
+ sgtl5000_enable_amp();
+ platform_device_register(&mxc_sgtl5000_device);
+}
+#else
+static inline void mxc_init_sgtl5000(void)
+{
+}
+#endif
+
+#if defined(CONFIG_SND_SOC_IMX_3STACK_AK5702) \
+ || defined(CONFIG_SND_SOC_IMX_3STACK_AK5702_MODULE)
+static struct platform_device mxc_ak5702_device = {
+ .name = "imx-3stack-ak5702",
+ .dev = {
+ .release = mxc_nop_release,
+ },
+};
+
+static void mxc_init_ak5702(void)
+{
+ platform_device_register(&mxc_ak5702_device);
+}
+#else
+static inline void mxc_init_ak5702(void)
+{
+}
+#endif
+
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+static struct resource smsc911x_resources[] = {
+ {
+ .start = LAN9217_BASE_ADDR,
+ .end = LAN9217_BASE_ADDR + 255,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MXC_BOARD_IRQ_START,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct smsc911x_platform_config smsc911x_config = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .flags = 0x8000 | SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+};
+
+static struct platform_device smsc_lan9217_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &smsc911x_config,
+ },
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+};
+
+static int __init mxc_init_enet(void)
+{
+ (void)platform_device_register(&smsc_lan9217_device);
+ return 0;
+}
+#else
+static int __init mxc_init_enet(void)
+{
+ return 0;
+}
+#endif
+
+late_initcall(mxc_init_enet);
+
+#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)
+static struct resource mxc_fec_resources[] = {
+ {
+ .start = MX25_FEC_BASE_ADDR,
+ .end = MX25_FEC_BASE_ADDR + 0xfff,
+ .flags = IORESOURCE_MEM
+ }, {
+ .start = MX25_INT_FEC,
+ .end = MX25_INT_FEC,
+ .flags = IORESOURCE_IRQ
+ },
+};
+
+static struct fec_platform_data fec_data = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+struct platform_device mxc_fec_device = {
+ .name = "fec",
+ .id = 0,
+ .dev = {
+ .platform_data = &fec_data,
+ },
+ .num_resources = ARRAY_SIZE(mxc_fec_resources),
+ .resource = mxc_fec_resources,
+};
+
+static __init int mxc_init_fec(void)
+{
+ return platform_device_register(&mxc_fec_device);
+}
+#else
+static inline int mxc_init_fec(void)
+{
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_IMX_SIM) || defined(CONFIG_IMX_SIM_MODULE)
+/* Used to configure the SIM bus */
+static struct mxc_sim_platform_data sim1_data = {
+ .clk_rate = 5000000,
+ .clock_sim = "sim1_clk",
+ .power_sim = NULL,
+ .init = NULL,
+ .exit = NULL,
+ .detect = 1,
+};
+
+/*!
+ * Resource definition for the SIM
+ */
+static struct resource mxc_sim1_resources[] = {
+ [0] = {
+ .start = MX25_SIM1_BASE_ADDR,
+ .end = MX25_SIM1_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MX25_INT_SIM1,
+ .end = MX25_INT_SIM1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/*! Device Definition for IMX SIM */
+static struct platform_device mxc_sim1_device = {
+ .name = "mxc_sim",
+ .id = 0,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &sim1_data,
+ },
+ .num_resources = ARRAY_SIZE(mxc_sim1_resources),
+ .resource = mxc_sim1_resources,
+};
+
+static inline void mxc_init_sim(void)
+{
+ (void)platform_device_register(&mxc_sim1_device);
+}
+#else
+static inline void mxc_init_sim(void)
+{
+}
+#endif
+
+#if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE)
+static struct mxc_mmc_platform_data mmc1_data = {
+ .ocr_mask = MMC_VDD_29_30 | MMC_VDD_32_33,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 52000000,
+ .card_inserted_state = 1,
+ .status = sdhc_get_card_det_status,
+ .wp_status = sdhc_write_protect,
+ .clock_mmc = "esdhc_clk",
+};
+
+/*!
+ * Resource definition for the SDHC1
+ */
+static struct resource mxcsdhc1_resources[] = {
+ [0] = {
+ .start = MX25_MMC_SDHC1_BASE_ADDR,
+ .end = MX25_MMC_SDHC1_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MX25_INT_SDHC1,
+ .end = MX25_INT_SDHC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IOMUX_TO_IRQ(MX25_PIN_A15),
+ .end = IOMUX_TO_IRQ(MX25_PIN_A15),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/*! Device Definition for MXC SDHC1 */
+static struct platform_device mxcsdhc1_device = {
+ .name = "mxsdhci",
+ .id = 0,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &mmc1_data,
+ },
+ .num_resources = ARRAY_SIZE(mxcsdhc1_resources),
+ .resource = mxcsdhc1_resources,
+};
+
+#ifdef CONFIG_MMC_IMX_ESDHCI_SELECT2
+static struct mxc_mmc_platform_data mmc2_data = {
+ .ocr_mask = MMC_VDD_29_30 | MMC_VDD_32_33,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .min_clk = 400000,
+ .max_clk = 52000000,
+ .card_fixed = 1,
+ .card_inserted_state = 1,
+ .status = sdhc_get_card_det_status,
+ .clock_mmc = "esdhc2_clk",
+};
+
+/*!
+ * Resource definition for the SDHC2
+ */
+static struct resource mxcsdhc2_resources[] = {
+ [0] = {
+ .start = MX25_MMC_SDHC2_BASE_ADDR,
+ .end = MX25_MMC_SDHC2_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MX25_INT_SDHC2,
+ .end = MX25_INT_SDHC2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/*! Device Definition for MXC SDHC2 */
+static struct platform_device mxcsdhc2_device = {
+ .name = "mxsdhci",
+ .id = 1,
+ .dev = {
+ .release = mxc_nop_release,
+ .platform_data = &mmc2_data,
+ },
+ .num_resources = ARRAY_SIZE(mxcsdhc2_resources),
+ .resource = mxcsdhc2_resources,
+};
+#endif
+
+static inline void mxc_init_mmc(void)
+{
+ (void)platform_device_register(&mxcsdhc1_device);
+#ifdef CONFIG_MMC_IMX_ESDHCI_SELECT2
+ (void)platform_device_register(&mxcsdhc2_device);
+#endif
+}
+#else
+static inline void mxc_init_mmc(void)
+{
+}
+#endif
+
+static void __init mx25_3stack_timer_init(void)
+{
+ struct clk *uart_clk;
+
+ mx25_clocks_init();
+ uart_clk = clk_get_sys("imx-uart.0", NULL);
+ early_console_setup(MX25_UART1_BASE_ADDR, uart_clk);
+}
+
+static struct sys_timer mxc_timer = {
+ .init = mx25_3stack_timer_init,
+};
+
+#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE)
+static void flexcan_xcvr_enable(int id, int en)
+{
+ static int pwdn;
+
+ if (id != 1) /* MX25 3-stack uses only CAN2 */
+ return;
+
+ if (en) {
+ if (!pwdn++)
+ gpio_set_value(IOMUX_TO_GPIO(MX25_PIN_D14), 0);
+ } else {
+ if (!--pwdn)
+ gpio_set_value(IOMUX_TO_GPIO(MX25_PIN_D14), 1);
+ }
+}
+
+struct flexcan_platform_data flexcan_data[] = {
+ {
+ .core_reg = NULL,
+ .io_reg = NULL,
+ .xcvr_enable = flexcan_xcvr_enable,
+ .active = gpio_can_active,
+ .inactive = gpio_can_inactive,
+ .br_clksrc = 1,
+ .br_rjw = 2,
+ .br_presdiv = 6,
+ .br_propseg = 4,
+ .br_pseg1 = 4,
+ .br_pseg2 = 7,
+ .bcc = 1,
+ .srx_dis = 1,
+ .smp = 1,
+ .boff_rec = 1,
+ .ext_msg = 1,
+ .std_msg = 1,},
+ {
+ .core_reg = NULL,
+ .io_reg = NULL,
+ .xcvr_enable = flexcan_xcvr_enable,
+ .active = gpio_can_active,
+ .inactive = gpio_can_inactive,
+ .br_clksrc = 1,
+ .br_rjw = 2,
+ .br_presdiv = 6,
+ .br_propseg = 4,
+ .br_pseg1 = 4,
+ .br_pseg2 = 7,
+ .bcc = 1,
+ .srx_dis = 1,
+ .smp = 1,
+ .boff_rec = 1,
+ .ext_msg = 1,
+ .std_msg = 1,},
+};
+
+static struct resource flexcan1_resources[] = {
+ {
+ .start = MX25_CAN1_BASE_ADDR,
+ .end = MX25_CAN1_BASE_ADDR + 0x97F,
+ .flags = IORESOURCE_MEM,},
+ {
+ .start = MX25_INT_CAN1,
+ .end = MX25_INT_CAN1,
+ .flags = IORESOURCE_IRQ,}
+};
+static struct resource flexcan2_resources[] = {
+ {
+ .start = MX25_CAN3_BASE_ADDR,
+ .end = MX25_CAN3_BASE_ADDR + 0x97F,
+ .flags = IORESOURCE_MEM,},
+ {
+ .start = MX25_INT_CAN2,
+ .end = MX25_INT_CAN2,
+ .flags = IORESOURCE_IRQ,}
+};
+
+static struct platform_device flexcan_devices[] = {
+ {
+ .name = "FlexCAN",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(flexcan1_resources),
+ .resource = flexcan1_resources,},
+ {
+ .name = "FlexCAN",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(flexcan2_resources),
+ .resource = flexcan2_resources,},
+};
+
+static inline void mxc_init_flexcan(void)
+{
+#ifdef CONFIG_FLEXCAN_MXC_SELECT1
+ /* MX25 3stack doesn't use CAN1 */
+ mxc_register_device(&flexcan_devices[0], &flexcan_data[0]);
+#endif
+ mxc_register_device(&flexcan_devices[1], &flexcan_data[1]);
+}
+#else
+static inline void mxc_init_flexcan(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)
+{
+ mxc_cpu_init();
+
+#ifdef CONFIG_DISCONTIGMEM
+ do {
+ int nid;
+ mi->nr_banks = MXC_NUMNODES;
+ for (nid = 0; nid < mi->nr_banks; nid++)
+ SET_NODE(mi, nid);
+ } while (0);
+#endif
+}
+
+/*!
+ * Board specific initialization.
+ */
+static void __init mxc_board_init(void)
+{
+ pr_info("AIPS1 VA base: 0x%p\n", IO_ADDRESS(MX25_AIPS1_BASE_ADDR));
+ mxc_cpu_common_init();
+ mx25_3stack_gpio_init();
+ mxc_init_keypad();
+#ifdef CONFIG_I2C
+ i2c_register_board_info(0, mxc_i2c_board_info,
+ ARRAY_SIZE(mxc_i2c_board_info));
+#endif
+ spi_register_board_info(mxc_spi_board_info,
+ ARRAY_SIZE(mxc_spi_board_info));
+ mx25_3stack_init_mc34704();
+ mxc_init_fb();
+ mxc_init_bl();
+ mxc_init_nand_mtd();
+ mxc_init_sgtl5000();
+ mxc_init_ak5702();
+ mxc_init_mmc();
+ mxc_init_sim();
+ mxc_init_fec();
+ mxc_init_flexcan();
+ mxc_register_device(&mx25_rtc_device, NULL);
+}
+
+/*
+ * The following uses standard kernel macros define in arch.h in order to
+ * initialize __mach_desc_MX25_3DS data structure.
+ */
+/* *INDENT-OFF* */
+MACHINE_START(MX25_3DS, "Freescale MX25 3-Stack Board")
+ /* Maintainer: Freescale Semiconductor, Inc. */
+ .phys_io = MX25_AIPS1_BASE_ADDR,
+ .io_pg_offst = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
+ .boot_params = PHYS_OFFSET + 0x100,
+ .fixup = fixup_mxc_board,
+ .map_io = mx25_map_io,
+ .init_irq = mx25_init_irq,
+ .init_machine = mxc_board_init,
+ .timer = &mxc_timer,
+MACHINE_END