armv7: Add emulation/qemu-armv7 board.

To simplify testing ARM implementation, we need a QEMU configuration for
ARM. The qemu-armv7 provides serial output, CBFS simulation, and full
boot path (bootblock, romstage, ramstage) to verify the boot loader
functionality.

To run with QEMU:
 export QEMU_AUDIO_DRV=none
 qemu-system-arm -M vexpress-a9 -m 1024M -nographic -kernel build/coreboot.rom

Verified to boot until ramstage loaded successfully by QEMU v1.0.50.

Change-Id: I1f23ffaf408199811a0756236821c7e0f2a85004
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: http://review.coreboot.org/2354
Reviewed-by: David Hendricks <dhendrix@chromium.org>
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
diff --git a/src/cpu/Kconfig b/src/cpu/Kconfig
index f60ffe7..caf4ebc 100644
--- a/src/cpu/Kconfig
+++ b/src/cpu/Kconfig
@@ -3,6 +3,7 @@
 # (See also src/Kconfig)
 if ARCH_ARMV7
 
+source src/cpu/armltd/Kconfig
 source src/cpu/samsung/Kconfig
 
 endif	# ARCH_ARM
diff --git a/src/cpu/Makefile.inc b/src/cpu/Makefile.inc
index 93b16ae..e1efecc 100644
--- a/src/cpu/Makefile.inc
+++ b/src/cpu/Makefile.inc
@@ -2,6 +2,7 @@
 ## Subdirectories
 ################################################################################
 subdirs-y += amd
+subdirs-y += armltd
 subdirs-y += intel
 subdirs-y += samsung
 subdirs-y += via
diff --git a/src/cpu/armltd/Kconfig b/src/cpu/armltd/Kconfig
new file mode 100644
index 0000000..b1f4c2e
--- /dev/null
+++ b/src/cpu/armltd/Kconfig
@@ -0,0 +1,8 @@
+config CPU_ARMLTD_CORTEX_A9
+	depends on ARCH_ARMV7
+	bool
+	default n
+
+if CPU_ARMLTD_CORTEX_A9
+source src/cpu/armltd/cortex-a9/Kconfig
+endif
diff --git a/src/cpu/armltd/Makefile.inc b/src/cpu/armltd/Makefile.inc
new file mode 100644
index 0000000..014742f
--- /dev/null
+++ b/src/cpu/armltd/Makefile.inc
@@ -0,0 +1 @@
+subdirs-$(CONFIG_CPU_ARMLTD_CORTEX_A9) += cortex-a9
diff --git a/src/cpu/armltd/cortex-a9/Kconfig b/src/cpu/armltd/cortex-a9/Kconfig
new file mode 100644
index 0000000..7f35cfd
--- /dev/null
+++ b/src/cpu/armltd/cortex-a9/Kconfig
@@ -0,0 +1,5 @@
+config BOOTBLOCK_CPU_INIT
+	string
+	default "cpu/armltd/cortex-a9/bootblock.c"
+	help
+	  CPU/SoC-specific bootblock code.
diff --git a/src/cpu/armltd/cortex-a9/Makefile.inc b/src/cpu/armltd/cortex-a9/Makefile.inc
new file mode 100644
index 0000000..d1e7edf
--- /dev/null
+++ b/src/cpu/armltd/cortex-a9/Makefile.inc
@@ -0,0 +1,2 @@
+ramstage-y += cache.c
+romstage-y += cache.c
diff --git a/src/cpu/armltd/cortex-a9/bootblock.c b/src/cpu/armltd/cortex-a9/bootblock.c
new file mode 100644
index 0000000..8925439
--- /dev/null
+++ b/src/cpu/armltd/cortex-a9/bootblock.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+void bootblock_cpu_init(void);
+void bootblock_cpu_init(void)
+{
+}
diff --git a/src/cpu/armltd/cortex-a9/cache.c b/src/cpu/armltd/cortex-a9/cache.c
new file mode 100644
index 0000000..957871d
--- /dev/null
+++ b/src/cpu/armltd/cortex-a9/cache.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <system.h>
+#include <armv7.h>
+
+/*
+ * Sets L2 cache related parameters before enabling data cache
+ */
+void v7_outer_cache_enable(void)
+{
+}
+
+/* stubs so we don't need weak symbols in cache_v7.c */
+void v7_outer_cache_disable(void)
+{
+}
+
+void v7_outer_cache_flush_all(void)
+{
+}
+
+void v7_outer_cache_inval_all(void)
+{
+}
+
+void v7_outer_cache_flush_range(u32 start, u32 end)
+{
+}
+
+void v7_outer_cache_inval_range(u32 start, u32 end)
+{
+}
diff --git a/src/mainboard/emulation/Kconfig b/src/mainboard/emulation/Kconfig
index 5661f0e..ea6b180 100644
--- a/src/mainboard/emulation/Kconfig
+++ b/src/mainboard/emulation/Kconfig
@@ -6,9 +6,13 @@
 config BOARD_EMULATION_QEMU_X86
 	bool "QEMU x86"
 
