[coreboot-gerrit] New patch to review for coreboot: soc/marvell/armada38x: Add generic support for armada38x

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Thu Jan 21 11:59:48 CET 2016


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/13110

-gerrit

commit bddefb5391747e248eece66eb9b226c84b62471a
Author: Ruilin Hao <rlhao at marvell.com>
Date:   Mon Nov 9 22:37:09 2015 -0800

    soc/marvell/armada38x: Add generic support for armada38x
    
    Skeleton for soc armada38x
    
    BUG=chrome-os-partner:47462
    TEST=None
    BRANCH=tot
    
    Change-Id: I76f631ee6cdfc90c44727cb20aa960796bc785a5
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: e91cc19468325f005c6ac920bbe27a174c409727
    Original-Change-Id: Iac5fc34df1ba18b4515029aa2fcff8f78a5df191
    Original-Signed-off-by: Ruilin Hao <rlhao at marvell.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/313179
    Original-Commit-Ready: Kan Yan <kyan at google.com>
    Original-Tested-by: Kan Yan <kyan at google.com>
    Original-Reviewed-by: Kan Yan <kyan at google.com>
---
 src/soc/marvell/armada38x/Kconfig                  |  27 ++++
 src/soc/marvell/armada38x/Makefile.inc             |  31 ++++
 src/soc/marvell/armada38x/bootblock.c              | 179 +++++++++++++++++++++
 src/soc/marvell/armada38x/bootblock_asm.S          | 126 +++++++++++++++
 src/soc/marvell/armada38x/cbmem.c                  |  25 +++
 src/soc/marvell/armada38x/include/soc/common.h     | 131 +++++++++++++++
 src/soc/marvell/armada38x/include/soc/memlayout.ld |  37 +++++
 .../marvell/armada38x/include/soc/soc_services.h   |  26 +++
 src/soc/marvell/armada38x/monotonic_timer.c        |  61 +++++++
 src/soc/marvell/armada38x/soc.c                    |  58 +++++++
 src/soc/marvell/armada38x/uart.c                   | 154 ++++++++++++++++++
 11 files changed, 855 insertions(+)

