[PATCH] arm: Introduce VPR200 board

Marc Reilly marc at cpdesign.com.au
Fri Dec 10 00:42:42 EST 2010


Starting point for the vpr200 board.
Very similar core hardware to mx35 3stack.

Signed-off-by: Marc Reilly <marc at cpdesign.com.au>
---
 arch/arm/Makefile                            |    1 +
 arch/arm/boards/vpr200/Makefile              |    4 +
 arch/arm/boards/vpr200/config.h              |   28 +
 arch/arm/boards/vpr200/env/bin/_update       |   39 ++
 arch/arm/boards/vpr200/env/bin/boot          |   67 ++
 arch/arm/boards/vpr200/env/bin/hush_hack     |    1 +
 arch/arm/boards/vpr200/env/bin/init          |   38 +
 arch/arm/boards/vpr200/env/bin/update_kernel |   15 +
 arch/arm/boards/vpr200/env/bin/update_rootfs |   20 +
 arch/arm/boards/vpr200/env/config            |   46 ++
 arch/arm/boards/vpr200/flash_header.c        |   46 ++
 arch/arm/boards/vpr200/lowlevel.c            |  255 +++++++
 arch/arm/boards/vpr200/vpr200.c              |  929 ++++++++++++++++++++++++++
 arch/arm/boards/vpr200/vpr200.dox            |   10 +
 arch/arm/configs/vpr200_defconfig            |   60 ++
 arch/arm/mach-imx/Kconfig                    |   13 +
 16 files changed, 1572 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boards/vpr200/Makefile
 create mode 100644 arch/arm/boards/vpr200/config.h
 create mode 100644 arch/arm/boards/vpr200/env/bin/_update
 create mode 100644 arch/arm/boards/vpr200/env/bin/boot
 create mode 100644 arch/arm/boards/vpr200/env/bin/hush_hack
 create mode 100644 arch/arm/boards/vpr200/env/bin/init
 create mode 100644 arch/arm/boards/vpr200/env/bin/update_kernel
 create mode 100644 arch/arm/boards/vpr200/env/bin/update_rootfs
 create mode 100644 arch/arm/boards/vpr200/env/config
 create mode 100644 arch/arm/boards/vpr200/flash_header.c
 create mode 100644 arch/arm/boards/vpr200/lowlevel.c
 create mode 100644 arch/arm/boards/vpr200/vpr200.c
 create mode 100644 arch/arm/boards/vpr200/vpr200.dox
 create mode 100644 arch/arm/configs/vpr200_defconfig

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 9729c23..6e6be98 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -91,6 +91,7 @@ board-$(CONFIG_MACH_CHUMBY)			:= chumby_falconwing
 board-$(CONFIG_MACH_FREESCALE_MX51_PDK)		:= freescale-mx51-pdk
 board-$(CONFIG_MACH_GUF_CUPID)			:= guf-cupid
 board-$(CONFIG_MACH_MINI2440)			:= mini2440
+board-$(CONFIG_MACH_VPR200)			:= vpr200
 
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
 
