[platform] add zybo and vexpress-a9 support for the VM

This commit is contained in:
Travis Geiselbrecht
2014-07-11 18:07:40 -07:00
parent 25a78c5225
commit 184cac4a0f
8 changed files with 284 additions and 35 deletions

View File

@@ -24,7 +24,7 @@
#include <platform/vexpress-a9.h>
#define GICBASE(n) (CPUPRIV_BASE)
#define GICBASE(n) (CPUPRIV_BASE_VIRT)
#define GICC_OFFSET (0x0100)
#define GICD_OFFSET (0x1000)

View File

@@ -23,22 +23,37 @@
#pragma once
/* memory map of the motherboard */
#define MOTHERBOARD_CS0 (0x40000000)
#define MOTHERBOARD_CS1 (0x44000000)
#define MOTHERBOARD_CS2 (0x48000000)
#define MOTHERBOARD_CS3 (0x4c000000)
#define MOTHERBOARD_CS4 (0x50000000)
#define MOTHERBOARD_CS5 (0x54000000)
#define MOTHERBOARD_CS6 (0x58000000)
#define MOTHERBOARD_CS7 (0x10000000)
#define MOTHERBOARD_CS0_PHYS (0x40000000)
#define MOTHERBOARD_CS1_PHYS (0x44000000)
#define MOTHERBOARD_CS2_PHYS (0x48000000)
#define MOTHERBOARD_CS3_PHYS (0x4c000000)
#define MOTHERBOARD_CS4_PHYS (0x50000000)
#define MOTHERBOARD_CS5_PHYS (0x54000000)
#define MOTHERBOARD_CS6_PHYS (0x58000000)
#define MOTHERBOARD_CS7_PHYS (0x10000000)
#define MOTHERBOARD_CS_SIZE (0x04000000)
#define MOTHERBOARD_CS0_VIRT (0xe0000000)
#define MOTHERBOARD_CS1_VIRT (0xe4000000)
#define MOTHERBOARD_CS2_VIRT (0xe8000000)
#define MOTHERBOARD_CS3_VIRT (0xec000000)
#define MOTHERBOARD_CS4_VIRT (0xf0000000)
#define MOTHERBOARD_CS5_VIRT (0xf4000000)
#define MOTHERBOARD_CS6_VIRT (0xf8000000)
#define MOTHERBOARD_CS7_VIRT (0xfc000000)
#define SDRAM_BASE (0x60000000)
#define SDRAM_APERTURE_SIZE (0x40000000)
/* most of the peripherals live on the motherboard CS7 */
#define UART0_BASE (MOTHERBOARD_CS7 + 0x9000)
#define UART1_BASE (MOTHERBOARD_CS7 + 0xa000)
#define UART2_BASE (MOTHERBOARD_CS7 + 0xb000)
#define UART3_BASE (MOTHERBOARD_CS7 + 0xc000)
#define UART0_BASE (MOTHERBOARD_CS7_VIRT + 0x9000)
#define UART1_BASE (MOTHERBOARD_CS7_VIRT + 0xa000)
#define UART2_BASE (MOTHERBOARD_CS7_VIRT + 0xb000)
#define UART3_BASE (MOTHERBOARD_CS7_VIRT + 0xc000)
#define CPUPRIV_BASE (0x1e000000)
#define CPUPRIV_SIZE (0x00100000)
#define CPUPRIV_BASE_PHYS (0x1e000000)
#define CPUPRIV_BASE_VIRT (MOTHERBOARD_CS0_VIRT - CPUPRIV_SIZE)
/* interrupts */
#define ARM_GENERIC_TIMER_INT 29

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012 Travis Geiselbrecht
* Copyright (c) 2012-2014 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -29,12 +29,62 @@
#include <dev/timer/arm_cortex_a9.h>
#include <dev/uart.h>
#include <lk/init.h>
#include <kernel/vm.h>
#include <platform.h>
#include <platform/gic.h>
#include <platform/interrupts.h>
#include <platform/vexpress-a9.h>
#include "platform_p.h"
#define SDRAM_SIZE (512*1024*1024) // XXX get this from the emulator somehow
/* initial memory mappings. parsed by start.S */
struct mmu_initial_mapping mmu_initial_mappings[] = {
/* 1GB of sdram space */
{ .phys = SDRAM_BASE,
.virt = KERNEL_BASE,
.size = SDRAM_SIZE,
.flags = 0,
.name = "memory" },
/* CS0 - CS6 devices */
{ .phys = MOTHERBOARD_CS0_PHYS,
.virt = MOTHERBOARD_CS0_VIRT,
.size = MOTHERBOARD_CS_SIZE * 7,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "cs0-cs6" },
/* CS7 devices */
{ .phys = MOTHERBOARD_CS7_PHYS,
.virt = MOTHERBOARD_CS7_VIRT,
.size = MOTHERBOARD_CS_SIZE,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "cs7" },
/* cortex-a9 private memory area */
{ .phys = CPUPRIV_BASE_PHYS,
.virt = CPUPRIV_BASE_VIRT,
.size = CPUPRIV_SIZE,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "cpu_priv"},
/* identity map to let the boot code run */
{ .phys = SDRAM_BASE,
.virt = SDRAM_BASE,
.size = 16*1024*1024,
.flags = MMU_INITIAL_MAPPING_TEMPORARY },
/* null entry to terminate the list */
{ 0 }
};
static pmm_arena_t arena = {
.name = "sdram",
.base = SDRAM_BASE,
.size = SDRAM_SIZE,
.flags = PMM_ARENA_FLAG_KMAP,
};
void platform_init_mmu_mappings(void)
{
}
@@ -45,9 +95,12 @@ void platform_early_init(void)
arm_gic_init();
/* initialize the timer block */
arm_cortex_a9_timer_init(CPUPRIV_BASE, 100000000);
arm_cortex_a9_timer_init(CPUPRIV_BASE_VIRT, 100000000);
uart_init_early();
/* add the main memory arena */
pmm_add_arena(&arena);
}
void platform_init(void)

