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@chromium.org>
Original-Commit-Id: e91cc19468325f005c6ac920bbe27a174c409727
Original-Change-Id: Iac5fc34df1ba18b4515029aa2fcff8f78a5df191
Original-Signed-off-by: Ruilin Hao <rlhao@marvell.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/313179
Original-Commit-Ready: Kan Yan <kyan@google.com>
Original-Tested-by: Kan Yan <kyan@google.com>
Original-Reviewed-by: Kan Yan <kyan@google.com>
Reviewed-on: https://review.coreboot.org/13110
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Ruilin Hao 2015-11-09 22:37:09 -08:00 committed by Patrick Georgi
parent 0e06f5bd70
commit 2c8b0b1373
11 changed files with 828 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,176 @@
/*
* 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.
*/
#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();
}

View File

@ -0,0 +1,123 @@
/*
* 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.
*/
#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)

View File

@ -0,0 +1,22 @@
/*
* 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.
*/
#include <cbmem.h>
#include <soc/soc_services.h>
void *cbmem_top(void)
{
return (void *)_memlayout_cbmem_top;
}

View File

@ -0,0 +1,128 @@
/*
* 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.
*/
#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__

View File

@ -0,0 +1,34 @@
/*
* 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.
*/
#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)
}

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
#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_*/

View File

@ -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.
*/
#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);
}

View File

@ -0,0 +1,55 @@
/*
* 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.
*/
#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,
};

View File

@ -0,0 +1,151 @@
/*
* 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.
*/
#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