diff --git a/arch/arm/boards/vpr200/Makefile b/arch/arm/boards/vpr200/Makefile
new file mode 100644
index 0000000..08bef79
--- /dev/null
+++ b/arch/arm/boards/vpr200/Makefile
@@ -0,0 +1,4 @@
+
+obj-y					+= lowlevel.o
+obj-y					+= vpr200.o
+obj-$(CONFIG_ARCH_IMX_INTERNAL_BOOT)	+= flash_header.o
diff --git a/arch/arm/boards/vpr200/config.h b/arch/arm/boards/vpr200/config.h
new file mode 100644
index 0000000..2f03006
--- /dev/null
+++ b/arch/arm/boards/vpr200/config.h
@@ -0,0 +1,28 @@
+/*
+ * 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
+ * @brief Global defintions for the VPR-R CPU board.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_MX35_HCLK_FREQ        24000000
+
+#endif	/* __CONFIG_H */
diff --git a/arch/arm/boards/vpr200/env/bin/_update b/arch/arm/boards/vpr200/env/bin/_update
new file mode 100644
index 0000000..ddd6b84
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/bin/_update
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+if [ -z "$part" -o -z "$image" ]; then
+	echo "define \$part and \$image"
+	exit 1
+fi
+
+if [ ! -e "$part" ]; then
+	echo "Partition $part does not exist"
+	exit 1
+fi
+
+if [ $# = 1 ]; then
+	image=$1
+fi
+
+if [ x$ip = xdhcp ]; then
+	dhcp
+fi
+
+ping $eth0.serverip
+if [ $? -ne 0 ] ; then
+	echo "Server did not reply! Update aborted."
+	exit 1
+fi
+
+unprotect $part
+
+echo
+echo "erasing partition $part"
+echo
+erase $part
+
+echo
+echo "flashing $image to $part"
+echo
+tftp $image $part
+
+protect $part
diff --git a/arch/arm/boards/vpr200/env/bin/boot b/arch/arm/boards/vpr200/env/bin/boot
new file mode 100644
index 0000000..80135db
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/bin/boot
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+. /env/config
+
+if [ x$1 = xnand ]; then
+	rootfs_loc=nand
+	kernel_loc=nand
+elif [ x$1 = xnor ]; then
+	rootfs_loc=nand
+	kernel_loc=nor
+elif [ x$1 = xnet ]; then
+	rootfs_loc=net
+	kernel_loc=net
+elif [ x$1 = xmmc ]; then
+	rootfs_loc=mmc
+	kernel_loc=mmc
+fi
+
+
+if [ x$ip = xdhcp ]; then
+	bootargs="$bootargs ip=dhcp"
+elif [ x$ip != xno ]; then
+	bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask:::"
+fi
+
+
+if [ $rootfs_loc != net ]; then
+	if [ x$rootfs_loc = xnand ]; then
+		rootfs_mtdblock=$rootfs_mtdblock_nand
+	elif [ x$rootfs_loc = xnor ]; then
+		rootfs_mtdblock=$rootfs_mtdblock_nor
+	else
+		rootfs_mtdblock=$rootfs_mmc_part
+	fi
+
+
+	if [ $rootfs_type = ubifs ]; then
+		bootargs="$bootargs ubi.mtd=$rootfs_mtdblock root=ubi0:$rootfs"
+	elif [ $rootfs_loc = mmc ]; then
+		bootargs="$bootargs root=/dev/mmcblk0p$rootfs_mmc_part"
+	else
+		bootargs="$bootargs root=/dev/mtdblock$rootfs_mtdblock"
+	fi
+
+	bootargs="$bootargs rootfstype=$rootfs_type"
+
+else
+	bootargs="$bootargs root=/dev/nfs nfsroot=$eth0.serverip:$nfsroot,v3,tcp"
+fi
+
+
+bootargs="$bootargs mtdparts=physmap-flash.0:$nor_parts;mxc_nand:$nand_parts"
+
+if [ $kernel_loc = net ]; then
+	if [ x$ip = xdhcp ]; then
+		dhcp
+	fi
+	tftp $kernel uImage || exit 1
+	bootm uImage
+elif [ $kernel_loc = nor ]; then
+	bootm /dev/nor0.kernel
+elif [ $kernel_loc = mmc ]; then
+	bootm /dev/disk0.kernel
+else
+	bootm /dev/nand0.kernel.bb
+fi
+
diff --git a/arch/arm/boards/vpr200/env/bin/hush_hack b/arch/arm/boards/vpr200/env/bin/hush_hack
new file mode 100644
index 0000000..5fffa92
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/bin/hush_hack
@@ -0,0 +1 @@
+nand -a /dev/nand0.*
diff --git a/arch/arm/boards/vpr200/env/bin/init b/arch/arm/boards/vpr200/env/bin/init
new file mode 100644
index 0000000..5e6f837
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/bin/init
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+PATH=/env/bin
+export PATH
+
+. /env/config
+if [ -e /dev/nor0 ]; then
+	addpart /dev/nor0 $nor_parts
+fi
+
+if [ -e /dev/nand0 ]; then
+	addpart /dev/nand0 $nand_parts
+
+	# Uh, oh, hush first expands wildcards and then starts executing
+	# commands. What a bug!
+	source /env/bin/hush_hack 
+fi
+
+if [ -e /dev/disk0 ]; then
+	addpart /dev/disk0 $mmc_boot_parts
+fi
+
+if [ -z $eth0.ethaddr ]; then
+	echo "WARN: no MAC address set for eth0."
+fi
+
+echo
+echo -n "Hit any key to stop autoboot: "
+timeout -a $autoboot_timeout
+if [ $? != 0 ]; then
+	echo
+	echo "type update_kernel nand|nor [<imagename>] to update kernel into flash"
+	echo "type update_rootfs nand|nor [<imagename>] to update rootfs into flash"
+	echo
+	exit
+fi
+
+boot
diff --git a/arch/arm/boards/vpr200/env/bin/update_kernel b/arch/arm/boards/vpr200/env/bin/update_kernel
new file mode 100644
index 0000000..63ad11a
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/bin/update_kernel
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+. /env/config
+image=$kernel
+
+if [ x$1 = xnand ]; then
+	part=/dev/nand0.kernel.bb
+elif [ x$1 = xnor ]; then
+	part=/dev/nor0.kernel
+else
+	echo "usage: $0 nor|nand [imagename]"
+	exit 1
+fi
+
+. /env/bin/_update $2
diff --git a/arch/arm/boards/vpr200/env/bin/update_rootfs b/arch/arm/boards/vpr200/env/bin/update_rootfs
new file mode 100644
index 0000000..53dd2ca
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/bin/update_rootfs
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+. /env/config
+
+if [ $rootfs_type = ubifs ]; then
+	image=${rootfs}.ubi
+else
+	image=${rootfs}.$rootfs_type
+fi
+
+if [ x$1 = xnand ]; then
+	part=/dev/nand0.root.bb
+elif [ x$1 = xnor ]; then
+	part=/dev/nor0.root
+else
+	echo "usage: $0 nor|nand [imagename]"
+	exit 1
+fi
+
+. /env/bin/_update $2
diff --git a/arch/arm/boards/vpr200/env/config b/arch/arm/boards/vpr200/env/config
new file mode 100644
index 0000000..300de2d
--- /dev/null
+++ b/arch/arm/boards/vpr200/env/config
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# use 'dhcp' to do dhcp in barebox and in kernel
+# use 'no' if you don't want to pass the ip from barebox to the kernel
+ip=no
+
+# or set your networking parameters here
+#eth0.ipaddr=a.b.c.d
+#eth0.netmask=a.b.c.d
+#eth0.gateway=a.b.c.d
+#eth0.serverip=a.b.c.d
+
+# can be either 'net', 'nor' or 'nand''
+kernel_loc=nor
+rootfs_loc=nand
+
+# can be either 'jffs2', or 'ubifs' for flash, 'ext3' for mmc
+rootfs_type=ubifs
+
+if [ x$boot_loc = $xmmc ]; then
+	kernel_loc=mmc
+	rootfs_loc=mmc
+	rootfs_type=ext3
+fi
+
+kernel=uImage
+rootfs=vpr200v1-rootfs
+envimage=vpr200-env
+
+autoboot_timeout=1
+
+nfsroot="/srv/tftpboot"
+debugargs="jtag=on nohlt debug"
+bootargs="earlyprintk=ttymxc0,115200 console=ttymxc0,115200"
+
+nor_parts="256k(barebox)ro,512k(bareboxenv),4M(kernel),-(scratch)"
+rootfs_mtdblock_nor=3
+
+nand_parts="120M(rootfs),-(root)"
+rootfs_mtdblock_nand=4
+
+#note: these are fake partitions within the first real partition on 
+#on the card. They are purely for the bootloader.
+mmc_boot_parts="256k(barebox)ro,512k(bareboxenv),4M(kernel)"
+#the second real partition is our boot partition.
+rootfs_mmc_part=2
diff --git a/arch/arm/boards/vpr200/flash_header.c b/arch/arm/boards/vpr200/flash_header.c
new file mode 100644
index 0000000..ef29bc2
--- /dev/null
+++ b/arch/arm/boards/vpr200/flash_header.c
@@ -0,0 +1,46 @@
+#include <common.h>
+#include <mach/imx-flash-header.h>
+#include <mach/imx-regs.h>
+
+extern void exception_vectors(void);
+
+void __naked __flash_header_start go(void)
+{
+	__asm__ __volatile__("b exception_vectors\n");
+}
+
+struct imx_dcd_entry __dcd_entry_section dcd_entry[] = {
+	{ .ptr_type = 4, .addr = 0xB8001010, .val = 0x00000304, },
+	{ .ptr_type = 4, .addr = 0xB8001010, .val = 0x0000030C, },
+	{ .ptr_type = 4, .addr = 0xB8001004, .val = 0x007ffc3f, },
+	{ .ptr_type = 4, .addr = 0xB8001000, .val = 0x92220000, },
+	{ .ptr_type = 4, .addr = 0x80000400, .val = 0x12345678, },
+	{ .ptr_type = 4, .addr = 0xB8001000, .val = 0xA2220000, },
+	{ .ptr_type = 4, .addr = 0x80000000, .val = 0x87654321, },
+	{ .ptr_type = 4, .addr = 0x80000000, .val = 0x87654321, },
+	{ .ptr_type = 4, .addr = 0xB8001000, .val = 0xB2220000, },
+	{ .ptr_type = 1, .addr = 0x80000233, .val = 0xda, },
+	{ .ptr_type = 1, .addr = 0x82000780, .val = 0xda, },
+	{ .ptr_type = 1, .addr = 0x82000400, .val = 0xda, },
+	{ .ptr_type = 4, .addr = 0xB8001000, .val = 0x82226080, },
+	{ .ptr_type = 4, .addr = 0xB8001004, .val = 0x007ffc3f, },
+	{ .ptr_type = 4, .addr = 0xB800100C, .val = 0x007ffc3f, },
+	{ .ptr_type = 4, .addr = 0xB8001010, .val = 0x00000304, },
+	{ .ptr_type = 4, .addr = 0xB8001008, .val = 0x00002000, },
+};
+
+
+struct imx_flash_header __flash_header_section flash_header = {
+	.app_code_jump_vector	= DEST_BASE + ((unsigned int)&exception_vectors - TEXT_BASE),
+	.app_code_barker	= APP_CODE_BARKER,
+	.app_code_csf		= 0,
+	.dcd_ptr_ptr		= FLASH_HEADER_BASE + offsetof(struct imx_flash_header, dcd),
+	.super_root_key		= 0,
+	.dcd			= FLASH_HEADER_BASE + offsetof(struct imx_flash_header, dcd_barker),
+	.app_dest		= DEST_BASE,
+	.dcd_barker		= DCD_BARKER,
+	.dcd_block_len		= sizeof(dcd_entry),
+};
+
+unsigned long __image_len_section barebox_len = 0x40000;
+
diff --git a/arch/arm/boards/vpr200/lowlevel.c b/arch/arm/boards/vpr200/lowlevel.c
new file mode 100644
index 0000000..7e777aa
--- /dev/null
+++ b/arch/arm/boards/vpr200/lowlevel.c
@@ -0,0 +1,255 @@
+/*
+ *
+ * (c) 2007 Pengutronix, Sascha Hauer <s.hauer at pengutronix.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <init.h>
+#include <mach/imx-regs.h>
+#include <mach/imx-pll.h>
+#include <mach/esdctl.h>
+#include <asm/cache-l2x0.h>
+#include <asm/io.h>
+#include <mach/imx-nand.h>
+#include <asm/barebox-arm.h>
+#include <asm-generic/memory_layout.h>
+#include <asm/system.h>
+
+/* Assuming 24MHz input clock */
+#define MPCTL_PARAM_399     (IMX_PLL_PD(0) | IMX_PLL_MFD(15) | IMX_PLL_MFI(8) | IMX_PLL_MFN(5))
+#define MPCTL_PARAM_532     ((1 << 31) | IMX_PLL_PD(0) | IMX_PLL_MFD(11) | IMX_PLL_MFI(11) | IMX_PLL_MFN(1))
+#define PPCTL_PARAM_300     (IMX_PLL_PD(0) | IMX_PLL_MFD(3) | IMX_PLL_MFI(6) | IMX_PLL_MFN(1))
+
+
+#ifdef CONFIG_NAND_IMX_BOOT
+static void __bare_init __naked insdram(void)
+{
+	uint32_t r;
+
+	/* Speed up NAND controller by adjusting the NFC divider */
+	r = readl(IMX_CCM_BASE + CCM_PDR4);
+	r &= ~(0xf << 28);
+	r |= 0x1 << 28;
+	writel(r, IMX_CCM_BASE + CCM_PDR4);
+
+	/* setup a stack to be able to call imx_nand_load_image() */
+	r = STACK_BASE + STACK_SIZE - 12;
+	__asm__ __volatile__("mov sp, %0" : : "r"(r));
+
+	imx_nand_load_image((void *)TEXT_BASE, 256 * 1024);
+
+	board_init_lowlevel_return();
+}
+#endif
+
+void __bare_init __naked board_init_lowlevel(void)
+{
+	uint32_t r, s;
+	unsigned long ccm_base = IMX_CCM_BASE;
+#ifdef CONFIG_NAND_IMX_BOOT
+	unsigned int *trg, *src;
+	int i;
+#endif
+
+	r = get_cr();
+	r |= CR_Z; /* Flow prediction (Z) */
+	r |= CR_U; /* unaligned accesses  */
+	r |= CR_FI; /* Low Int Latency     */
+
+	__asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(s));
+	s |= 0x7;
+	__asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1" : : "r"(s));
+
+	set_cr(r);
+
+	r = 0;
+	__asm__ __volatile__("mcr p15, 0, %0, c15, c2, 4" : : "r"(r));
+
+	/*
+	 * Branch predicition is now enabled.  Flush the BTAC to ensure a valid
+	 * starting point.  Don't flush BTAC while it is disabled to avoid
+	 * ARM1136 erratum 408023.
+	 */
+	__asm__ __volatile__("mcr p15, 0, %0, c7, c5, 6" : : "r"(r));
+
+	/* invalidate I cache and D cache */
+	__asm__ __volatile__("mcr p15, 0, %0, c7, c7, 0" : : "r"(r));
+
+	/* invalidate TLBs */
+	__asm__ __volatile__("mcr p15, 0, %0, c8, c7, 0" : : "r"(r));
+
+	/* Drain the write buffer */
+	__asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4" : : "r"(r));
+
+	/* Also setup the Peripheral Port Remap register inside the core */
+	r = 0x40000015; /* start from AIPS 2GB region */
+	__asm__ __volatile__("mcr p15, 0, %0, c15, c2, 4" : : "r"(r));
+
+	/*
+	 * End of ARM1136 init
+	 */
+
+	writel(0x003F4208, ccm_base + CCM_CCMR);
+
+	/* Set MPLL , arm clock and ahb clock*/
+	writel(MPCTL_PARAM_532, ccm_base + CCM_MPCTL);
+
+	writel(PPCTL_PARAM_300, ccm_base + CCM_PPCTL);
+	writel(0x00001000, ccm_base + CCM_PDR0);
+
+	r = readl(ccm_base + CCM_CGR0);
+	r |= 0x00300000;
+	writel(r, ccm_base + CCM_CGR0);
+
+	r = readl(ccm_base + CCM_CGR1);
+	r |= 0x00000C00;
+	r |= 0x00000003;
+	writel(r, ccm_base + CCM_CGR1);
+
+	r = readl(IMX_L2CC_BASE + L2X0_AUX_CTRL);
+	r |= 0x1000;
+	writel(r, IMX_L2CC_BASE + L2X0_AUX_CTRL);
+
+	/* Skip SDRAM initialization if we run from RAM */
+	r = get_pc();
+	if (r > 0x80000000 && r < 0x90000000)
+		board_init_lowlevel_return();
+
+	/**
+	 * RAM init
+	 */
+	/* VPR200v1 has DDR2, DDR2_EN 0x200, DDR_EN 0x100, MDDR_EN 0x004 */
+	writel(0x00000304, ESDMISC); /*  */
+
+	/* set timing paramters (basically max delays for all)*/
+	writel(0x007ffc2f, ESDCFG0);
+	/* select Precharge-All mode */
+	writel(0x92220000, ESDCTL0);
+	/* Precharge-All */
+	writel(0x12345678, IMX_SDRAM_CS0 + 0x400);
+
+	/* select Load-Mode-Register mode */
+	writel(0xB8001000, ESDCTL0);
+	/* Load reg EMR2 */
+	writeb(0xda, 0x84000000);
+	/* Load reg EMR3 */
+	writeb(0xda, 0x86000000);
+	/* Load reg EMR1 -- enable DLL */
+	writeb(0xda, 0x82000400);
+	/* Load reg MR -- reset DLL */
+	writeb(0xda, 0x80000333);
+
+	/* select Precharge-All mode */
+	writel(0x92220000, ESDCTL0);
+	/* Precharge-All */
+	writel(0x12345678, IMX_SDRAM_CS0 + 0x400);
+
+	/* select Manual-Refresh mode */
+	writel(0xA2220000, ESDCTL0);
+	/* Manual-Refresh 2 times */
+	writel(0x87654321, IMX_SDRAM_CS0);
+	writel(0x87654321, IMX_SDRAM_CS0);
+
+	/* select Load-Mode-Register mode */
+	writel(0xB2220000, ESDCTL0);
+	/* Load reg MR -- CL3, BL8, end DLL reset */
+	writeb(0xda, 0x80000233);
+	/* Load reg EMR1 -- OCD default */
+	writeb(0xda, 0x82000780);
+	/* Load reg EMR1 -- OCD exit */
+	writeb(0xda, 0x82000400);
+
+	/* select normal-operation mode
+	 * DSIZ32-bit, BL8, COL10-bit, ROW13-bit
+	 * disable PWT & PRCT
+	 * disable Auto-Refresh */
+	writel(0x82220080, ESDCTL0);
+	/* enable Auto-Refresh */
+	writel(0x82228080, ESDCTL0);
+
+	/* BANK 2 */
+
+	/* set timing paramters (basically max delays for all)*/
+	writel(0x007ffc2f, ESDCFG1);
+	/* select Precharge-All mode */
+	writel(0x92220000, ESDCTL1);
+	/* Precharge-All */
+	writel(0x12345678, IMX_SDRAM_CS1 + 0x400);
+
+	/* select Load-Mode-Register mode */
+	writel(0xB8001000, ESDCTL1);
+	/* Load reg EMR2 */
+	writeb(0xda, 0x94000000);
+	/* Load reg EMR3 */
+	writeb(0xda, 0x96000000);
+	/* Load reg EMR1 -- enable DLL */
+	writeb(0xda, 0x92000400);
+	/* Load reg MR -- reset DLL */
+	writeb(0xda, 0x90000333);
+
+	/* select Precharge-All mode */
+	writel(0x92220000, ESDCTL1);
+	/* Precharge-All */
+	writel(0x12345678, IMX_SDRAM_CS1 + 0x400);
+
+	/* select Manual-Refresh mode */
+	writel(0xA2220000, ESDCTL1);
+	/* Manual-Refresh 2 times */
+	writel(0x87654321, IMX_SDRAM_CS1);
+	writel(0x87654321, IMX_SDRAM_CS1);
+
+	/* select Load-Mode-Register mode */
+	writel(0xB2220000, ESDCTL1);
+	/* Load reg MR -- CL3, BL8, end DLL reset */
+	writeb(0xda, 0x90000233);
+	/* Load reg EMR1 -- OCD default */
+	writeb(0xda, 0x92000780);
+	/* Load reg EMR1 -- OCD exit */
+	writeb(0xda, 0x92000400);
+
+	/* select normal-operation mode
+	 * DSIZ32-bit, BL8, COL10-bit, ROW13-bit
+	 * disable PWT & PRCT
+	 * disable Auto-Refresh */
+	writel(0x82220080, ESDCTL1);
+	/* enable Auto-Refresh */
+	writel(0x82228080, ESDCTL1);
+
+#ifdef CONFIG_NAND_IMX_BOOT
+	/* skip NAND boot if not running from NFC space */
+	r = get_pc();
+	if (r < IMX_NFC_BASE || r > IMX_NFC_BASE + 0x800)
+		board_init_lowlevel_return();
+
+	src = (unsigned int *)IMX_NFC_BASE;
+	trg = (unsigned int *)TEXT_BASE;
+
+	/* Move ourselves out of NFC SRAM */
+	for (i = 0; i < 0x800 / sizeof(int); i++)
+		*trg++ = *src++;
+
+	/* Jump to SDRAM */
+	r = (unsigned int)&insdram;
+	__asm__ __volatile__("mov pc, %0" : : "r"(r));
+#else
+	board_init_lowlevel_return();
+#endif
+}
+
diff --git a/arch/arm/boards/vpr200/vpr200.c b/arch/arm/boards/vpr200/vpr200.c
new file mode 100644
index 0000000..298195d
--- /dev/null
+++ b/arch/arm/boards/vpr200/vpr200.c
@@ -0,0 +1,929 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ *               2009 Marc Kleine-Budde, Pengutronix
+ *               2010 Marc Reilly, Creative Product Design
+ *
+ * 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
+ *
+ * Derived from:
+ *
+ * * mx35_3stack.c - board file for uboot-v1
+ *   Copyright (C) 2007, Guennadi Liakhovetski <lg at denx.de>
+ *   (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
+ *
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fec.h>
+#include <fs.h>
+#include <init.h>
+#include <nand.h>
+#include <net.h>
+#include <partition.h>
+#include <command.h>
+#include <getopt.h>
+
+#include <asm/armlinux.h>
+#include <asm/io.h>
+#include <generated/mach-types.h>
+
+#include <mach/gpio.h>
+#include <mach/imx-nand.h>
+#include <mach/imx-regs.h>
+#include <mach/iomux-mx35.h>
+#include <mach/iomux-v3.h>
+#include <mach/pmic.h>
+#include <mach/imx-ipu-fb.h>
+#include <mach/generic.h>
+#include <mach/devices-imx35.h>
+
+#include <i2c/i2c.h>
+#include <mfd/mc13892.h>
+
+/* ------------------------------------------------------------------------- */
+/* Board revs for the VPR CPU */
+#define VPR_CPU_V1  0x19
+
+/*
+ * IO Defines for the VPR
+ *
+ * The current GPIO API considers the gpios as a contiguous bits across
+ * ports. These defines and macros convert the GPIO1_3 nomenclature to
+ * a numbered GPIO line.
+ */
+
+/* Port numbers start from 1 to be consistent with iMX docs */
+#define GPIO_FROM_PORT(x, y) (((x-1)*32) + y)
+
+#define LCD_PWR_PORT		1
+#define LCD_PWR_BIT		2
+#define LCD_PWR_GPIO		GPIO_FROM_PORT(LCD_PWR_PORT, LCD_PWR_BIT)
+
+#define FEC_ENABLE_PORT		1
+#define FEC_ENABLE_BIT		3
+#define FEC_ENABLE_GPIO		GPIO_FROM_PORT(FEC_ENABLE_PORT, FEC_ENABLE_BIT)
+
+#define FEC_RESET_PORT		3
+#define FEC_RESET_BIT		0
+#define FEC_RESET_GPIO		GPIO_FROM_PORT(FEC_RESET_PORT, FEC_RESET_BIT)
+
+#define DIAG_PORT		3
+#define DIAG_RED_BIT		14
+#define DIAG_GREEN_BIT		15
+#define DIAG_BLUE_BIT		30
+#define DIAG_RED_GPIO		GPIO_FROM_PORT(DIAG_PORT, DIAG_RED_BIT)
+#define DIAG_GREEN_GPIO		GPIO_FROM_PORT(DIAG_PORT, DIAG_GREEN_BIT)
+#define DIAG_BLUE_GPIO		GPIO_FROM_PORT(DIAG_PORT, DIAG_BLUE_BIT)
+
+#define SYS_CFG_PORT		2
+#define SYS_CFG_1_BIT		27
+#define SYS_CFG_2_BIT		28
+#define SYS_CFG_3_BIT		29
+#define SYS_CFG_4_BIT		30
+#define SYS_CFG_5_BIT		31
+#define SYS_CFG_1_GPIO		GPIO_FROM_PORT(SYS_CFG_PORT, SYS_CFG_1_BIT)
+#define SYS_CFG_2_GPIO		GPIO_FROM_PORT(SYS_CFG_PORT, SYS_CFG_2_BIT)
+#define SYS_CFG_3_GPIO		GPIO_FROM_PORT(SYS_CFG_PORT, SYS_CFG_3_BIT)
+#define SYS_CFG_4_GPIO		GPIO_FROM_PORT(SYS_CFG_PORT, SYS_CFG_4_BIT)
+#define SYS_CFG_5_GPIO		GPIO_FROM_PORT(SYS_CFG_PORT, SYS_CFG_5_BIT)
+
+#define BUTTON_PORT		1
+#define BUTTON1_BIT		4
+#define BUTTON2_BIT		5
+#define BUTTON3_BIT		7
+#define BUTTON4_BIT		8
+#define BUTTON5_BIT		9
+#define BUTTON6_BIT		10
+#define BUTTON7_BIT		11
+#define BUTTON8_BIT		12
+#define BUTTON1_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON1_BIT)
+#define BUTTON2_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON2_BIT)
+#define BUTTON3_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON3_BIT)
+#define BUTTON4_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON4_BIT)
+#define BUTTON5_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON5_BIT)
+#define BUTTON6_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON6_BIT)
+#define BUTTON7_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON7_BIT)
+#define BUTTON8_GPIO		GPIO_FROM_PORT(BUTTON_PORT, BUTTON8_BIT)
+
+#define BUZZER_PORT		1
+#define BUZZER_BIT		13
+#define BUZZER_GPIO		GPIO_FROM_PORT(BUZZER_PORT, BUZZER_BIT)
+
+#define BP_PORT			2
+#define BP_RESET_BIT		18
+#define BP_EOC_BIT		17
+#define BP_RESET_GPIO		GPIO_FROM_PORT(BP_PORT, BP_RESET_BIT)
+#define BP_EOC_GPIO		GPIO_FROM_PORT(BP_PORT, BP_EOC_BIT)
+
+#define RF_PORT			2
+#define RF_RESET_BIT		12
+#define RF_TDI_BIT		13
+#define RF_TDO_BIT		14
+#define RF_TCK_BIT		15
+#define RF_TMS_BIT		16
+#define RF_RESET_GPIO		GPIO_FROM_PORT(RF_PORT, RF_RESET_BIT)
+#define RF_TDI_GPIO		GPIO_FROM_PORT(RF_PORT, RF_TDI_BIT)
+#define RF_TDO_GPIO		GPIO_FROM_PORT(RF_PORT, RF_TDO_BIT)
+#define RF_TCK_GPIO		GPIO_FROM_PORT(RF_PORT, RF_TCK_BIT)
+#define RF_TMS_GPIO		GPIO_FROM_PORT(RF_PORT, RF_TMS_BIT)
+
+/* ------------------------------------------------------------------------- */
+static struct device_d cfi_dev = {
+	.id		= -1,
+	.name		= "cfi_flash",
+	.map_base	= IMX_CS0_BASE,
+	.size		= 64 * 1024 * 1024,
+};
+
+static struct fec_platform_data fec_info = {
+	.xcv_type	= MII100,
+	.phy_addr	= 0x0,
+};
+
+static struct memory_platform_data sdram_pdata = {
+	.name		= "ram0",
+	.flags		= DEVFS_RDWR,
+};
+
+static struct device_d sdram_dev = {
+	.id		= -1,
+	.name		= "mem",
+	.map_base	= IMX_SDRAM_CS0,
+	.size		= 128 * 1024 * 1024,
+	.platform_data	= &sdram_pdata,
+};
+
+static struct memory_platform_data sdram_pdata1 = {
+	.name		= "ram1",
+	.flags		= DEVFS_RDWR,
+};
+
+static struct device_d sdram_dev1 = {
+	.id		= -1,
+	.name		= "mem",
+	.map_base	= IMX_SDRAM_CS1,
+	.size		= 128 * 1024 * 1024,
+	.platform_data	= &sdram_pdata1,
+};
+
+struct imx_nand_platform_data nand_info = {
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+static struct i2c_board_info i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("mc13892-i2c", 0x08),
+	}, {
+		I2C_BOARD_INFO("at24", 0x50),
+	},
+};
+
+static void vpr_display_enable(int enable)
+{
+	gpio_direction_output(LCD_PWR_GPIO, enable ? 0 : 1);
+}
+
+/*
+ * Same as imx35 pdk
+ */
+static struct fb_videomode CTP_CLAA070LC0ACW = {
+	/* 800x480 @ 60 Hz */
+	.name		= "CTP-CLAA070LC0ACW",
+	.refresh	= 60,
+	.xres		= 800,
+	.yres		= 480,
+	.pixclock	= KHZ2PICOS(27000),
+	.left_margin	= 50,
+	.right_margin	= 50,	/* whole line should have 900 clocks */
+	.upper_margin	= 10,
+	.lower_margin	= 10,	/* whole frame should have 500 lines */
+	.hsync_len	= 1,	/* note: DE only display */
+	.vsync_len	= 1,	/* note: DE only display */
+	.sync		= FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
+	.vmode		= FB_VMODE_NONINTERLACED,
+	.flag		= 0,
+};
+
+static struct imx_ipu_fb_platform_data ipu_fb_data = {
+	.mode		= &CTP_CLAA070LC0ACW,
+	.bpp		= 16,
+	.enable		= vpr_display_enable,
+};
+
+/* ------------------------------------------------------------------------- */
+/**
+ * Board has 5 lines that are tied high or low to give a system configuration
+ * ID. (ie board revision).
+ */
+static uint32_t vpr_read_sys_cfg(void)
+{
+	uint32_t ret = 0;
+
+	ret |= gpio_get_value(SYS_CFG_1_GPIO);
+	ret |= gpio_get_value(SYS_CFG_2_GPIO) << 1;
+	ret |= gpio_get_value(SYS_CFG_3_GPIO) << 2;
+	ret |= gpio_get_value(SYS_CFG_4_GPIO) << 3;
+	ret |= gpio_get_value(SYS_CFG_5_GPIO) << 4;
+
+	return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ * Init gpio lines for tri-color LED used for diagnostics.
+ *
+ * Note does not set the IOMUX directions, so this needs to be
+ * done elsewhere.
+ */
+void vpr_diag_init(void)
+{
+	/* active low outputs, all start off */
+	gpio_direction_output(DIAG_RED_GPIO, 1);
+	gpio_direction_output(DIAG_GREEN_GPIO, 1);
+	gpio_direction_output(DIAG_BLUE_GPIO, 1);
+}
+
+/**
+ *  Sets each color component of the tri color led
+ *
+ *  \param red      Zero for Off. All other values On.
+ *  \param green    Zero for Off. All other values On.
+ *  \param blue     Zero for Off. All other values On.
+ */
+void vpr_diag_set(int red, int green, int blue)
+{
+	/* active low outputs */
+	gpio_set_value(DIAG_RED_GPIO, !red);
+	gpio_set_value(DIAG_GREEN_GPIO, !green);
+	gpio_set_value(DIAG_BLUE_GPIO, !blue);
+}
+
+/**
+ * Enum matching all color component triplets to
+ * named identifiers.
+ */
+enum diag_led_color {
+	DIAG_LED_OFF        = 0x0,
+	DIAG_LED_BLUE       = 0x1,
+	DIAG_LED_GREEN      = 0x2,
+	DIAG_LED_AQUA       = 0x3,
+	DIAG_LED_RED        = 0x4,
+	DIAG_LED_MAGENTA    = 0x5,
+	DIAG_LED_YELLOW     = 0x6,
+	DIAG_LED_WHITE      = 0x7,
+};
+
+/**
+ * Set Diagnostic LED to specified color
+ */
+void vpr_diag_set_color(enum diag_led_color color)
+{
+	vpr_diag_set(color & 0x4, color & 0x02, color & 0x01);
+}
+
+/* ------------------------------------------------------------------------- */
+enum vpr_button {
+	BUTTONNONE = 0,
+	BUTTON1 = 0x01,
+	BUTTON2 = 0x02,
+	BUTTON3 = 0x04,
+	BUTTON4 = 0x08,
+	BUTTON5 = 0x10,
+	BUTTON6 = 0x20,
+	BUTTON7 = 0x40,
+	BUTTON8 = 0x80
+};
+
+static void vpr_button_init(void)
+{
+	gpio_direction_input(BUTTON1_GPIO);
+	gpio_direction_input(BUTTON2_GPIO);
+	gpio_direction_input(BUTTON3_GPIO);
+	gpio_direction_input(BUTTON4_GPIO);
+	gpio_direction_input(BUTTON5_GPIO);
+	gpio_direction_input(BUTTON6_GPIO);
+	gpio_direction_input(BUTTON7_GPIO);
+	gpio_direction_input(BUTTON8_GPIO);
+}
+
+static int vpr_button_state(void)
+{
+	uint32_t ret = 0;
+
+	ret |= (!gpio_get_value(BUTTON1_GPIO));
+	ret |= (!gpio_get_value(BUTTON2_GPIO)) << 1;
+	ret |= (!gpio_get_value(BUTTON3_GPIO)) << 2;
+	ret |= (!gpio_get_value(BUTTON4_GPIO)) << 3;
+	ret |= (!gpio_get_value(BUTTON5_GPIO)) << 4;
+	ret |= (!gpio_get_value(BUTTON6_GPIO)) << 5;
+	ret |= (!gpio_get_value(BUTTON7_GPIO)) << 6;
+	ret |= (!gpio_get_value(BUTTON8_GPIO)) << 7;
+
+	return ret;
+}
+
+static int vpr_button_state_to_number(int bstate)
+{
+	int ret = 1;
+	if (!bstate)
+		return 0;
+
+	while (!(bstate & 0x01)) {
+		bstate >>= 1;
+		++ret;
+	}
+	return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+static void vpr_buzzer_init(void)
+{
+	gpio_direction_output(BUZZER_GPIO, 0);
+}
+
+static void vpr_buzzer_off(void)
+{
+	gpio_set_value(BUZZER_GPIO, 0);
+}
+
+static void vpr_buzzer_on(void)
+{
+	gpio_set_value(BUZZER_GPIO, 1);
+}
+
+/* ------------------------------------------------------------------------- */
+static void vpr_bp_init(void)
+{
+	struct pad_desc bp_pads[] = {
+		MX35_PAD_ATA_DATA4__GPIO2_17,
+		MX35_PAD_ATA_DATA5__GPIO2_18,
+	};
+
+	mxc_iomux_v3_setup_multiple_pads(bp_pads, ARRAY_SIZE(bp_pads));
+
+	gpio_direction_output(BP_RESET_GPIO, 1);
+	gpio_direction_input(BP_EOC_GPIO);
+}
+
+static void vpr_rf_init(void)
+{
+	struct pad_desc rf_pads[] = {
+		MX35_PAD_ATA_IORDY__GPIO2_12,
+		MX35_PAD_ATA_DATA0__GPIO2_13,
+		MX35_PAD_ATA_DATA1__GPIO2_14,
+		MX35_PAD_ATA_DATA2__GPIO2_15,
+		MX35_PAD_ATA_DATA3__GPIO2_16,
+	};
+
+	mxc_iomux_v3_setup_multiple_pads(rf_pads, ARRAY_SIZE(rf_pads));
+
+	gpio_direction_output(RF_RESET_GPIO, 0);
+	gpio_direction_output(RF_TDI_GPIO, 1);
+	gpio_direction_output(RF_TCK_GPIO, 1);
+	gpio_direction_output(RF_TMS_GPIO, 1);
+	gpio_direction_input(RF_TDO_GPIO);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Board initialization order:
+ *  core_initcall
+ *  postcore_initcall
+ *  console_initcall
+ *  postconsole_initcall
+ *  coredevice_initcall
+ *  fs_initcall
+ *  device_initcall
+ *  late_initcall
+ */
+
+static int vpr_devices_init(void)
+{
+#define MAX_BOOTSRC_MSG 80
+	uint32_t reg;
+	char bootsrc_msg[MAX_BOOTSRC_MSG+1] = {0,};
+
+	/* take care of WDT */
+	writew(0xFFB3, IMX_WDT_BASE + 0);
+	writew(0x0000, IMX_WDT_BASE + 8);
+
+	/* CS0: Nor Flash */
+	writel(0x0000cf03, CSCR_U(0));
+	writel(0x10000d03, CSCR_L(0));
+	writel(0x00720900, CSCR_A(0));
+
+	reg = readl(IMX_CCM_BASE + CCM_RCSR);
+	/* some fuses provide us vital information about connected hardware */
+	if (reg & 0x20000000)
+		nand_info.width = 2;	/* 16 bit */
+	else
+		nand_info.width = 1;	/* 8 bit */
+
+	/* This platform supports NOR, NAND and SD */
+	imx35_add_nand(&nand_info);
+	register_device(&cfi_dev);
+	imx35_add_mmc0(NULL);
+
+	switch ((reg >> 25) & 0x3) {
+	case 0x03:		/* SD/MMC is the source */
+		vpr_diag_set_color(DIAG_LED_MAGENTA);
+		snprintf(bootsrc_msg, MAX_BOOTSRC_MSG, "SD boot: ");
+		devfs_add_partition("disk0", 0x00000, 0x40000, PARTITION_FIXED, "self0");
+		devfs_add_partition("disk0", 0x40000, 0x80000, PARTITION_FIXED, "env0");
+		protect_file("/dev/self0", 1);
+		protect_file("/dev/env0", 1);
+		break;
+
+	case 0x01:		/* NAND is the source */
+		devfs_add_partition("nand0", 0x00000, 0x40000, PARTITION_FIXED, "self_raw");
+		dev_add_bb_dev("self_raw", "self0");
+		devfs_add_partition("nand0", 0x40000, 0x80000, PARTITION_FIXED, "env_raw");
+		dev_add_bb_dev("env_raw", "env0");
+		break;
+
+	case 0x00:		/* NOR is the source */
+		vpr_diag_set_color(DIAG_LED_AQUA);
+		snprintf(bootsrc_msg, MAX_BOOTSRC_MSG, "NOR boot: ");
+		devfs_add_partition("nor0", 0x00000, 0x40000, PARTITION_FIXED, "self0");
+		devfs_add_partition("nor0", 0x40000, 0x80000, PARTITION_FIXED, "env0");
+		protect_file("/dev/self0", 1);
+		protect_file("/dev/env0", 1);
+		break;
+	default:
+		printf("WARN: Unrecognized boot source.\n");
+		break;
+	}
+
+	/* delay printing message so protect file doesn't get in the middle */
+	printf(bootsrc_msg);
+
+	switch ((reg >> 10) & 0x3) {
+	case 0x03:
+		printf("Bootstrap mode\n");
+		break;
+	case 0x02:
+		printf("External\n");
+		break;
+	case 0x00:
+		printf("Internal\n");
+		break;
+	default:
+		break;
+	}
+
+	i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+
+	imx35_add_i2c0(NULL);
+	imx35_add_i2c1(NULL);
+	imx35_add_fec(&fec_info);
+
+	register_device(&sdram_dev);
+	register_device(&sdram_dev1);
+
+	imx35_add_fb(&ipu_fb_data);
+
+	vpr_button_init();
+	vpr_buzzer_init();
+	vpr_bp_init();
+	vpr_rf_init();
+
+	armlinux_add_dram(&sdram_dev);
+	/* TODO adding BANK1 causes early kernel crash when booting
+	 * off SD card */
+
+	armlinux_set_bootparams((void *)0x80000100);
+
+	armlinux_set_architecture(MACH_TYPE_VPR200);
+
+	/* For compat with the freescale kernel, relies on setting revision*/
+	armlinux_set_revision(0x00035100 | imx_silicon_revision());
+
+	return 0;
+}
+
+device_initcall(vpr_devices_init);
+
+static struct pad_desc vpr_pads[] = {
+	/* FEC */
+	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX35_PAD_FEC_COL__FEC_COL,
+	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX35_PAD_FEC_MDC__FEC_MDC,
+	MX35_PAD_FEC_MDIO__FEC_MDIO,
+	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
+	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
+	MX35_PAD_FEC_CRS__FEC_CRS,
+	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
+	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
+	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
+	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
+	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
+	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
+	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
+	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
+	/* FEC enable */
+	MX35_PAD_D3_REV__GPIO1_3,
+	/* UART 1*/
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RTS1__UART1_RTS,
+	MX35_PAD_CTS1__UART1_CTS,
+	/* I2C1 */
+	MX35_PAD_I2C1_CLK__I2C1_SCL,
+	MX35_PAD_I2C1_DAT__I2C1_SDA,
+	/* I2C2 */
+	MX35_PAD_I2C2_CLK__I2C2_SCL,
+	MX35_PAD_I2C2_DAT__I2C2_SDA,
+	/* Sys config */
+	MX35_PAD_ATA_DATA14__GPIO2_27,
+	MX35_PAD_ATA_DATA15__GPIO2_28,
+	MX35_PAD_ATA_INTRQ__GPIO2_29,
+	MX35_PAD_ATA_BUFF_EN__GPIO2_30,
+	MX35_PAD_ATA_DMARQ__GPIO2_31,
+	/* LCD enable */
+	MX35_PAD_D3_VSYNC__GPIO1_2,
+	/* Display */
+	MX35_PAD_LD0__IPU_DISPB_DAT_0,
+	MX35_PAD_LD1__IPU_DISPB_DAT_1,
+	MX35_PAD_LD2__IPU_DISPB_DAT_2,
+	MX35_PAD_LD3__IPU_DISPB_DAT_3,
+	MX35_PAD_LD4__IPU_DISPB_DAT_4,
+	MX35_PAD_LD5__IPU_DISPB_DAT_5,
+	MX35_PAD_LD6__IPU_DISPB_DAT_6,
+	MX35_PAD_LD7__IPU_DISPB_DAT_7,
+	MX35_PAD_LD8__IPU_DISPB_DAT_8,
+	MX35_PAD_LD9__IPU_DISPB_DAT_9,
+	MX35_PAD_LD10__IPU_DISPB_DAT_10,
+	MX35_PAD_LD11__IPU_DISPB_DAT_11,
+	MX35_PAD_LD12__IPU_DISPB_DAT_12,
+	MX35_PAD_LD13__IPU_DISPB_DAT_13,
+	MX35_PAD_LD14__IPU_DISPB_DAT_14,
+	MX35_PAD_LD15__IPU_DISPB_DAT_15,
+	MX35_PAD_LD16__IPU_DISPB_DAT_16,
+	MX35_PAD_LD17__IPU_DISPB_DAT_17,
+	MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK,
+	MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
+	MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
+	/* Buttons */
+	MX35_PAD_SCKR__GPIO1_4,
+	MX35_PAD_COMPARE__GPIO1_5,
+	MX35_PAD_SCKT__GPIO1_7,
+	MX35_PAD_FST__GPIO1_8,
+	MX35_PAD_HCKT__GPIO1_9,
+	MX35_PAD_TX5_RX0__GPIO1_10,
+	MX35_PAD_TX4_RX1__GPIO1_11,
+	MX35_PAD_TX3_RX2__GPIO1_12,
+	/* Buzzer */
+	MX35_PAD_TX2_RX3__GPIO1_13,
+	/* Diag LED */
+	MX35_PAD_USBOTG_PWR__GPIO3_14,
+	MX35_PAD_USBOTG_OC__GPIO3_15,
+	MX35_PAD_D3_HSYNC__GPIO3_30,
+};
+
+
+static int vpr_console_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(vpr_pads, ARRAY_SIZE(vpr_pads));
+
+	imx35_add_uart0();
+	return 0;
+}
+
+console_initcall(vpr_console_init);
+
+static int vpr_post_console_init(void)
+{
+	vpr_diag_init();
+	vpr_diag_set_color(DIAG_LED_YELLOW);
+	return 0;
+}
+
+postcore_initcall(vpr_post_console_init);
+
+static int vpr_core_init(void)
+{
+	u32 reg;
+
+	/* enable clock for SDHC1, I2C[1] and FEC */
+	reg = readl(IMX_CCM_BASE + CCM_CGR1);
+	reg |= 0x3 << CCM_CGR1_FEC_SHIFT;
+	reg |= 0x3 << CCM_CGR1_I2C1_SHIFT;
+	reg |= 0x3 << CCM_CGR1_SDHC1_SHIFT;
+	reg = writel(reg, IMX_CCM_BASE + CCM_CGR1);
+
+	/* AIPS setup - Only setup MPROTx regs. The PACR defaults are good.*/
+	/*
+	 * Set all MPROTx to be non-bufferable, trusted for R/W,
+	 * not forced to user-mode.
+	 */
+	writel(0x77777777, IMX_AIPS1_BASE);
+	writel(0x77777777, IMX_AIPS1_BASE + 0x4);
+	writel(0x77777777, IMX_AIPS2_BASE);
+	writel(0x77777777, IMX_AIPS2_BASE + 0x4);
+
+	/*
+	 * Clear the on and off peripheral modules Supervisor Protect bit
+	 * for SDMA to access them. Did not change the AIPS control registers
+	 * (offset 0x20) access type
+	 */
+	writel(0x0, IMX_AIPS1_BASE + 0x40);
+	writel(0x0, IMX_AIPS1_BASE + 0x44);
+	writel(0x0, IMX_AIPS1_BASE + 0x48);
+	writel(0x0, IMX_AIPS1_BASE + 0x4C);
+	reg = readl(IMX_AIPS1_BASE + 0x50);
+	reg &= 0x00FFFFFF;
+	writel(reg, IMX_AIPS1_BASE + 0x50);
+
+	writel(0x0, IMX_AIPS2_BASE + 0x40);
+	writel(0x0, IMX_AIPS2_BASE + 0x44);
+	writel(0x0, IMX_AIPS2_BASE + 0x48);
+	writel(0x0, IMX_AIPS2_BASE + 0x4C);
+	reg = readl(IMX_AIPS2_BASE + 0x50);
+	reg &= 0x00FFFFFF;
+	writel(reg, IMX_AIPS2_BASE + 0x50);
+
+	/* MAX (Multi-Layer AHB Crossbar Switch) setup */
+
+	/* MPR - priority is M4 > M2 > M3 > M5 > M0 > M1 */
+#define MAX_PARAM1 0x00302154
+	writel(MAX_PARAM1, IMX_MAX_BASE + 0x000); /* for S0 */
+	writel(MAX_PARAM1, IMX_MAX_BASE + 0x100); /* for S1 */
+	writel(MAX_PARAM1, IMX_MAX_BASE + 0x200); /* for S2 */
+	writel(MAX_PARAM1, IMX_MAX_BASE + 0x300); /* for S3 */
+	writel(MAX_PARAM1, IMX_MAX_BASE + 0x400); /* for S4 */
+
+	/* SGPCR - always park on last master */
+	writel(0x10, IMX_MAX_BASE + 0x10);	/* for S0 */
+	writel(0x10, IMX_MAX_BASE + 0x110);	/* for S1 */
+	writel(0x10, IMX_MAX_BASE + 0x210);	/* for S2 */
+	writel(0x10, IMX_MAX_BASE + 0x310);	/* for S3 */
+	writel(0x10, IMX_MAX_BASE + 0x410);	/* for S4 */
+
+	/* MGPCR - restore default values */
+	writel(0x0, IMX_MAX_BASE + 0x800);	/* for M0 */
+	writel(0x0, IMX_MAX_BASE + 0x900);	/* for M1 */
+	writel(0x0, IMX_MAX_BASE + 0xa00);	/* for M2 */
+	writel(0x0, IMX_MAX_BASE + 0xb00);	/* for M3 */
+	writel(0x0, IMX_MAX_BASE + 0xc00);	/* for M4 */
+	writel(0x0, IMX_MAX_BASE + 0xd00);	/* for M5 */
+
+	return 0;
+}
+
+core_initcall(vpr_core_init);
+
+/* -------------------------------------------------------------------------*/
+
+static int vpr_pmic_init_v1(struct mc13892 *mc13892)
+{
+	int err = 0;
+	unsigned int mask = 0;
+	unsigned int val = 0;
+
+	/* VGEN2[2:0] = b111 --> output to 3.15V */
+	mc13892_set_bits(mc13892, MC13892_REG_SETTING_0, 0x7 << 6, 0x7 << 6);
+
+	/* VCHRG[2:0] = 0b011, Charge reg output voltage 4.200 */
+	val |= 0x3;
+	mask |= 0x7;
+	/* ICHRG[3:0] = 0b1011, Current limit 960mA*/
+	val |= 0xb << 3;
+	mask |= 0xf << 3;
+	/* PLIM[1:0] = 0b11, Power limit 1000mW */
+	val |= 3 << 15;
+	mask |= 0x3 << 15;
+	/* Enable setting of V I */
+	val |= 1 << 23;
+	mask |= 0x1 << 23;
+	err |= mc13892_set_bits(mc13892, MC13892_REG_CHARGE, mask, val);
+
+	gpio_direction_output(FEC_RESET_GPIO, 0);
+
+	/*turn on the FEC power supply */
+	/* VGEN1[1:0] = 0b11*/
+	err |= mc13892_set_bits(mc13892, MC13892_REG_SETTING_0, 0x03, 0x03);
+	/* VGEN1EN = 1 */
+	err |= mc13892_set_bits(mc13892, MC13892_REG_MODE_0, 0x01, 0x01);
+	if (err) {
+		dev_err(&mc13892->client->dev,
+			"Init sequence failed, the system might not be working!\n");
+	}
+
+	gpio_direction_output(FEC_ENABLE_GPIO, 1);
+	mdelay(10);
+	gpio_set_value(FEC_RESET_GPIO, 1);
+
+	return err;
+}
+
+/*
+ * Maybe this is a bit dodgy because the env is only set up in
+ * a late_initcall?
+ */
+static void vpr_save_boot_loc(void)
+{
+	uint32_t reg;
+	reg = readl(IMX_CCM_BASE + CCM_RCSR);
+
+	switch ((reg >> 25) & 0x3) {
+	case 0x03:		/* SD/MMC is the source */
+		setenv("boot_loc", "mmc");
+		export("boot_loc");
+		break;
+	case 0x01:		/* NAND is the source */
+		setenv("boot_loc", "nane");
+		export("boot_loc");
+		break;
+
+	case 0x00:		/* NOR is the source */
+		setenv("boot_loc", "nor");
+		export("boot_loc");
+		break;
+	default:
+		break;
+	}
+}
+
+static int vpr_final_init(void)
+{
+	struct mc13892 *mc13892;
+	uint32_t system_rev;
+
+	mc13892 = mc13892_get();
+	if (!mc13892) {
+		printf("FAILED to get mc13892 handle!\n");
+		return 0;
+	}
+
+	system_rev = vpr_read_sys_cfg();
+	printf("VPR CPU board version 0x%02x.\n", system_rev);
+	switch (system_rev) {
+	case VPR_CPU_V1:
+		vpr_pmic_init_v1(mc13892);
+		break;
+	default:
+		printf("Unknown revision 0x%02x.\n", system_rev);
+		return 0;
+	}
+
+	vpr_save_boot_loc();
+
+	return 0;
+}
+
+late_initcall(vpr_final_init);
+
+#ifdef CONFIG_NAND_IMX_BOOT
+void __bare_init nand_boot(void)
+{
+	/*
+	 * The driver is able to detect NAND's pagesize by CPU internal
+	 * fuses or external pull ups. But not the blocksize...
+	 */
+	imx_nand_load_image((void *)TEXT_BASE, 256 * 1024);
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int do_diagled(struct command *cmdtp, int argc, char *argv[])
+{
+	int color;
+
+	if (argc != 2)
+		return COMMAND_ERROR_USAGE;
+
+	color = simple_strtoul(argv[1], NULL, 0);
+	vpr_diag_set_color(color);
+
+	return 0;
+}
+
+BAREBOX_CMD_HELP_START(diagled)
+BAREBOX_CMD_HELP_USAGE("diagled [color]\n")
+BAREBOX_CMD_HELP_SHORT("Sets the color of the diagnostic LED.\n")
+BAREBOX_CMD_HELP_TEXT("\toff\t 0\n")
+BAREBOX_CMD_HELP_TEXT("\tblue\t 1\n")
+BAREBOX_CMD_HELP_TEXT("\tgreen\t 2\n")
+BAREBOX_CMD_HELP_TEXT("\taqua\t 3\n")
+BAREBOX_CMD_HELP_TEXT("\tred\t 4\n")
+BAREBOX_CMD_HELP_TEXT("\tmagenta\t 5\n")
+BAREBOX_CMD_HELP_TEXT("\tyellow\t 6\n")
+BAREBOX_CMD_HELP_TEXT("\twhite\t 7\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(diagled)
+	.cmd            = do_diagled,
+	.usage          = "Set color of diagnositc tri-color LED",
+	BAREBOX_CMD_HELP(cmd_diagled_help)
+BAREBOX_CMD_END
+
+/* ------------------------------------------------------------------------ */
+
+static int do_waitbutton(struct command *cmdtp, int argc, char *argv[])
+{
+	int opt;
+	uint64_t start;
+	ulong timeout = 0;
+	uint32_t bstate;
+
+	while ((opt = getopt(argc, argv, "t:")) > 0) {
+		switch (opt) {
+		case 't':
+			timeout = simple_strtol(optarg, NULL, 0);
+			break;
+		}
+	}
+
+	start = get_time_ns();
+	while (!timeout || !is_timeout(start, timeout * SECOND)) {
+		bstate = vpr_button_state();
+		if (bstate) {
+			printf("%d\n", vpr_button_state_to_number(bstate));
+			return 0;
+		}
+		if (ctrlc())
+			return -EINTR;
+	}
+
+	return -ETIMEDOUT;
+}
+
+BAREBOX_CMD_HELP_START(waitbutton)
+BAREBOX_CMD_HELP_USAGE("waitbutton [-t]\n")
+BAREBOX_CMD_HELP_SHORT("Prints the button number of the next pressed button.\n")
+BAREBOX_CMD_HELP_OPT("-t <seconds>", "time in seconds to wait. 0 (default) is forever.")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(button)
+	.cmd            = do_waitbutton,
+	.usage          = "Wait for button press",
+	BAREBOX_CMD_HELP(cmd_waitbutton_help)
+BAREBOX_CMD_END
+
+/* ------------------------------------------------------------------------ */
+
+static int do_buzzer(struct command *cmdtp, int argc, char *argv[])
+{
+	int opt;
+	uint64_t start;
+	ulong durationms = 200;
+
+	while ((opt = getopt(argc, argv, "d:")) > 0) {
+		switch (opt) {
+		case 'd':
+			durationms = simple_strtol(optarg, NULL, 0);
+			break;
+		}
+	}
+
+	vpr_buzzer_on();
+
+	start = get_time_ns();
+	while (!is_timeout(start, durationms * MSECOND)) {
+
+		vpr_buzzer_on();
+		udelay(120);
+		vpr_buzzer_off();
+		udelay(120);
+
+		if (ctrlc())
+			break;
+	}
+
+	vpr_buzzer_off();
+	return 0;
+}
+
+BAREBOX_CMD_HELP_START(buzzer)
+BAREBOX_CMD_HELP_USAGE("buzzer [-d]\n")
+BAREBOX_CMD_HELP_SHORT("Buzzer beep.\n")
+BAREBOX_CMD_HELP_OPT  ("-d <ms>", "time in milli-seconds to stay on. (default 200ms)\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(buzzer)
+	.cmd            = do_buzzer,
+	.usage          = "Buzzer beep",
+	BAREBOX_CMD_HELP(cmd_buzzer_help)
+BAREBOX_CMD_END
+
diff --git a/arch/arm/boards/vpr200/vpr200.dox b/arch/arm/boards/vpr200/vpr200.dox
new file mode 100644
index 0000000..304e00f
--- /dev/null
+++ b/arch/arm/boards/vpr200/vpr200.dox
@@ -0,0 +1,10 @@
+/** @page vpr200 VPR200
+
+The vpr200 board uses a iMX35 CPU.
+
+- 64 MiB NOR Memory
+- 2x 128 Mib RAM
+- 512 MiB NAND
+- 256 byte EEPROM
+
+*/
diff --git a/arch/arm/configs/vpr200_defconfig b/arch/arm/configs/vpr200_defconfig
new file mode 100644
index 0000000..6b1c64e
--- /dev/null
+++ b/arch/arm/configs/vpr200_defconfig
@@ -0,0 +1,60 @@
+CONFIG_ARCH_IMX=y
+CONFIG_ARCH_IMX_INTERNAL_BOOT=y
+CONFIG_ARCH_IMX_INTERNAL_BOOT_NOR=y
+CONFIG_ARCH_IMX35=y
+CONFIG_MACH_VPR200=y
+CONFIG_IMX_CLKO=y
+CONFIG_AEABI=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_TEXT_BASE=0x87F00000
+CONFIG_MALLOC_SIZE=0x4000000
+CONFIG_EXPERIMENTAL=y
+CONFIG_LONGHELP=y
+CONFIG_GLOB=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/vpr200/env/"
+CONFIG_DEBUG_INFO=y
+CONFIG_ENABLE_DEVICE_NOISE=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_MTEST=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_BMP=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_NET=y
+CONFIG_NET_DHCP=y
+CONFIG_NET_PING=y
+CONFIG_NET_TFTP=y
+CONFIG_DRIVER_NET_FEC_IMX=y
+# CONFIG_SPI is not set
+CONFIG_I2C=y
+CONFIG_I2C_IMX=y
+CONFIG_DRIVER_I2C_AT24=y
+CONFIG_DRIVER_CFI=y
+CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_IMX=y
+CONFIG_NAND_IMX_BOOT=y
+CONFIG_UBI=y
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_IMX_IPU=y
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_IMX_ESDHC=y
+CONFIG_I2C_MC13892=y
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index f3506af..1947ace 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -19,6 +19,7 @@ config ARCH_TEXT_BASE
 	default 0xa7e00000 if MACH_NESO
 	default 0x97f00000 if MACH_MX51_PDK
 	default 0x87f00000 if MACH_GUF_CUPID
+	default 0x87f00000 if MACH_VPR200
 
 config BOARDINFO
 	default "Eukrea CPUIMX25" if MACH_EUKREA_CPUIMX25
@@ -36,6 +37,7 @@ config BOARDINFO
 	default "Garz+Fricke Neso" if MACH_NESO
 	default "Freescale i.MX51 PDK" if MACH_FREESCALE_MX51_PDK
 	default "Garz+Fricke Cupid" if MACH_GUF_CUPID
+	default "VPR200" if MACH_VPR200
 
 config ARCH_HAS_FEC_IMX
 	bool
@@ -310,6 +312,17 @@ config MACH_GUF_CUPID
 	  Say Y here if you are using the Garz+Fricke Neso board equipped
 	  with a Freescale i.MX35 Processor
 
+config MACH_VPR200
+	bool "VPR200"
+	select HAS_CFI
+	select MACH_HAS_LOWLEVEL_INIT
+	select I2C
+	select I2C_IMX
+	select I2C_MC13892
+	help
+	  Say Y here if you are using the VPR200 (i.MX35 Processor)
+
+
 endchoice
 
 endif
-- 
1.7.1




More information about the barebox mailing list