View File

@@ -22,14 +22,15 @@
*/
#pragma once
#ifndef ASSEMBLY
#include <reg.h>
#include <stdbool.h>
#include <sys/types.h>
#endif
/* memory addresses */
#define SDRAM_BASE (0)
#define SDRAM_APERTURE_SIZE (0x40000000)
#define SRAM_BASE (0xfffc0000)
/* assumes sram is mapped at 0 the first MB of sdram is covered by it */
#define SDRAM_BASE (0x00100000)
#define SDRAM_APERTURE_SIZE (0x3ff00000)
#define SRAM_BASE (0x0)
#define SRAM_APERTURE_SIZE (0x00040000)
/* hardware base addresses */
@@ -104,7 +105,9 @@
#define SCL 0x00000000
#define SLCR_LOCK 0x00000004
#define SLCR_LOCK_KEY 0x767b
#define SLCR_UNLOCK 0x00000008
#define SLCR_UNLOCK_KEY 0xdf0d
#define SLCR_LOCKSTA 0x0000000c
#define ARM_PLL_CTRL 0x00000100
#define DDR_PLL_CTRL 0x00000104
@@ -265,6 +268,11 @@
#define DDRIOB_DCI_CTRL 0x00000B70
#define DDRIOB_DCI_STATU 0x00000B74
#ifndef ASSEMBLY
#include <stdbool.h>
#include <sys/types.h>
static inline void zynq_slcr_unlock(void) { SLCR_REG(SLCR_UNLOCK) = 0xdf0d; }
static inline void zynq_slcr_lock(void) { SLCR_REG(SLCR_LOCK) = 0x767b; }
@@ -306,4 +314,5 @@ enum zynq_periph {
status_t zynq_set_clock(enum zynq_periph, bool enable, enum zynq_clock_source, uint32_t divisor, uint32_t divisor2);
uint32_t zynq_get_clock(enum zynq_periph);
#endif

View File

@@ -24,6 +24,7 @@
#include <debug.h>
#include <stdio.h>
#include <arch/arm/mmu.h>
#include <kernel/vm.h>
#include <dev/uart.h>
#include <dev/interrupt/arm_gic.h>
#include <dev/timer/arm_cortex_a9.h>
@@ -34,14 +35,75 @@
/* target can specify this as the initial jam table to set up the soc */
__WEAK void ps7_init(void) { }
STATIC_ASSERT(IS_ALIGNED(SDRAM_BASE, MB));
STATIC_ASSERT(IS_ALIGNED(SDRAM_SIZE, MB));
/* initial memory mappings. parsed by start.S */
struct mmu_initial_mapping mmu_initial_mappings[] = {
/* 1GB of sram + sdram space */
{ .phys = SRAM_BASE,
.virt = KERNEL_BASE,
.size = MB + SDRAM_SIZE - MB,
.flags = 0,
.name = "memory" },
/* 0xe0000000 hardware devices */
{ .phys = 0xe0000000,
.virt = 0xe0000000,
.size = 0x00300000,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "hw" },
/* 0xe1000000 hardware devices */
{ .phys = 0xe1000000,
.virt = 0xe1000000,
.size = 0x05000000,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "hw" },
/* 0xf8000000 hardware devices */
{ .phys = 0xf8000000,
.virt = 0xf8000000,
.size = 0x01000000,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "hw" },
/* 0xfc000000 hardware devices */
{ .phys = 0xfc000000,
.virt = 0xfc000000,
.size = 0x02000000,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "hw" },
/* identity map to let the boot code run */
{ .phys = SRAM_BASE,
.virt = SRAM_BASE,
.size = MB,
.flags = MMU_INITIAL_MAPPING_TEMPORARY },
/* null entry to terminate the list */
{ 0 }
};
#if SDRAM_SIZE != 0
static pmm_arena_t sdram_arena = {
.name = "sdram",
.base = SDRAM_BASE,
.size = SDRAM_SIZE - MB,
.flags = PMM_ARENA_FLAG_KMAP
};
#endif
static pmm_arena_t sram_arena = {
.name = "sram",
.base = SRAM_BASE,
.size = MEMSIZE,
.priority = 1,
.flags = PMM_ARENA_FLAG_KMAP
};
void platform_init_mmu_mappings(void)
{
#define MB (1024*1024)
/* map dram as full cacheable */
for (addr_t a = SDRAM_BASE; a < (SDRAM_BASE + SDRAM_APERTURE_SIZE); a += MB) {
arm_mmu_map_section(a, a, MMU_MEMORY_L1_TYPE_NORMAL_WRITE_BACK_ALLOCATE | MMU_MEMORY_L1_AP_P_RW_U_NA);
}
}
void platform_early_init(void)
@@ -59,6 +121,21 @@ void platform_early_init(void)
/* initialize the timer block */
arm_cortex_a9_timer_init(CPUPRIV_BASE, zynq_get_arm_timer_freq());
/* add the main memory arena */
#if SDRAM_SIZE != 0
/* since we have a discontinuity between the end of SRAM (256K) and the start of SDRAM (1MB),
* intentionally bump the boot-time allocator to start in the base of SDRAM.
*/
extern uintptr_t boot_alloc_start;
extern uintptr_t boot_alloc_end;
boot_alloc_start = KERNEL_BASE + MB;
boot_alloc_end = KERNEL_BASE + MB;
pmm_add_arena(&sdram_arena);
#endif
pmm_add_arena(&sram_arena);
}
void platform_init(void)