+config BOARD_EMULATION_QEMU_ARMV7
+	bool "QEMU armv7 (vexpress-a9)"
+
 endchoice
 
 source "src/mainboard/emulation/qemu-x86/Kconfig"
+source "src/mainboard/emulation/qemu-armv7/Kconfig"
 
 config MAINBOARD_VENDOR
 	string
diff --git a/src/mainboard/emulation/qemu-armv7/Kconfig b/src/mainboard/emulation/qemu-armv7/Kconfig
new file mode 100644
index 0000000..38b1da24
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/Kconfig
@@ -0,0 +1,116 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 Google Inc.
+##
+## This software is licensed under the terms of the GNU General Public
+## License version 2, as published by the Free Software Foundation, and
+## may be copied, distributed, and modified under those terms.
+##
+## 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.
+
+# Emulation for ARM Ltd Versatile Express Cortex-A9
+#  http://www.arm.com/products/tools/development-boards/versatile-express
+
+# To execute, do:
+# export QEMU_AUDIO_DRV=none
+# qemu-system-arm -M vexpress-a9 -m 1024M -nographic -kernel build/coreboot.rom
+
+if BOARD_EMULATION_QEMU_ARMV7
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select ARCH_ARMV7
+	select CPU_ARMLTD_CORTEX_A9
+	select DEFAULT_EARLY_CONSOLE
+	select HAVE_UART_SPECIAL
+	select BOARD_ROMSIZE_KB_4096
+
+config MAINBOARD_DIR
+	string
+	default emulation/qemu-armv7
+
+config MAINBOARD_PART_NUMBER
+	string
+	default "QEMU ARMV7"
+
+config MAX_CPUS
+	int
+	default 2
+
+config MAINBOARD_VENDOR
+	string
+	default "ARM Ltd."
+
+config BOOTBLOCK_MAINBOARD_INIT
+	string
+	default "mainboard/emulation/qemu-armv7/bootblock.c"
+
+config DRAM_SIZE_MB
+	int
+	default 1024
+
+# Memory map for qemu vexpress-a9:
+#
+# 0x0000_0000: jump instruction (by qemu)
+# 0x0001_0000: bootblock (entry of kernel / firmware)
+# 0x0002_0000: romstage, assume up to 128KB in size.
+# 0x0007_ff00: stack pointer
+# 0x0010_0000: CBFS header
+# 0x0011_0000: CBFS data
+# 0x0100_0000: reserved for ramstage
+# 0x1000_0000: I/O map address
+
+config BOOTBLOCK_BASE
+	hex
+	default 0x00010000
+
+config ID_SECTION_BASE
+	hex
+	default 0x0001f000
+
+config ROMSTAGE_BASE
+	hex
+	default 0x00020000
+
+config ROMSTAGE_SIZE
+	hex
+	default 0x20000
+
+config CBFS_HEADER_ROM_OFFSET
+	hex
+	default 0x0100000
+
+config CBFS_ROM_OFFSET
+	hex
+	default 0x0110000
+
+config IRAM_STACK
+	hex
+	default 0x0007ff00
+
+config XIP_ROM_SIZE
+	hex
+	default ROMSTAGE_SIZE
+
+config SYS_SDRAM_BASE
+	hex "SDRAM base address"
+	default 0x01000000
+
+config SYS_TEXT_BASE
+	hex "Executable code section"
+	default 0x04e00000
+
+config RAMBASE
+	hex
+	default SYS_SDRAM_BASE
+
+# according to stefan, this is RAMBASE + 1M.
+config RAMTOP
+	hex
+	default 0x01100000
+
+endif #  BOARD_EMULATION_QEMU_ARMV7
diff --git a/src/mainboard/emulation/qemu-armv7/Makefile.inc b/src/mainboard/emulation/qemu-armv7/Makefile.inc
new file mode 100644
index 0000000..cea3b15
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/Makefile.inc
@@ -0,0 +1,30 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 Google Inc.
+##
+## This software is licensed under the terms of the GNU General Public
+## License version 2, as published by the Free Software Foundation, and
+## may be copied, distributed, and modified under those terms.
+##
+## 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.
+
+romstage-y += romstage.c
+ramstage-y += ramstage.c
+
+bootblock-y += media.c
+romstage-y += media.c
+ramstage-y += media.c
+
+bootblock-y += timer.c
+romstage-y += timer.c
+ramstage-y += timer.c
+
+bootblock-$(CONFIG_EARLY_CONSOLE) += uart.c
+romstage-$(CONFIG_EARLY_CONSOLE) += uart.c
+ramstage-y += uart.c
+
+SRC_ROOT = $(src)/mainboard/emulation/qemu-armv7a
diff --git a/src/mainboard/emulation/qemu-armv7/bootblock.c b/src/mainboard/emulation/qemu-armv7/bootblock.c
new file mode 100644
index 0000000..5654667
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/bootblock.c
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <console/console.h>
+
+void bootblock_mainboard_init(void);
+void bootblock_mainboard_init(void)
+{
+	console_init();
+	printk(BIOS_INFO, "\n\n\n%s: ARMv7 Emulation Started.\n", __func__);
+}
diff --git a/src/mainboard/emulation/qemu-armv7/devicetree.cb b/src/mainboard/emulation/qemu-armv7/devicetree.cb
new file mode 100644
index 0000000..9153442
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/devicetree.cb
@@ -0,0 +1,20 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2013 Google, Inc.
+##
+## This software is licensed under the terms of the GNU General Public
+## License version 2, as published by the Free Software Foundation, and
+## may be copied, distributed, and modified under those terms.
+##
+## 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.
+
+# TODO fill with Versatile Express board data in QEMU.
+chip cpu/armltd/cortex-a9
+	chip drivers/generic/generic # I2C0 controller
+		device i2c 6 on end # Fake component for testing
+	end
+end
diff --git a/src/mainboard/emulation/qemu-armv7/mainboard.c b/src/mainboard/emulation/qemu-armv7/mainboard.c
new file mode 100644
index 0000000..cbc3197
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/mainboard.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+
+static void enable_dev(device_t dev)
+{
+	printk(BIOS_INFO, "Enable qemu/armv7 device...\n");
+}
+
+struct chip_operations mainboard_ops = {
+	.enable_dev = enable_dev,
+};
+
diff --git a/src/mainboard/emulation/qemu-armv7/media.c b/src/mainboard/emulation/qemu-armv7/media.c
new file mode 100644
index 0000000..d024b5d
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/media.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+#include <cbfs.h>
+#include <string.h>
+#include <console/console.h>
+
+/* Simple memory-mapped ROM emulation. */
+
+static int emu_rom_open(struct cbfs_media *media) {
+	return 0;
+}
+
+static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count) {
+        return (void*)(offset + CONFIG_BOOTBLOCK_BASE);
+}
+
+static void *emu_rom_unmap(struct cbfs_media *media, const void *address) {
+	return NULL;
+}
+
+static size_t emu_rom_read(struct cbfs_media *media, void *dest, size_t offset,
+			   size_t count) {
+	void *ptr = emu_rom_map(media, offset, count);
+	memcpy(dest, ptr, count);
+	emu_rom_unmap(media, ptr);
+	return count;
+}
+
+static int emu_rom_close(struct cbfs_media *media) {
+	return 0;
+}
+
+int init_emu_rom_cbfs_media(struct cbfs_media *media);
+int init_emu_rom_cbfs_media(struct cbfs_media *media) {
+	media->open = emu_rom_open;
+	media->close = emu_rom_close;
+	media->map = emu_rom_map;
+	media->unmap = emu_rom_unmap;
+	media->read = emu_rom_read;
+	return 0;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media) {
+	return init_emu_rom_cbfs_media(media);
+}
diff --git a/src/mainboard/emulation/qemu-armv7/ramstage.c b/src/mainboard/emulation/qemu-armv7/ramstage.c
new file mode 100644
index 0000000..24d0d7f
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/ramstage.c
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <console/console.h>
+
+void hardwaremain(int boot_complete);
+void main(void)
+{
+	console_init();
+	printk(BIOS_INFO, "hello from ramstage\n");
+	hardwaremain(0);
+}
diff --git a/src/mainboard/emulation/qemu-armv7/romstage.c b/src/mainboard/emulation/qemu-armv7/romstage.c
new file mode 100644
index 0000000..81f62b6
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/romstage.c
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <cbfs.h>
+#include <common.h>
+#include <console/console.h>
+#include <arch/stages.h>
+
+void main(void)
+{
+        void *entry;
+	console_init();
+	printk(BIOS_INFO, "hello from romstage\n");
+
+	entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram");
+	printk(BIOS_INFO, "entry is 0x%p, leaving romstage.\n", entry);
+
+	stage_exit(entry);
+}
diff --git a/src/mainboard/emulation/qemu-armv7/timer.c b/src/mainboard/emulation/qemu-armv7/timer.c
new file mode 100644
index 0000000..53c3789
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/timer.c
@@ -0,0 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+void udelay(unsigned int n);
+void udelay(unsigned int n) {
+	/* TODO provide delay here. */
+}
+
+int init_timer(void);
+int init_timer(void) {
+	return 0;
+}
diff --git a/src/mainboard/emulation/qemu-armv7/uart.c b/src/mainboard/emulation/qemu-armv7/uart.c
new file mode 100644
index 0000000..2988777
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/uart.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <console/console.h>
+#include <uart.h>
+
+#define VEXPRESS_UART0_IO_ADDRESS	(0x10009000)
+
+static void pl011_init_dev(void) {
+}
+
+static void pl011_uart_tx_byte(unsigned char data) {
+	static volatile unsigned int *uart0_address =
+			(unsigned int *)VEXPRESS_UART0_IO_ADDRESS;
+
+	*uart0_address = (unsigned int)data;
+}
+
+static void pl011_uart_tx_flush(void) {
+}
+
+#if !defined(__PRE_RAM__)
+
+static const struct console_driver pl011_uart_console __console = {
+	.init     = pl011_init_dev,
+	.tx_byte  = pl011_uart_tx_byte,
+	.tx_flush = pl011_uart_tx_flush,
+};
+
+#else
+void uart_init(void)
+{
+	pl011_init_dev();
+}
+
+void uart_tx_byte(unsigned char data)
+{
+	pl011_uart_tx_byte(data);
+}
+
+void uart_tx_flush(void) {
+	pl011_uart_tx_flush();
+}
+#endif