summaryrefslogtreecommitdiffstats
path: root/arch/arm/boards/ccxmx51/ccxmx51.c
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2012-06-14 10:59:38 +0400
committerSascha Hauer <s.hauer@pengutronix.de>2012-06-30 12:46:12 +0200
commitfe25781a1b56b5cc39e4da55db146def5a0385c7 (patch)
treea417330816136ce2e68a70933b3910adbcd15813 /arch/arm/boards/ccxmx51/ccxmx51.c
parent68b32be4926d3ab5b72036c0ceecef2f82aa0625 (diff)
downloadbarebox-fe25781a1b56b5cc39e4da55db146def5a0385c7.tar.gz
barebox-fe25781a1b56b5cc39e4da55db146def5a0385c7.tar.xz
ARM: initial ConnectCore® i.MX51 board support
This patch adds support for ConnectCore® i.MX51 board from Digi International. A separate option includes support for debugging board for this module. Some code taken from the bootloader U-Boot and patch from Digi. Functional of Ethernet not tested yet. barebox 2012.05.0-00316-g4024d9c-dirty #0 Wed Jun 6 13:08:25 MSK 2012 Board: ConnectCore i.MX51 Module Variant: i.MX515@600MHz, PHY, Acceleromter (0x0b) Module HW Rev : 02 Module Serial : B111156789 mc13xxx-spi@mc13xxx-spi0: Found MC13892 ID: 0x0045d0 [Rev: 2.0a] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xda (Micron NAND 256MiB 3,3V 8-bit) Bad block table found at page 131008, version 0x01 Bad block table found at page 130944, version 0x01 nand_read_bbt: Bad block at 0x00ce0000 nand_read_bbt: Bad block at 0x05bc0000 nand_read_bbt: Bad block at 0x0bc40000 ehci@ehci0: USB EHCI 1.00 detected i.MX51 rev 3.0 imx-esdhc@mci0: registered as mci0 imx-esdhc@mci1: registered as mci1 Malloc space: 0x95f00000 -> 0x97efffff (size 32 MB) Stack space : 0x95ef8000 -> 0x95f00000 (size 32 kB) envfs: wrong magic on /dev/env0 no valid environment found on /dev/env0. Using default environment running /env/bin/init... Hit any key to stop autoboot: 3 barebox@ConnectCore i.MX51:/ Signed-off-by: Alexander Shiyan <shc_work@mail.ru> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/boards/ccxmx51/ccxmx51.c')
-rw-r--r--arch/arm/boards/ccxmx51/ccxmx51.c489
1 files changed, 489 insertions, 0 deletions
diff --git a/arch/arm/boards/ccxmx51/ccxmx51.c b/arch/arm/boards/ccxmx51/ccxmx51.c
new file mode 100644
index 0000000000..f494174b18
--- /dev/null
+++ b/arch/arm/boards/ccxmx51/ccxmx51.c
@@ -0,0 +1,489 @@
+/*
+ * (C) Copyright 2009-2010 Digi International, Inc.
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * (c) 2011 Eukrea Electromatique, Eric Bénard <eric@eukrea.com>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <net.h>
+#include <init.h>
+#include <environment.h>
+#include <mach/imx-regs.h>
+#include <fec.h>
+#include <mach/gpio.h>
+#include <asm/armlinux.h>
+#include <generated/mach-types.h>
+#include <partition.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <sizes.h>
+#include <nand.h>
+#include <notifier.h>
+#include <spi/spi.h>
+#include <mfd/mc13xxx.h>
+#include <asm/io.h>
+#include <mach/imx-nand.h>
+#include <mach/spi.h>
+#include <mach/generic.h>
+#include <mach/iomux-mx51.h>
+#include <mach/devices-imx51.h>
+#include <mach/iim.h>
+#include <mach/clock-imx51_53.h>
+#include <mach/imx5.h>
+
+#include "ccxmx51.h"
+
+static struct ccxmx51_ident ccxmx51_ids[] = {
+/* 0x00 */ { "Unknown", 0, 0, 0, 0, 0 },
+/* 0x01 */ { "Not supported", 0, 0, 0, 0, 0 },
+/* 0x02 */ { "i.MX515@800MHz, Wireless, PHY, Ext. Eth, Accel", SZ_512M, 0, 1, 1, 1 },
+/* 0x03 */ { "i.MX515@800MHz, PHY, Ext. Eth, Accel", SZ_512M, 0, 1, 1, 0 },
+/* 0x04 */ { "i.MX515@600MHz, Wireless, PHY, Ext. Eth, Accel", SZ_512M, 1, 1, 1, 1 },
+/* 0x05 */ { "i.MX515@600MHz, PHY, Ext. Eth, Accel", SZ_512M, 1, 1, 1, 0 },
+/* 0x06 */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_512M, 0, 1, 0, 1 },
+/* 0x07 */ { "i.MX515@800MHz, PHY, Accel", SZ_512M, 0, 1, 0, 0 },
+/* 0x08 */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_256M, 0, 1, 0, 1 },
+/* 0x09 */ { "i.MX515@800MHz, PHY, Accel", SZ_256M, 0, 1, 0, 0 },
+/* 0x0a */ { "i.MX515@600MHz, Wireless, PHY, Accel", SZ_256M, 1, 1, 0, 1 },
+/* 0x0b */ { "i.MX515@600MHz, PHY, Accel", SZ_256M, 1, 1, 0, 0 },
+/* 0x0c */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_128M, 0, 1, 0, 1 },
+/* 0x0d */ { "i.MX512@800MHz", SZ_128M, 0, 0, 0, 0 },
+/* 0x0e */ { "i.MX515@800MHz, Wireless, PHY, Accel", SZ_512M, 0, 1, 0, 1 },
+/* 0x0f */ { "i.MX515@600MHz, PHY, Accel", SZ_128M, 1, 1, 0, 0 },
+/* 0x10 */ { "i.MX515@600MHz, Wireless, PHY, Accel", SZ_128M, 1, 1, 0, 1 },
+/* 0x11 */ { "i.MX515@800MHz, PHY, Accel", SZ_128M, 0, 1, 0, 0 },
+/* 0x12 */ { "i.MX515@600MHz, Wireless, PHY, Accel", SZ_512M, 1, 1, 0, 1 },
+/* 0x13 */ { "i.MX515@800MHz, PHY, Accel", SZ_512M, 0, 1, 0, 0 },
+};
+
+struct ccxmx51_ident *ccxmx51_id;
+
+struct imx_nand_platform_data nand_info = {
+ .width = 1,
+ .hw_ecc = 1,
+ .flash_bbt = 1,
+};
+
+#ifdef CONFIG_DRIVER_NET_FEC_IMX
+static struct fec_platform_data fec_info = {
+ .xcv_type = MII100,
+ .phy_addr = 7,
+};
+#endif
+
+static iomux_v3_cfg_t ccxmx51_pads[] = {
+ /* UART1 */
+ MX51_PAD_UART1_RXD__UART1_RXD,
+ MX51_PAD_UART1_TXD__UART1_TXD,
+ /* UART2 */
+ MX51_PAD_UART2_RXD__UART2_RXD,
+ MX51_PAD_UART2_TXD__UART2_TXD,
+ /* UART3 */
+ MX51_PAD_UART3_RXD__UART3_RXD,
+ MX51_PAD_UART3_TXD__UART3_TXD,
+ /* I2C2 */
+ MX51_PAD_GPIO1_2__I2C2_SCL,
+ MX51_PAD_GPIO1_3__I2C2_SDA,
+ /* eCSPI1 */
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+ MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+ MX51_PAD_CSPI1_SS0__ECSPI1_SS0,
+ MX51_PAD_CSPI1_SS1__ECSPI1_SS1,
+ /* FEC */
+ MX51_PAD_DISP2_DAT14__FEC_RDATA0,
+ MX51_PAD_DI2_DISP_CLK__FEC_RDATA1,
+ MX51_PAD_DI_GP4__FEC_RDATA2,
+ MX51_PAD_DISP2_DAT0__FEC_RDATA3,
+ MX51_PAD_DISP2_DAT15__FEC_TDATA0,
+ MX51_PAD_DISP2_DAT6__FEC_TDATA1,
+ MX51_PAD_DISP2_DAT7__FEC_TDATA2,
+ MX51_PAD_DISP2_DAT8__FEC_TDATA3,
+ MX51_PAD_DISP2_DAT9__FEC_TX_EN,
+ MX51_PAD_DISP2_DAT10__FEC_COL,
+ MX51_PAD_DISP2_DAT11__FEC_RX_CLK,
+ MX51_PAD_DISP2_DAT12__FEC_RX_DV,
+ MX51_PAD_DISP2_DAT13__FEC_TX_CLK,
+ MX51_PAD_DI2_PIN2__FEC_MDC,
+ MX51_PAD_DI2_PIN4__FEC_CRS,
+ MX51_PAD_DI2_PIN3__FEC_MDIO,
+ MX51_PAD_DI_GP3__FEC_TX_ER,
+ MX51_PAD_DISP2_DAT1__FEC_RX_ER,
+ /* WEIM */
+ MX51_PAD_EIM_DA0__EIM_DA0,
+ MX51_PAD_EIM_DA1__EIM_DA1,
+ MX51_PAD_EIM_DA2__EIM_DA2,
+ MX51_PAD_EIM_DA3__EIM_DA3,
+ MX51_PAD_EIM_DA4__EIM_DA4,
+ MX51_PAD_EIM_DA5__EIM_DA5,
+ MX51_PAD_EIM_DA6__EIM_DA6,
+ MX51_PAD_EIM_DA7__EIM_DA7,
+ MX51_PAD_EIM_D16__EIM_D16,
+ MX51_PAD_EIM_D17__EIM_D17,
+ MX51_PAD_EIM_D18__EIM_D18,
+ MX51_PAD_EIM_D19__EIM_D19,
+ MX51_PAD_EIM_D20__EIM_D20,
+ MX51_PAD_EIM_D21__EIM_D21,
+ MX51_PAD_EIM_D22__EIM_D22,
+ MX51_PAD_EIM_D23__EIM_D23,
+ MX51_PAD_EIM_D24__EIM_D24,
+ MX51_PAD_EIM_D25__EIM_D25,
+ MX51_PAD_EIM_D26__EIM_D26,
+ MX51_PAD_EIM_D27__EIM_D27,
+ MX51_PAD_EIM_D28__EIM_D28,
+ MX51_PAD_EIM_D29__EIM_D29,
+ MX51_PAD_EIM_D30__EIM_D30,
+ MX51_PAD_EIM_D31__EIM_D31,
+ MX51_PAD_EIM_OE__EIM_OE,
+ MX51_PAD_EIM_CS5__EIM_CS5,
+ /* NAND */
+ MX51_PAD_NANDF_D0__NANDF_D0,
+ MX51_PAD_NANDF_D1__NANDF_D1,
+ MX51_PAD_NANDF_D2__NANDF_D2,
+ MX51_PAD_NANDF_D3__NANDF_D3,
+ MX51_PAD_NANDF_D4__NANDF_D4,
+ MX51_PAD_NANDF_D5__NANDF_D5,
+ MX51_PAD_NANDF_D6__NANDF_D6,
+ MX51_PAD_NANDF_D7__NANDF_D7,
+ MX51_PAD_NANDF_ALE__NANDF_ALE,
+ MX51_PAD_NANDF_CLE__NANDF_CLE,
+ MX51_PAD_NANDF_RE_B__NANDF_RE_B,
+ MX51_PAD_NANDF_WE_B__NANDF_WE_B,
+ MX51_PAD_NANDF_WP_B__NANDF_WP_B,
+ MX51_PAD_NANDF_CS0__NANDF_CS0,
+ MX51_PAD_NANDF_RB0__NANDF_RB0,
+ /* LAN9221 IRQ (GPIO1.9) */
+ MX51_PAD_GPIO1_9__GPIO1_9,
+ /* MC13892 IRQ (GPIO1.5) */
+ MX51_PAD_GPIO1_5__GPIO1_5,
+ /* MMA7455LR IRQ1 (GPIO1.7) */
+ MX51_PAD_GPIO1_7__GPIO1_7,
+ /* MMA7455LR IRQ2 (GPIO1.6) */
+ MX51_PAD_GPIO1_6__GPIO1_6,
+};
+
+#define CCXMX51_ECSPI1_CS0 IMX_GPIO_NR(4, 24)
+#define CCXMX51_ECSPI1_CS1 IMX_GPIO_NR(4, 25)
+
+static int ecspi_0_cs[] = { CCXMX51_ECSPI1_CS0, CCXMX51_ECSPI1_CS1, };
+
+static struct spi_imx_master ecspi_0_data = {
+ .chipselect = ecspi_0_cs,
+ .num_chipselect = ARRAY_SIZE(ecspi_0_cs),
+};
+
+static const struct spi_board_info ccxmx51_spi_board_info[] = {
+ {
+ .name = "mc13xxx-spi",
+ .max_speed_hz = 6000000,
+ .bus_num = 0,
+ .chip_select = 0,
+ },
+};
+
+static int ccxmx51_mem_init(void)
+{
+ /* Add minimal SDRAM first */
+ arm_add_mem_device("ram0", MX51_CSD0_BASE_ADDR, SZ_128M);
+
+ return 0;
+}
+mem_initcall(ccxmx51_mem_init);
+
+static void ccxmx51_otghost_init(void)
+{
+#define MX51_USBOTHER_REGS_OFFSET 0x800
+#define MX51_USBCTRL_OFFSET 0x0
+#define MX51_USB_PHY_CTR_FUNC_OFFSET 0x8
+#define MX51_USB_PHY_CTR_FUNC2_OFFSET 0xc
+#define MX51_USB_UTMI_PHYCTRL1_PLLDIV_MASK 0x3
+#define MX51_USB_PLL_DIV_19_2_MHZ 0x00
+#define MX51_USB_PLL_DIV_24_MHZ 0x01
+#define MX51_USB_PLL_DIV_26_MHZ 0x02
+#define MX51_USB_PLL_DIV_27_MHZ 0x03
+#define MX51_OTG_PHYCTRL_OC_DIS_BIT (1 << 8)
+#define MX51_OTG_UCTRL_OWIE_BIT (1 << 27)
+#define MX51_OTG_UCTRL_OPM_BIT (1 << 24)
+
+#define USBOTHER_BASE (MX51_OTG_BASE_ADDR + MX51_USBOTHER_REGS_OFFSET)
+
+ u32 reg;
+
+ /* Set sysclock to 24 MHz */
+ reg = readl(USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC2_OFFSET);
+ reg &= ~MX51_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+ reg |= MX51_USB_PLL_DIV_24_MHZ;
+ writel(reg, USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC2_OFFSET);
+
+ /* OC is not used */
+ reg = readl(USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC_OFFSET);
+ reg |= MX51_OTG_PHYCTRL_OC_DIS_BIT;
+ writel(reg, USBOTHER_BASE + MX51_USB_PHY_CTR_FUNC_OFFSET);
+
+ /* Power pins enable */
+ reg = readl(USBOTHER_BASE + MX51_USBCTRL_OFFSET);
+ reg |= MX51_OTG_UCTRL_OWIE_BIT | MX51_OTG_UCTRL_OPM_BIT;
+ writel(reg, USBOTHER_BASE + MX51_USBCTRL_OFFSET);
+
+ /* Setup PORTSC */
+ reg = readl(MX51_OTG_BASE_ADDR + 0x184);
+ reg &= ~(3 << 30);
+ reg |= 1 << 28;
+ writel(reg, MX51_OTG_BASE_ADDR + 0x184);
+
+ mdelay(10);
+
+ add_generic_usb_ehci_device(0, MX51_OTG_BASE_ADDR, NULL);
+}
+
+static int ccxmx51_power_init(void)
+{
+ struct mc13xxx *mc13xxx_dev;
+ u32 val;
+
+ mc13xxx_dev = mc13xxx_get();
+ if (!mc13xxx_dev)
+ return -ENODEV;
+
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_POWER_MISC, &val);
+ /* Reset devices by clearing GP01-GPO4 */
+ val &= ~((1 << 21) | (3 << 12) | (3 << 10) | (3 << 8) | (3 << 6));
+ /* Switching off the PWGT1SPIEN */
+ val |= (1 << 15);
+ /* Switching on the PWGT2SPIEN */
+ val &= ~(1 << 16);
+ /* Enable short circuit protection */
+ val |= (1 << 0);
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_MISC, val);
+
+ /* Allow charger to charge (4.2V and 560mA) */
+ val = 0x238033;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_CHARGE, val);
+
+ /* Set core voltage (SW1) to 1.1V */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_0, &val);
+ val &= ~0x00001f;
+ val |= 0x000014;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_0, val);
+
+ if (imx_silicon_revision() < IMX_CHIP_REV_3_0) {
+ /* Setup VCC (SW2) to 1.25 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_1, &val);
+ val &= ~0x00001f;
+ val |= 0x00001a;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_1, val);
+
+ /* Setup 1V2_DIG1 (SW3) to 1.25 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_2, &val);
+ val &= ~0x00001f;
+ val |= 0x00001a;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_2, val);
+ } else {
+ /* Setup VCC (SW2) to 1.225 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_1, &val);
+ val &= ~0x00001f;
+ val |= 0x000019;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_1, val);
+
+ /* Setup 1V2_DIG1 (SW3) to 1.2 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_2, &val);
+ val &= ~0x00001f;
+ val |= 0x000018;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_2, val);
+ }
+
+ if (mc13xxx_dev->revision <= MC13892_REVISION_2_0) {
+ /* Set switchers in PWM mode for Atlas 2.0 and lower */
+ /* Setup the switcher mode for SW1 & SW2*/
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_4, &val);
+ val &= ~0x003c0f;
+ val |= 0x001405;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_4, val);
+
+ /* Setup the switcher mode for SW3 & SW4 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_5, &val);
+ val &= ~0x000f0f;
+ val |= 0x000505;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_5, val);
+ } else {
+ /* Set switchers in Auto in NORMAL mode & STANDBY mode for Atlas 2.0a */
+ /* Setup the switcher mode for SW1 & SW2*/
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_4, &val);
+ val &= ~0x003c0f;
+ val |= 0x002008;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_4, val);
+
+ /* Setup the switcher mode for SW3 & SW4 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SW_5, &val);
+ val &= ~0x000f0f;
+ val |= 0x000808;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SW_5, val);
+ }
+
+ /* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SETTING_1, &val);
+ val &= ~0x0001fc;
+ val |= 0x0001f4;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SETTING_1, val);
+
+ /* Configure VGEN3 and VCAM regulators to use external PNP */
+ val = 0x000208;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_MODE_1, val);
+ udelay(200);
+
+ /* Set VGEN3 to 1.8V */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_SETTING_0, &val);
+ val &= ~(1 << 14);
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_SETTING_0, val);
+
+ /* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */
+ val = 0x049249;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_MODE_1, val);
+
+ /* Enable USB1 charger */
+ val = 0x000409;
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_USB1, val);
+
+ /* Set VCOIN to 3.0V and Enable It */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_POWER_CTL0, &val);
+ val &= ~(7 << 20);
+ val |= (4 << 20) | (1 << 23);
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_CTL0, val);
+ /* Keeps VSRTC and CLK32KMCU */
+ val |= (1 << 4);
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_CTL0, val);
+
+ /* De-assert reset of external devices on GP01, GPO2, GPO3 and GPO4 */
+ mc13xxx_reg_read(mc13xxx_dev, MC13892_REG_POWER_MISC, &val);
+ /* GPO1 - External */
+ /* GP02 - LAN9221 */
+ /* GP03 - FEC */
+ /* GP04 - Wireless */
+ if (IS_ENABLED(CONFIG_DRIVER_NET_SMC911X) && ccxmx51_id->eth0)
+ val |= (1 << 8);
+ if (IS_ENABLED(CONFIG_DRIVER_NET_FEC_IMX) && ccxmx51_id->eth1)
+ val |= (1 << 10);
+ if (ccxmx51_id->wless)
+ val |= (1 << 12);
+ mc13xxx_reg_write(mc13xxx_dev, MC13892_REG_POWER_MISC, val);
+
+ udelay(100);
+
+ return 0;
+}
+
+static int ccxmx51_devices_init(void)
+{
+ u8 hwid[6];
+ int pwr;
+ char manloc;
+
+ if ((imx_iim_read(1, 9, hwid, sizeof(hwid)) != sizeof(hwid)) || (hwid[0] < 0x02) || (hwid[0] >= ARRAY_SIZE(ccxmx51_ids)))
+ memset(hwid, 0x00, sizeof(hwid));
+
+ ccxmx51_id = &ccxmx51_ids[hwid[0]];
+ printf("Module Variant: %s (0x%02x)\n", ccxmx51_id->id_string, hwid[0]);
+
+ if (hwid[0]) {
+ printf("Module HW Rev : %02x\n", hwid[1]);
+ switch (hwid[2] & 0xc0) {
+ case 0x00:
+ manloc = 'B';
+ break;
+ case 0x40:
+ manloc = 'W';
+ break;
+ case 0x80:
+ manloc = 'S';
+ break;
+ default:
+ manloc = 'N';
+ break;
+ }
+ printf("Module Serial : %c%d\n", manloc, ((hwid[2] & 0x3f) << 24) | (hwid[3] << 16) | (hwid[4] << 8) | hwid[5]);
+ if ((ccxmx51_id->mem_sz - SZ_128M) > 0)
+ arm_add_mem_device("ram1", MX51_CSD0_BASE_ADDR + SZ_128M, ccxmx51_id->mem_sz - SZ_128M);
+ }
+
+ imx51_add_uart1();
+ imx51_add_uart2();
+
+ spi_register_board_info(ccxmx51_spi_board_info, ARRAY_SIZE(ccxmx51_spi_board_info));
+ imx51_add_spi0(&ecspi_0_data);
+
+ pwr = ccxmx51_power_init();
+ console_flush();
+ imx51_init_lowlevel((ccxmx51_id->industrial || pwr) ? 600 : 800);
+ clock_notifier_call_chain();
+ if (pwr)
+ printf("Could not setup PMIC. Clocks not adjusted.\n");
+
+ imx51_add_i2c1(NULL);
+
+ imx51_add_nand(&nand_info);
+ devfs_add_partition("nand0", 0x00000, 0x80000, DEVFS_PARTITION_FIXED, "self_raw");
+ dev_add_bb_dev("self_raw", "self0");
+ devfs_add_partition("nand0", 0x80000, 0x40000, DEVFS_PARTITION_FIXED, "env_raw");
+ dev_add_bb_dev("env_raw", "env0");
+
+#ifdef CONFIG_DRIVER_NET_FEC_IMX
+ if (ccxmx51_id->eth0 && !pwr) {
+ imx51_add_fec(&fec_info);
+ eth_register_ethaddr(0, hwid);
+ }
+#endif
+
+#ifdef CONFIG_DRIVER_NET_SMC911X
+ if (ccxmx51_id->eth1 && !pwr) {
+ /* Configure the WEIM CS5 timming, bus width, etc */
+ /* 16 bit on DATA[31..16], not multiplexed, async */
+ writel(0x00420081, MX51_WEIM_BASE_ADDR + WEIM_CSxGCR1(5));
+ /* ADH has not effect on non muxed bus */
+ writel(0, MX51_WEIM_BASE_ADDR + WEIM_CSxGCR2(5));
+ /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */
+ writel(0x32260000, MX51_WEIM_BASE_ADDR + WEIM_CSxRCR1(5));
+ /* APR=0 */
+ writel(0, MX51_WEIM_BASE_ADDR + WEIM_CSxRCR2(5));
+ /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, WCSA=0 */
+ writel(0x72080f00, MX51_WEIM_BASE_ADDR + WEIM_CSxWCR1(5));
+
+ /* LAN9221 network controller */
+ add_generic_device("smc911x", 1, NULL, MX51_CS5_BASE_ADDR, SZ_4K, IORESOURCE_MEM, NULL);
+ }
+#endif
+
+ ccxmx51_otghost_init();
+
+ armlinux_set_bootparams((void *)(MX51_CSD0_BASE_ADDR + 0x100));
+
+ armlinux_set_architecture(ccxmx51_id->wless ? MACH_TYPE_CCWMX51 : MACH_TYPE_CCMX51);
+
+ return 0;
+}
+device_initcall(ccxmx51_devices_init);
+
+static int ccxmx51_console_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(ccxmx51_pads, ARRAY_SIZE(ccxmx51_pads));
+
+ imx51_add_uart0();
+
+ return 0;
+}
+console_initcall(ccxmx51_console_init);