View File

@@ -18,20 +18,27 @@ MODULE_SRCS += \
$(LOCAL_DIR)/clocks.c \
$(LOCAL_DIR)/debug.c \
$(LOCAL_DIR)/platform.c \
$(LOCAL_DIR)/start.S \
$(LOCAL_DIR)/uart.c \
$(LOCAL_DIR)/fpga.c
# default to no sdram unless the target calls it out
ZYNQ_SDRAM_SIZE ?= 0
ifeq ($(ZYNQ_USE_SRAM),1)
MEMBASE := 0x0
MEMSIZE ?= 0x40000 # 256KB
MEMSIZE := 0x30000 # 3 * 64K
else
MEMBASE := 0x0
MEMSIZE ?= 0x10000000 # 256MB
# XXX untested path
MEMBASE := 0x00000000
MEMSIZE ?= $(ZYNQ_SDRAM_SIZE) # 256MB
#KERNEL_LOAD_OFFSET := 0x00100000 # loaded 1MB into physical space
endif
GLOBAL_DEFINES += \
MEMBASE=$(MEMBASE) \
MEMSIZE=$(MEMSIZE)
MEMSIZE=$(MEMSIZE) \
SDRAM_SIZE=$(ZYNQ_SDRAM_SIZE)
LINKER_SCRIPT += \
$(BUILDDIR)/system-onesegment.ld

88
platform/zynq/start.S Normal file
View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2014 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <asm.h>
#include <platform/zynq.h>
/* this code attempts to remap sram to 0xfffc0000 - 0xffffffff and
branch the cpu into the equivalent spot. Assumes the cpu is running
at the initial 0 based mapping */
/* disabled for now */
#if 0
/* a spot of the top bank of OCM memory for us to run our code from
needs to be below where the second cpu is running (0xffffe00-0xfffffff0) */
#define TARGET_SPOT 0xfffff800
/* first piece of code run out of the reset vector. use
to relocate sram to the final location at 0xfffc0000
and switch to there */
FUNCTION(platform_reset)
/* relocate the below code to TARGET_SPOT */
ldr r8, =TARGET_SPOT
adr r9, .Lcore_reloc_start
adr r10, .Lcore_reloc_end
0:
ldr r12, [r9], #4
str r12, [r8], #4
cmp r9, r10
bne 0b
/* load constants we will need below */
ldr r8, =SLCR_BASE
ldr r9, =SCU_CONTROL_BASE
/* calculate the new return address this code will need to branch to */
adr r12, .Ldone
add r12, #0xfffc0000
ldr r10, =TARGET_SPOT
bx r10
.Ldone:
b arm_reset
.Lcore_reloc_start:
# use SCLR to map the sram blocks to the top of their segment
movw r10, #SLCR_UNLOCK_KEY
str r10, [r8, #SLCR_UNLOCK]
ldr r10, [r8, #OCM_CFG]
orr r10, #0xf
str r10, [r8, #OCM_CFG]
movw r10, #SLCR_LOCK_KEY
str r10, [r8, #SLCR_LOCK]
# tell the SCU to not filter first 1MB
mov r10, #0
str r10, [r9, #0x40] /* SCU filter start address */
dmb
bx r12
.Lcore_reloc_end:
.ltorg
#endif

View File

@@ -7,14 +7,14 @@ PLATFORM := zynq
# set the system base to sram
ZYNQ_USE_SRAM := 1
# we have sdram
ZYNQ_SDRAM_SIZE := 0x10000000
GLOBAL_INCLUDES += \
$(LOCAL_DIR)/include
GLOBAL_DEFINES += \
EXTERNAL_CLOCK_FREQ=50000000 \
WITH_STATIC_HEAP=1 \
HEAP_START=0x00100000 \
HEAP_LEN=0x1ff00000
EXTERNAL_CLOCK_FREQ=50000000
MODULE_SRCS += \
$(LOCAL_DIR)/target.c \