diff --git a/src/soc/marvell/armada38x/Kconfig b/src/soc/marvell/armada38x/Kconfig
new file mode 100644
index 0000000..6754a0f
--- /dev/null
+++ b/src/soc/marvell/armada38x/Kconfig
@@ -0,0 +1,27 @@
+config SOC_MARVELL_ARMADA38X
+	bool
+	default n
+	select ARCH_BOOTBLOCK_ARMV7
+	select ARCH_VERSTAGE_ARMV7
+	select ARCH_ROMSTAGE_ARMV7
+	select ARCH_RAMSTAGE_ARMV7
+	select HAVE_UART_SPECIAL
+	select BOOTBLOCK_CONSOLE
+	select RETURN_FROM_VERSTAGE
+	select BOOTBLOCK_CUSTOM
+	select GENERIC_UDELAY
+
+if SOC_MARVELL_ARMADA38X
+
+config BOOTBLOCK_CPU_INIT
+	string
+	default "soc/marvell/armada38x/bootblock.c"
+	help
+	  CPU/SoC-specific bootblock code. This is useful if the
+	  bootblock must load microcode or copy data from ROM before
+	  searching for the bootblock.
+
+config CONSOLE_SERIAL_UART_ADDRESS
+	hex
+	default 0xf1012000
+endif
diff --git a/src/soc/marvell/armada38x/Makefile.inc b/src/soc/marvell/armada38x/Makefile.inc
new file mode 100644
index 0000000..416ad74
--- /dev/null
+++ b/src/soc/marvell/armada38x/Makefile.inc
@@ -0,0 +1,31 @@
+ifeq ($(CONFIG_SOC_MARVELL_ARMADA38X),y)
+
+bootblock-y += bootblock.c
+bootblock-y += bootblock_asm.S
+bootblock-y += monotonic_timer.c
+ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)
+bootblock-$(CONFIG_DRIVERS_UART) += uart.c
+endif
+
+verstage-$(CONFIG_DRIVERS_UART) += uart.c
+verstage-y += monotonic_timer.c
+
+romstage-y += cbmem.c
+romstage-y += monotonic_timer.c
+romstage-$(CONFIG_DRIVERS_UART) += uart.c
+
+ramstage-y += cbmem.c
+ramstage-y += monotonic_timer.c
+ramstage-y += soc.c
+ramstage-$(CONFIG_DRIVERS_UART) += uart.c
+
+CPPFLAGS_common += -Isrc/soc/marvell/armada38x/include/
+
+BIN_HDR = 3rdparty/blobs/cpu/marvell/armada38x/bin_hdr.bin
+DOIMAGE = 3rdparty/blobs/cpu/marvell/armada38x/doimage
+
+$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin
+	@chmod a+x $(DOIMAGE)
+	$(DOIMAGE) -T flash -D 0 -E 0 -G $(BIN_HDR) $< $@
+	rm $<
+endif
diff --git a/src/soc/marvell/armada38x/bootblock.c b/src/soc/marvell/armada38x/bootblock.c
new file mode 100644
index 0000000..a8d2a7e
--- /dev/null
+++ b/src/soc/marvell/armada38x/bootblock.c
@@ -0,0 +1,179 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <arch/io.h>
+#include <arch/cache.h>
+#include <arch/exception.h>
+#include <arch/hlt.h>
+#include <bootblock_common.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <delay.h>
+#include <arch/stages.h>
+#include <symbols.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <soc/common.h>
+
+#define CLOCK_BIT_SATA23	BIT30
+#define CLOCK_BIT_PNC		BIT29
+#define CLOCK_BIT_TDM		BIT25
+#define CLOCK_BIT_CRYPTO0_GATE	BIT23
+#define CLOCK_BIT_CRYPTO1_GATE	BIT21
+#define CLOCK_BIT_CRYPTO1_Z	BIT16
+#define CLOCK_BIT_SATA01	BIT15
+#define CLOCK_BIT_CRYPTO0_Z	BIT14
+#define CLOCK_BIT_BM		BIT13
+#define CLOCK_BIT_PCIE2		BIT6
+#define CLOCK_BIT_PCIE1		BIT5
+#define CLOCK_BIT_GBE0		BIT4
+#define CLOCK_BIT_GBE1		BIT3
+#define CLOCK_BIT_GBE2		BIT2
+#define CLOCK_BIT_AUDIO		BIT0
+
+#define A38x_MPP0_7_OFFSET 0x18000
+#define A38x_MPP8_15_OFFSET 0x18004
+#define A38x_MPP16_23_OFFSET 0x18008
+#define A38x_MPP24_31_OFFSET 0x1800c
+#define A38x_MPP32_39_OFFSET 0x18010
+#define A38x_MPP40_47_OFFSET 0x18014
+#define A38x_MPP48_55_OFFSET 0x18018
+#define A38x_MPP56_63_OFFSET 0x1801c
+
+#define A38X_GPP_OUT_ENA_OFFSET_LOW 0x18104
+#define A38X_GPP_OUT_ENA_OFFSET_MID 0x18144
+
+#define A38X_GPP_OUT_VALUE_OFFSET_LOW	0x18100
+#define A38X_GPP_OUT_VALUE_OFFSET_MID	0x18140
+
+#define A38x_CUBE_BOARD_MPP0_7 0x00001111
+#define A38x_CUBE_BOARD_MPP8_15 0x46200000
+#define A38x_CUBE_BOARD_MPP16_23 0x00400444
+#define A38x_CUBE_BOARD_MPP24_31 0x00043300
+#define A38x_CUBE_BOARD_MPP32_39 0x44400000
+#define A38x_CUBE_BOARD_MPP40_47 0x00000004
+#define A38x_CUBE_BOARD_MPP48_55 0x00444444
+#define A38x_CUBE_BOARD_MPP56_63 0x00004444
+
+/* Set bit x to enable GPIO output mode for MPP x */
+#define A38x_CUBE_BOARD_0_GPP_OUT_ENA_LOW ~(BIT4 | BIT6)
+/* MID group is for MPP32 ~ MPP63 e.g BIT3 corresponds to MPP35 */
+#define A38x_CUBE_BOARD_0_GPP_OUT_ENA_MID ~(BIT3)
+
+#define A38x_CUSTOMER_BOARD_0_GPP_OUT_VAL_LOW (BIT4)
+/* MID group is for MPP32 ~ MPP63 e.g BIT3 corresponds to MPP35 */
+#define A38x_CUSTOMER_BOARD_0_GPP_OUT_VAL_MID (BIT3)
+
+#define A38X_POWER_MANAGEMENT_CLOCK_GATING_CONTROL 0x18220
+
+#define A38x_SOC_IO_ERR_CTRL_OFFSET 0x20200
+#define A38x_SOC_WIN_CTRL_OFFSET 0x20250
+#define A38x_SOC_WIN_BASE_OFFSET 0x20254
+
+#define A38x_CUBE_BOARD_SOC_IO_ERR_CTRL 0x00000000
+#define A38x_CUBE_BOARD_SOC_WIN_CTRL 0x1ff00001
+#define A38x_CUBE_BOARD_SOC_BASE_CTRL 0xe0000000
+
+#define DRAM_START ((uintptr_t)_dram / MiB)
+#define DRAM_SIZE (CONFIG_DRAM_SIZE_MB)
+/* DMA memory for drivers */
+#define DMA_START ((uintptr_t)_dma_coherent / MiB)
+#define DMA_SIZE (_dma_coherent_size / MiB)
+
+static void setup_pinmux(void)
+{
+	/* Hard coded pin mux configuration */
+	mrvl_reg_write(A38x_MPP0_7_OFFSET, A38x_CUBE_BOARD_MPP0_7);
+	mrvl_reg_write(A38x_MPP8_15_OFFSET, A38x_CUBE_BOARD_MPP8_15);
+	mrvl_reg_write(A38x_MPP16_23_OFFSET, A38x_CUBE_BOARD_MPP16_23);
+	mrvl_reg_write(A38x_MPP24_31_OFFSET, A38x_CUBE_BOARD_MPP24_31);
+	mrvl_reg_write(A38x_MPP32_39_OFFSET, A38x_CUBE_BOARD_MPP32_39);
+	mrvl_reg_write(A38x_MPP40_47_OFFSET, A38x_CUBE_BOARD_MPP40_47);
+	mrvl_reg_write(A38x_MPP48_55_OFFSET, A38x_CUBE_BOARD_MPP48_55);
+	mrvl_reg_write(A38x_MPP56_63_OFFSET, A38x_CUBE_BOARD_MPP56_63);
+}
+
+static void setup_gpp_out_value(void)
+{
+	mrvl_reg_write(
+		A38X_GPP_OUT_VALUE_OFFSET_LOW,
+			A38x_CUSTOMER_BOARD_0_GPP_OUT_VAL_LOW);
+	mrvl_reg_write(
+		A38X_GPP_OUT_VALUE_OFFSET_MID,
+			A38x_CUSTOMER_BOARD_0_GPP_OUT_VAL_MID);
+}
+
+static void setup_gpp_out_enable(void)
+{
+	mrvl_reg_write(
+		A38X_GPP_OUT_ENA_OFFSET_LOW,
+			A38x_CUBE_BOARD_0_GPP_OUT_ENA_LOW);
+	mrvl_reg_write(
+		A38X_GPP_OUT_ENA_OFFSET_MID,
+			A38x_CUBE_BOARD_0_GPP_OUT_ENA_MID);
+}
+
+/* This function disable unused periperal clocks */
+static void setup_peripherals_clocks(void)
+{
+	mrvl_reg_bit_reset(
+		A38X_POWER_MANAGEMENT_CLOCK_GATING_CONTROL, (
+			CLOCK_BIT_SATA23 | CLOCK_BIT_PNC | CLOCK_BIT_TDM |
+			CLOCK_BIT_CRYPTO0_GATE | CLOCK_BIT_CRYPTO1_GATE |
+			CLOCK_BIT_CRYPTO1_Z | CLOCK_BIT_SATA01 |
+			CLOCK_BIT_CRYPTO0_Z | CLOCK_BIT_BM |
+			CLOCK_BIT_PCIE2 | CLOCK_BIT_PCIE1 |
+			CLOCK_BIT_GBE0 | CLOCK_BIT_GBE1 |
+			CLOCK_BIT_GBE2 | CLOCK_BIT_AUDIO
+		)
+	);
+}
+
+static void setup_win_regs(void)
+{
+	mrvl_reg_write(A38x_SOC_IO_ERR_CTRL_OFFSET,
+			A38x_CUBE_BOARD_SOC_IO_ERR_CTRL);
+	mrvl_reg_write(A38x_SOC_WIN_CTRL_OFFSET, A38x_CUBE_BOARD_SOC_WIN_CTRL);
+	mrvl_reg_write(A38x_SOC_WIN_BASE_OFFSET, A38x_CUBE_BOARD_SOC_BASE_CTRL);
+}
+
+void main(void)
+{
+	if (CONFIG_BOOTBLOCK_CONSOLE) {
+		console_init();
+		exception_init();
+	}
+
+	init_timer();
+
+	/* enable mmu */
+	mmu_init();
+	mmu_config_range(0, 4096, DCACHE_OFF);
+	mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
+	mmu_config_range(DMA_START, DMA_SIZE, DCACHE_OFF);
+	dcache_mmu_enable();
+
+	bootblock_mainboard_init();
+
+	setup_pinmux();
+	setup_gpp_out_value();
+	setup_gpp_out_enable();
+	setup_win_regs();
+	setup_peripherals_clocks();
+	run_romstage();
+}
diff --git a/src/soc/marvell/armada38x/bootblock_asm.S b/src/soc/marvell/armada38x/bootblock_asm.S
new file mode 100644
index 0000000..9711744
--- /dev/null
+++ b/src/soc/marvell/armada38x/bootblock_asm.S
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arch/asm.h>
+
+.arm
+	/*
+	 * Just in case the maskrom or the vendor basic firmware passes on a
+	 * parameter when calling the bootblock, store it here for handling by C
+	 * code.
+	 */
+	.section .bss, "aw" @nobits
+	.global maskrom_param
+	.align 4
+maskrom_param:
+	.word 0
+
+ENTRY(_start)
+	/*
+	 * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data
+	 * aborts may happen early and crash before the abort handlers are
+	 * installed, but at least the problem will show up near the code that
+	 * causes it.
+	 */
+	msr	cpsr_cxf, #0xdf
+	bl	_thumb_start
+ENDPROC(_start)
+
+.thumb
+ENTRY(_thumb_start)
+
+	/* Preserve the maskrom passed value, if any */
+	mov	r10, r0
+
+	/* Disable L2 Cache */
+        ldr r1, =0x0
+        ldr r0, =0xD0008100
+        str r1, [r0]
+
+        /* Disable windows that overlap with 0xF1000000 */
+        /* By default, window #12 overlaps with 0xF1000000 */
+        mov  r1, #0
+        ldr  r0, =0xD00200B0
+        str  r1, [r0]
+        /* Set Registers Base address. */
+        ldr  r1, =0xf1000000
+        ldr  r0, =0xD0020080
+        str  r1, [r0]
+        /* Update SCU (peripheral) register Base address with
+	 * correct INTER_REG_BASE
+	 */
+        ldr r2, = 0xC000                /* SCU offset = 0xC000 */
+        add r1, r1, r2                  /* r1 = INTER_REG_BASE + SCU_OFFSET */
+        mcr p15, 4, r1, c15, c0, 0      /* Write SCU base register */
+
+	bl	arm_init_caches
+
+	/*
+	 * From Cortex-A Series Programmer's Guide:
+	 * Only CPU 0 performs initialization. Other CPUs go into WFI
+	 * to do this, first work out which CPU this is
+	 * this code typically is run before any other initialization step
+	 */
+	mrc p15, 0, r1, c0, c0, 5	@ Read Multiprocessor Affinity Register
+	and r1, r1, #0x3 @ Extract CPU ID bits
+	cmp r1, #0
+	bne wait_for_interrupt		@ If this is not core0, wait
+
+	/*
+	 * Initialize the stack to a known value. This is used to check for
+	 * stack overflow later in the boot process.
+	 */
+	ldr	r0, =_stack
+	ldr	r1, =_estack
+	ldr	r2, =0xdeadbeef
+init_stack_loop:
+	str	r2, [r0]
+	add	r0, #4
+	cmp	r0, r1
+	bne	init_stack_loop
+
+        ldr     r0, =_bss
+        ldr     r1, =_ebss
+        mov     r2, #0x00000000         /* prepare zero to clear BSS */
+clbss_l:
+	str     r2, [r0]
+	add     r0, #4
+	cmp     r0, r1
+	bne     clbss_l
+
+call_bootblock:
+
+	/* Restore parameter passed in by maskrom/vendor firmware. */
+	ldr	r0, =maskrom_param
+	str	r10, [r0]
+
+	/* Set stackpointer in internal RAM to call bootblock main() */
+	ldr	sp, =_estack
+	ldr	r0,=0x00000000
+	 /*
+	  * The current design of cpu_info places the struct at the top of the
+	  * stack. Free enough space to accommodate for that, but make sure it's
+	  * 8-byte aligned for ABI compliance.
+	  */
+	sub	sp, sp, #16
+	bl	main
+
+wait_for_interrupt:
+	wfi
+	mov	pc, lr			@ back to my caller
+ENDPROC(_thumb_start)
diff --git a/src/soc/marvell/armada38x/cbmem.c b/src/soc/marvell/armada38x/cbmem.c
new file mode 100644
index 0000000..eaaa096
--- /dev/null
+++ b/src/soc/marvell/armada38x/cbmem.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <cbmem.h>
+#include <soc/soc_services.h>
+
+void *cbmem_top(void)
+{
+	return (void *)_memlayout_cbmem_top;
+}
diff --git a/src/soc/marvell/armada38x/include/soc/common.h b/src/soc/marvell/armada38x/include/soc/common.h
new file mode 100644
index 0000000..296a088
--- /dev/null
+++ b/src/soc/marvell/armada38x/include/soc/common.h
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Marvell Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SOC_MARVELL_ARMADA38X_COMMON_H_
+#define __SOC_MARVELL_ARMADA38X_COMMON_H_
+
+#include <types.h>
+#include <arch/io.h>
+
+#define INTER_REGS_BASE 0xF1000000
+
+#define MV_TRUE (1)
+#define MV_FALSE (0)
+
+/* The following is a list of Marvell status    */
+#define MV_ERROR (-1)
+#define MV_OK (0)
+#define MV_FAIL (1)
+#define MV_BAD_VALUE (2)
+#define MV_OUT_OF_RANGE (3)
+#define MV_BAD_PARAM (4)
+#define MV_BAD_PTR (5)
+#define MV_BAD_SIZE (6)
+#define MV_BAD_STATE (7)
+#define MV_SET_ERROR (8)
+#define MV_GET_ERROR (9)
+#define MV_CREATE_ERROR (10)
+#define MV_NOT_FOUND (11)
+#define MV_NO_MORE (12)
+#define MV_NO_SUCH (13)
+#define MV_TIMEOUT (14)
+#define MV_NO_CHANGE (15)
+#define MV_NOT_SUPPORTED (16)
+#define MV_NOT_IMPLEMENTED (17)
+#define MV_NOT_INITIALIZED (18)
+#define MV_NO_RESOURCE (19)
+#define MV_FULL (20)
+#define MV_EMPTY (21)
+#define MV_INIT_ERROR (22)
+#define MV_HW_ERROR (23)
+#define MV_TX_ERROR (24)
+#define MV_RX_ERROR (25)
+#define MV_NOT_READY (26)
+#define MV_ALREADY_EXIST (27)
+#define MV_OUT_OF_CPU_MEM (28)
+#define MV_NOT_STARTED (29)
+#define MV_BUSY (30)
+#define MV_TERMINATE (31)
+#define MV_NOT_ALIGNED (32)
+#define MV_NOT_ALLOWED (33)
+#define MV_WRITE_PROTECT (34)
+#define MV_DROPPED (35)
+#define MV_STOLEN (36)
+#define MV_CONTINUE (37)
+#define MV_RETRY (38)
+
+#define MV_INVALID (int)(-1)
+
+#define MV_BOARD_TCLK_200MHZ 200000000
+#define MV_BOARD_TCLK_250MHZ 250000000
+
+#define MPP_SAMPLE_AT_RESET (0x18600)
+
+#define MV_6810_DEV_ID 0x6810
+
+#define BIT0        0x00000001
+#define BIT1        0x00000002
+#define BIT2        0x00000004
+#define BIT3        0x00000008
+#define BIT4        0x00000010
+#define BIT5        0x00000020
+#define BIT6        0x00000040
+#define BIT7        0x00000080
+#define BIT8        0x00000100
+#define BIT9        0x00000200
+#define BIT10       0x00000400
+#define BIT11       0x00000800
+#define BIT12       0x00001000
+#define BIT13       0x00002000
+#define BIT14       0x00004000
+#define BIT15       0x00008000
+#define BIT16       0x00010000
+#define BIT17       0x00020000
+#define BIT18       0x00040000
+#define BIT19       0x00080000
+#define BIT20       0x00100000
+#define BIT21       0x00200000
+#define BIT22       0x00400000
+#define BIT23       0x00800000
+#define BIT24       0x01000000
+#define BIT25       0x02000000
+#define BIT26       0x04000000
+#define BIT27       0x08000000
+#define BIT28       0x10000000
+#define BIT29       0x20000000
+#define BIT30       0x40000000
+#define BIT31       0x80000000
+
+static inline uint32_t mrvl_reg_read(uint32_t offset)
+{
+	return read32((void *)(INTER_REGS_BASE + offset));
+}
+static inline void mrvl_reg_write(uint32_t offset, uint32_t val)
+{
+	write32((void *)(INTER_REGS_BASE + offset), val);
+}
+static inline void mrvl_reg_bit_set(uint32_t offset, uint32_t bit_mask)
+{
+	mrvl_reg_write(offset, (mrvl_reg_read(offset) | bit_mask));
+}
+static inline void mrvl_reg_bit_reset(uint32_t offset, uint32_t bit_mask)
+{
+	mrvl_reg_write(offset, (mrvl_reg_read(offset) & (~bit_mask)));
+}
+
+#endif  // __SOC_MARVELL_ARMADA38X_COMMON_H__
diff --git a/src/soc/marvell/armada38x/include/soc/memlayout.ld b/src/soc/marvell/armada38x/include/soc/memlayout.ld
new file mode 100644
index 0000000..a36abcf
--- /dev/null
+++ b/src/soc/marvell/armada38x/include/soc/memlayout.ld
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <memlayout.h>
+#include <arch/header.ld>
+
+SECTIONS
+{
+	DRAM_START(0x00000000)
+	BOOTBLOCK(0x00000000, 24K)
+	RAMSTAGE(0x00800000, 128K)
+	CBFS_CACHE(0x12006000, 80K)
+	STACK(0x1201c000, 16K)
+
+	VERSTAGE(0x1202c000, 96K)
+	ROMSTAGE(0x12044000, 96K)
+	VBOOT2_WORK(0x1205c000, 16K)
+	DMA_COHERENT(0x12100000, 2M)
+	SYMBOL(memlayout_cbmem_top, 0x1F400000)
+	TTB(0x1FF00000, 16K)
+	TTB_SUBTABLES(0x1FF04000, 2K)
+}
diff --git a/src/soc/marvell/armada38x/include/soc/soc_services.h b/src/soc/marvell/armada38x/include/soc/soc_services.h
new file mode 100644
index 0000000..cd3aad0
--- /dev/null
+++ b/src/soc/marvell/armada38x/include/soc/soc_services.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SOC_MARVELL_ARMADA38X_SOC_SERVICES_H_
+#define __SOC_MARVELL_ARMADA38X_SOC_SERVICES_H_
+
+#include <types.h>
+
+extern u8 _memlayout_cbmem_top[];
+
+#endif /*__SOC_MARVELL_ARMADA38X_SOC_SERVICES_H_*/
diff --git a/src/soc/marvell/armada38x/monotonic_timer.c b/src/soc/marvell/armada38x/monotonic_timer.c
new file mode 100644
index 0000000..3c757e9
--- /dev/null
+++ b/src/soc/marvell/armada38x/monotonic_timer.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arch/io.h>
+#include <timer.h>
+#include <delay.h>
+
+#define TIMER_CTRL_REG 0xf1020300
+#define TIMER_RELOAD_REG 0xf1020310
+#define TIMER_REG 0xf1020314
+#define TIMER_RELOAD_VALUE 0xffffffff
+
+#define MHZ_NUM 25
+
+void init_timer(void)
+{
+	unsigned int reg;
+
+	/* Set the reload timer */
+	write32((void *)TIMER_RELOAD_REG, TIMER_RELOAD_VALUE);
+	/* Set the initial value to TIMER_RELOAD_VALUE - 1
+	 * (instead of TIMER_RELOAD_VALUE) to avoid 'fake'
+	 * overflow being detected in timer_monotonic_get
+	 * if it's called close enough with 'this' function */
+	write32((void *)TIMER_REG, TIMER_RELOAD_VALUE - 1);
+	reg = read32((const void *)TIMER_CTRL_REG);
+	/* Let it start counting */
+	reg |= 0x3;
+	write32((void *)TIMER_CTRL_REG, reg);
+}
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+	static uint64_t total_ticks = 0;
+	uint64_t overflow = 0;
+	uint32_t current_ticks =
+		TIMER_RELOAD_VALUE - read32((const void *)TIMER_REG);
+
+	/* Assuming at most one overflow happened since last call */
+	if (current_ticks <= total_ticks)
+		overflow = 1ULL << 32;
+
+	total_ticks = (((total_ticks + overflow) >> 32) << 32) + current_ticks;
+	mono_time_set_usecs(mt, total_ticks / MHZ_NUM);
+}
+
diff --git a/src/soc/marvell/armada38x/soc.c b/src/soc/marvell/armada38x/soc.c
new file mode 100644
index 0000000..200d240
--- /dev/null
+++ b/src/soc/marvell/armada38x/soc.c
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <vendorcode/google/chromeos/chromeos.h>
+#include <symbols.h>
+
+#define RESERVED_SIZE_KB (1 * KiB)
+
+static void soc_enable(device_t dev)
+{
+	/* Reserve bottom 1M bytes for MMU/TTB */
+	reserved_ram_resource(dev, 0, ((uintptr_t)_dram / KiB +
+	    (CONFIG_DRAM_SIZE_MB * KiB - RESERVED_SIZE_KB)),
+	    RESERVED_SIZE_KB);
+	ram_resource(dev, 0, (uintptr_t)_dram / KiB,
+		     (CONFIG_DRAM_SIZE_MB * KiB) - RESERVED_SIZE_KB);
+}
+
+static void soc_init(device_t dev)
+{
+	printk(BIOS_INFO, "CPU: Armada 38X\n");
+}
+
+static struct device_operations soc_ops = {
+	.read_resources = DEVICE_NOOP,
+	.set_resources = DEVICE_NOOP,
+	.enable_resources = soc_enable,
+	.init = soc_init,
+	.scan_bus = 0,
+};
+
+static void enable_armada38x_dev(device_t dev)
+{
+	dev->ops = &soc_ops;
+}
+
+struct chip_operations soc_marvell_armada38x_ops = {
+	CHIP_NAME("SOC Marvell Armada 38x")
+	.enable_dev = enable_armada38x_dev,
+};
diff --git a/src/soc/marvell/armada38x/uart.c b/src/soc/marvell/armada38x/uart.c
new file mode 100644
index 0000000..740a782
--- /dev/null
+++ b/src/soc/marvell/armada38x/uart.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google Inc.
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arch/io.h>
+#include <console/uart.h>
+#include <console/console.h>
+#include <drivers/uart/uart8250reg.h>
+#include <boot/coreboot_tables.h>
+#include <stdint.h>
+#include <assert.h>
+#include <soc/common.h>
+
+struct armada38x_uart {
+	union {
+		uint32_t thr; // Transmit holding register.
+		uint32_t rbr; // Receive buffer register.
+		uint32_t dll; // Divisor latch lsb.
+	};
+	union {
+		uint32_t ier; // Interrupt enable register.
+		uint32_t dlm; // Divisor latch msb.
+	};
+	union {
+		uint32_t iir; // Interrupt identification register.
+		uint32_t fcr; // FIFO control register.
+	};
+	uint32_t lcr; // Line control register.
+	uint32_t mcr; // Modem control register.
+	uint32_t lsr; // Line status register.
+	uint32_t msr; // Modem status register.
+} __attribute__ ((packed));
+
+static void armada38x_uart_tx_flush(struct armada38x_uart *uart_ptr);
+static int armada38x_uart_tst_byte(struct armada38x_uart *uart_ptr);
+
+static void armada38x_uart_init(struct armada38x_uart *uart_ptr)
+{
+	const uint8_t line_config = UART8250_LCR_WLS_8;
+	uint16_t divisor = (u16) uart_baudrate_divisor(default_baudrate(),
+		uart_platform_refclk(), 16);
+
+	armada38x_uart_tx_flush(uart_ptr);
+	// Disable interrupts.
+	write8(&uart_ptr->ier, 0);
+	// Enable access to divisor latches.
+	write8(&uart_ptr->lcr, UART8250_LCR_DLAB);
+	// Set the divisor.
+	write8(&uart_ptr->dll, divisor & 0xff);
+	write8(&uart_ptr->dlm, (divisor >> 8) & 0xff);
+	// Hide divisor latches and program line config.
+	write8(&uart_ptr->lcr, line_config);
+	// Enable FIFOs, and clear receive and transmit.
+	write8(&uart_ptr->fcr, UART8250_FCR_FIFO_EN | UART8250_FCR_CLEAR_RCVR |
+				   UART8250_FCR_CLEAR_XMIT);
+}
+
+static void armada38x_uart_tx_byte(struct armada38x_uart *uart_ptr,
+					unsigned char data)
+{
+	while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE))
+		;
+	write8(&uart_ptr->thr, data);
+}
+
+static void armada38x_uart_tx_flush(struct armada38x_uart *uart_ptr)
+{
+	while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT))
+		;
+}
+
+static unsigned char armada38x_uart_rx_byte(struct armada38x_uart *uart_ptr)
+{
+	if (!armada38x_uart_tst_byte(uart_ptr))
+		return 0;
+	return read8(&uart_ptr->rbr);
+}
+
+static int armada38x_uart_tst_byte(struct armada38x_uart *uart_ptr)
+{
+	return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR;
+}
+
+unsigned int uart_platform_refclk(void)
+{
+	return MV_BOARD_TCLK_250MHZ;
+}
+
+uintptr_t uart_platform_base(int idx)
+{
+	/* Default to UART 0 */
+	unsigned int base = CONFIG_CONSOLE_SERIAL_UART_ADDRESS;
+
+	assert((idx >= 0) && (idx < 2));
+	base += idx * 0x100;
+	return base;
+}
+
+void uart_init(int idx)
+{
+	struct armada38x_uart *uart_ptr = uart_platform_baseptr(idx);
+
+	armada38x_uart_init(uart_ptr);
+}
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+	struct armada38x_uart *uart_ptr = uart_platform_baseptr(idx);
+
+	armada38x_uart_tx_byte(uart_ptr, data);
+}
+
+void uart_tx_flush(int idx)
+{
+	struct armada38x_uart *uart_ptr = uart_platform_baseptr(idx);
+
+	armada38x_uart_tx_flush(uart_ptr);
+}
+
+unsigned char uart_rx_byte(int idx)
+{
+	struct armada38x_uart *uart_ptr = uart_platform_baseptr(idx);
+
+	return armada38x_uart_rx_byte(uart_ptr);
+}
+
+#if ENV_RAMSTAGE
+void uart_fill_lb(void *data)
+{
+	struct lb_serial serial;
+
+	serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
+	serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
+	serial.baud = default_baudrate();
+	serial.regwidth = 1;
+	lb_add_serial(&serial, data);
+
+	lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
+}
+#endif



More information about the coreboot-gerrit mailing list