Merge branch master into pae

This commit is contained in:
Adrian Danis 2015-02-17 10:37:33 +11:00
commit a5e442a70e
21 changed files with 827 additions and 22 deletions

View file

@ -163,6 +163,13 @@ config ARCH_IA32
depends on ARCH_I386
help
Support for PC99 based platform
config PLAT_ALLWINNERA20
bool "ALLWINNERA20 (CUBIETRUCK)"
depends on ARCH_ARM
depends on ARM_CORTEX_A15
help
Support for ALLWINNERA20 platform (CUBIETRUCK).
endchoice
source "$KERNEL_PATH/src/plat/pc99/Kconfig"
@ -250,7 +257,7 @@ menu "seL4 System Parameters"
configuration.
config NUM_PRIORITIES
int "Numer of priority levels"
int "Number of priority levels"
default 256
help
The number of priority levels per domain

View file

@ -17,7 +17,7 @@
ARCH_LIST:=arm ia32
CPU_LIST:=arm1136jf-s ixp420 cortex-a8 cortex-a9 cortex-a15
PLAT_LIST:=imx31 pc99 ixp420 omap3 am335x exynos4 exynos5 imx6 apq8064 zynq7000
PLAT_LIST:=imx31 pc99 ixp420 omap3 am335x exynos4 exynos5 imx6 apq8064 zynq7000 allwinnerA20
ARMV_LIST:=armv6 armv7-a
ifndef SOURCE_ROOT
@ -354,10 +354,12 @@ ASFLAGS += -Wa,-mcpu=${CPU} -Wa,-march=${ARMV}
DEFINES += -D$(shell echo ${ARMV}|tr [:lower:] [:upper:]|tr - _)
ifeq (${CPU},cortex-a8)
DEFINES += -DARM_CORTEX_A8
else
endif
ifeq (${CPU},cortex-a9)
DEFINES += -DARM_CORTEX_A9
endif
ifeq (${CPU},cortex-a15)
DEFINES += -DARM_CORTEX_A15
endif
endif

View file

@ -0,0 +1,11 @@
#
# Copyright 2015, DornerWorks, Ltd.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(GD_GPL)
#
include ${SOURCE_ROOT}/include/plat/${PLAT}/plat/machine/Makefile

View file

@ -0,0 +1,151 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#ifndef __PLAT_MACHINE_H
#define __PLAT_MACHINE_H
#include <arch/machine/gic_pl390.h>
#define N_INTERRUPTS 122
enum IRQConstants {
SGI_0 = 0,
SGI_1 = 1,
SGI_2 = 2,
SGI_3 = 3,
SGI_4 = 4,
SGI_5 = 5,
SGI_6 = 6,
SGI_7 = 7,
SGI_8 = 8,
SGI_9 = 9,
SGI_10 = 10,
SGI_11 = 11,
SGI_12 = 12,
SGI_13 = 13,
SGI_14 = 14,
SGI_15 = 15,
PPI_0 = 16,
PPI_1 = 17,
PPI_2 = 18,
PPI_3 = 19,
PPI_4 = 20,
PPI_5 = 21,
PPI_6 = 22,
PPI_7 = 23,
PPI_8 = 24,
PPI_9 = 25,
PPI_10 = 26,
PPI_11 = 27,
PPI_12 = 28,
PPI_13 = 29,
PPI_14 = 30,
PPI_15 = 31,
NMI = 32,
UART_0 = 33,
UART_1 = 34,
UART_2 = 35,
UART_3 = 36,
IR_0 = 37,
IR_1 = 38,
TWI_0 = 39,
TWI_1 = 40,
TWI_2 = 41,
SPI_0 = 42,
SPI_1 = 43,
SPI_2 = 44,
OWA = 45,
AC97 = 46,
TS = 47,
IIS0 = 48,
UART_4 = 49,
UART_5 = 50,
UART_6 = 51,
UART_7 = 52,
KEYPAD = 53,
TIMER_0 = 54,
TIMER_1 = 55,
TIMER_2 = 56,
TIMER_3 = 57,
CAN = 58,
DMA = 59,
PIO = 60,
TOUCH_PANEL = 61,
AUDIO_CODEC = 62,
LRADC = 63,
MMC_0 = 64,
MMC_1 = 65,
MMC_2 = 66,
MMC_3 = 67,
MS = 68,
NAND = 69,
USB_0 = 70,
USB_1 = 71,
USB_2 = 72,
SCR = 73,
CSI_0 = 74,
CSI_1 = 75,
LCD_0 = 76,
LCD_1 = 77,
MP = 78,
DE_FE0 = 79,
DE_FE1 = 80,
PMU = 81,
SPI3 = 82,
RESERVED_IRQ01 = 83,
RESERVED_IRQ02 = 84,
VE = 85,
SS = 86,
EMAC = 87,
SATA = 88,
RESERVED_IRQ03 = 89,
HDMI_0 = 90,
TVE = 91,
ACE = 92,
TVD = 93,
PS2_0 = 94,
PS2_1 = 95,
USB_3 = 96,
USB_4 = 97,
PLE = 98,
TIMER_4 = 99,
TIMER_5 = 100,
GPU_GP = 101,
GPU_GPMMU = 102,
GPU_PP0 = 103,
GPU_PPMMU0 = 104,
GPU_PMU = 105,
GPU_PP1 = 106,
GPU_PPMMU1 = 107,
GPU_RSV0 = 108,
GPU_RSV1 = 109,
GPU_RSV2 = 110,
GPU_RSV3 = 111,
GPU_RSV4 = 112,
HS_TIMER_0 = 113,
HS_TIMER_1 = 114,
HS_TIMER_2 = 115,
HS_TIMER_3 = 116,
GMAC = 117,
HDMI_1 = 118,
IIS1 = 119,
TWI_3 = 120,
TWI_4 = 121,
IIS_2 = 122,
maxIRQ = 122
} platform_interrupt_t;
#define KERNEL_TIMER_IRQ TIMER_0
enum irqNumbers {
irqInvalid = 255
};
#endif /* ! __PLAT_MACHINE_H */

View file

@ -0,0 +1,13 @@
#
# Copyright 2015, DornerWorks, Ltd.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(GD_GPL)
#
DIRECTORIES += plat/machine
BF_SOURCES += plat/machine/hardware.bf

View file

@ -0,0 +1,17 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#ifndef __PLAT_MACHINE_DEBUG_HELPERS_H
#define __PLAT_MACHINE_DEBUG_HELPERS_H
#include <plat/machine/io.h>
#endif

View file

@ -0,0 +1,47 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
/*
definitions for memory addresses of allwinner A20 platform
listed in the order of ascending memory address, similar to the datasheet
the size must all be powers of 2 and page aligned (4k or 1M).
*/
#ifndef __PLAT_MACHINE_DEVICES_H
#define __PLAT_MACHINE_DEVICES_H
/* These devices are used by the seL4 kernel. */
#define UART0_PPTR 0xfff01000
#define TIMER0_PPTR 0xfff02000
#define GIC_DISTRIBUTOR_PPTR 0xfff03000
#define GIC_CONTROLLER_PPTR 0xfff04000
#define GIC_PL390_CONTROLLER_PPTR GIC_CONTROLLER_PPTR
#define GIC_PL390_DISTRIBUTOR_PPTR GIC_DISTRIBUTOR_PPTR
#define GIC_DISTRIBUTOR_PADDR GIC_PADDR + 0x1000
#define GIC_CONTROLLER0_PADDR GIC_PADDR + 0x2000
#define UART0_PADDR 0x01C28000
/* CCU, Interrupt, Timer, OWA */
/* Timer = PPTR + 0xC00 */
#define TIMER0_PADDR 0x01C20000
#define GIC_PADDR 0x01C80000
/* TODO: Add other devices PADDRs */
#define SPI0_PADDR 0x01C05000
#define SPI1_PADDR 0x01C06000
#endif

View file

@ -0,0 +1,12 @@
--
-- Copyright 2015, DornerWorks, Ltd.
--
-- This software may be distributed and modified according to the terms of
-- the GNU General Public License version 2. Note that NO WARRANTY is provided.
-- See "LICENSE_GPLv2.txt" for details.
--
-- @TAG(GD_GPL)
--
base 32

View file

@ -0,0 +1,87 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#ifndef __PLAT_MACHINE_HARDWARE_H
#define __PLAT_MACHINE_HARDWARE_H
#define physBase 0x48000000
#define kernelBase 0xA0000000
#define physMappingOffset (kernelBase - physBase)
#define BASE_OFFSET physMappingOffset
#define PPTR_TOP 0xfff00000
#define PADDR_TOP (PPTR_TOP - BASE_OFFSET)
#ifndef __ASSEMBLER__
#include <types.h>
#include <arch/object/structures.h>
#include <plat/machine.h>
#include <plat/machine/hardware_gen.h>
static inline void* CONST
ptrFromPAddr(paddr_t paddr)
{
return (void*)(paddr + physMappingOffset);
}
static inline paddr_t CONST
addrFromPPtr(void* pptr)
{
return (paddr_t)pptr - physMappingOffset;
}
#define paddr_to_pptr ptrFromPAddr
#define pptr_to_paddr addrFromPPtr
static inline region_t CONST
paddr_to_pptr_reg(p_region_t p_reg)
{
return (region_t) {
p_reg.start + physMappingOffset, p_reg.end + physMappingOffset
};
}
static inline p_region_t CONST
pptr_to_paddr_reg(region_t reg)
{
return (p_region_t) {
reg.start - physMappingOffset, reg.end - physMappingOffset
};
}
int get_num_avail_p_regs(void);
p_region_t get_avail_p_reg(unsigned int i);
int get_num_dev_p_regs(void);
p_region_t get_dev_p_reg(unsigned int i);
void map_kernel_devices(void);
bool_t CONST isReservedIRQ(irq_t irq);
void handleReservedIRQ(irq_t irq);
/** MODIFIES: [*] */
void resetTimer(void);
/** MODIFIES: [*] */
void initTimer(void);
/* L2 cache control */
/** MODIFIES: [*] */
void initL2Cache(void);
/** MODIFIES: [*] */
static inline void plat_cleanL2Range(paddr_t start, paddr_t end) {}
/** MODIFIES: [*] */
static inline void plat_invalidateL2Range(paddr_t start, paddr_t end) {}
/** MODIFIES: [*] */
static inline void plat_cleanInvalidateL2Range(paddr_t start, paddr_t end) {}
#endif /* !__ASSEMBLER__ */
#endif

View file

@ -0,0 +1,26 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#ifndef __PLAT_IO_H
#define __PLAT_IO_H
#include <types.h>
#ifdef DEBUG
void allwinnerA20_uart_putchar(char c);
void putDebugChar(unsigned char c);
unsigned char getDebugChar(void);
#define kernel_putchar(c) allwinnerA20_uart_putchar(c)
#else /* !DEBUG */
#define kernel_putchar(c) ((void)(0))
#endif
#endif

View file

@ -15,6 +15,8 @@
#define INTC_PPTR 0xfff01000
#define UART0_PPTR 0xfff02000
#define DMTIMER0_PPTR 0xfff03000
#define WDT1_PPTR 0xfff04000
/* Other devices on the SoC. */
#define INTC_PADDR 0x48200000
@ -26,5 +28,7 @@
#define DMTIMER5_PADDR 0x48046000
#define DMTIMER6_PADDR 0x48048000
#define DMTIMER7_PADDR 0x4804A000
#define WDT1_PADDR 0x44e35000
#endif

View file

@ -37,7 +37,7 @@ typedef seL4_CPtr seL4_ARM_PageDirectory;
typedef seL4_CPtr seL4_ARM_ASIDControl;
typedef seL4_CPtr seL4_ARM_ASIDPool;
typedef struct {
typedef struct seL4_UserContext_ {
/* frame registers */
seL4_Word pc, sp, cpsr, r0, r1, r8, r9, r10, r11, r12;
/* other integer registers */

View file

@ -50,7 +50,7 @@ typedef seL4_CPtr seL4_IA32_IOPageTable;
/* User context as used by seL4_TCB_ReadRegisters / seL4_TCB_WriteRegisters */
typedef struct {
typedef struct seL4_UserContext_ {
/* frameRegisters */
seL4_Word eip, esp, eflags, eax, ebx, ecx, edx, esi, edi, ebp;
/* gpRegisters */

View file

@ -276,7 +276,7 @@ initL2Cache(void)
| CTRL_AUX_ASSOCIATIVITY_16WAY
| CTRL_AUS_REPLPOLICY_RROBIN;
#if defined(EXYNOS4) || defined(IMX6) || defined(PLAT_ZYNQ7000)
#if defined(EXYNOS4) || defined(IMX6) || defined(PLAT_ZYNQ7000) || defined(PLAT_ALLWINNERA20)
aux |= CTRL_AUX_WAYSIZE_64K;
#elif defined(OMAP4)
aux |= CTRL_AUX_WAYSIZE_32K;

11
src/plat/allwinnerA20/Makefile Executable file
View file

@ -0,0 +1,11 @@
#
# Copyright 2015, DornerWorks, Ltd.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(GD_GPL)
#
include ${SOURCE_ROOT}/src/plat/allwinnerA20/machine/Makefile

View file

@ -0,0 +1,84 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
ENTRY(_start)
/* WARNING: constants also defined in plat/machine/hardware.h */
KERNEL_BASE = 0xA0000000;
PHYS_BASE = 0x48000000;
KERNEL_OFFSET = KERNEL_BASE - PHYS_BASE;
SECTIONS
{
. = KERNEL_BASE;
.boot . : AT(ADDR(.boot) - KERNEL_OFFSET)
{
*(.boot.text)
*(.boot.rodata)
*(.boot.data)
. = ALIGN(64K);
}
ki_boot_end = .;
.text . : AT(ADDR(.text) - KERNEL_OFFSET)
{
/* Sit inside a large frame */
. = ALIGN(64K);
*(.vectors)
/* Fastpath code */
*(.vectors.fastpath_call)
*(.vectors.fastpath_reply_wait)
*(.vectors.text)
/* Anything else that should be in the vectors page. */
*(.vectors.*)
/* Hopefully all that fits into 4K! */
/* Standard kernel */
*(.text)
}
.rodata . : AT(ADDR(.rodata) - KERNEL_OFFSET)
{
*(.rodata)
*(.rodata.*)
}
.data . : AT(ADDR(.data) - KERNEL_OFFSET)
{
*(.data)
}
.bss . : AT(ADDR(.bss) - KERNEL_OFFSET)
{
*(.bss)
/* 4k breakpoint stack */
_breakpoint_stack_bottom = .;
. = . + 4K;
_breakpoint_stack_top = .;
/* large data such as the globals frame and global PD */
*(.bss.aligned)
}
. = ALIGN(4K);
ki_end = .;
/DISCARD/ :
{
*(.note.gnu.build-id)
*(.comment)
}
}

View file

@ -0,0 +1,18 @@
#
# Copyright 2015, DornerWorks, Ltd.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(GD_GPL)
#
DIRECTORIES += src/plat/allwinnerA20/machine
PLAT_C_SOURCES += machine/hardware.c \
machine/l2cache.c
ifdef DEBUG
PLAT_C_SOURCES += machine/io.c
endif

View file

@ -0,0 +1,174 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#include <types.h>
#include <machine/io.h>
#include <kernel/vspace.h>
#include <arch/machine.h>
#include <arch/kernel/vspace.h>
#include <plat/machine.h>
#include <arch/linker.h>
#include <plat/machine/devices.h>
#include <plat/machine/hardware.h>
/* Available physical memory regions on platform (RAM minus kernel image). */
/* NOTE: Regions are not allowed to be adjacent! */
const p_region_t BOOT_RODATA avail_p_regs[] = {
/* 1408 MB */
{ .start = 0x48000000, .end = 0xA0000000 }
};
BOOT_CODE int get_num_avail_p_regs(void)
{
return sizeof(avail_p_regs) / sizeof(p_region_t);
}
BOOT_CODE p_region_t get_avail_p_reg(unsigned int i)
{
return avail_p_regs[i];
}
const p_region_t BOOT_RODATA dev_p_regs[] = {
/* sorted by increasing memory address */
/* region caps must be a power of 2. */
/* TODO: Add more devices. */
{ SPI0_PADDR , SPI0_PADDR + ( 2 << PAGE_BITS) },
{ SPI1_PADDR , SPI1_PADDR + ( 2 << PAGE_BITS) },
};
BOOT_CODE int get_num_dev_p_regs(void)
{
return sizeof(dev_p_regs) / sizeof(p_region_t);
}
BOOT_CODE p_region_t get_dev_p_reg(unsigned int i)
{
return dev_p_regs[i];
}
/* Determine if the given IRQ should be reserved by the kernel. */
bool_t CONST
isReservedIRQ(irq_t irq)
{
return irq == KERNEL_TIMER_IRQ ||
irq == RESERVED_IRQ01 ||
irq == RESERVED_IRQ02 ||
irq == RESERVED_IRQ03;
}
/* Handle a platform-reserved IRQ. */
void
handleReservedIRQ(irq_t irq)
{
printf("Received reserved IRQ: %d\n", (int)irq);
}
BOOT_CODE void
map_kernel_devices(void)
{
/* map kernel device: GP Timer 11 */
map_kernel_frame(
TIMER0_PADDR,
TIMER0_PPTR,
VMKernelOnly,
vm_attributes_new(
false, /* armExecuteNever */
false, /* armParityEnabled */
false /* armPageCacheable */
)
);
/* map kernel device: GIC */
map_kernel_frame(
GIC_CONTROLLER0_PADDR,
GIC_CONTROLLER_PPTR,
VMKernelOnly,
vm_attributes_new(
false, /* armExecuteNever */
false, /* armParityEnabled */
false /* armPageCacheable */
)
);
map_kernel_frame(
GIC_DISTRIBUTOR_PADDR,
GIC_DISTRIBUTOR_PPTR,
VMKernelOnly,
vm_attributes_new(
false, /* armExecuteNever */
false, /* armParityEnabled */
false /* armPageCacheable */
)
);
#ifdef DEBUG
/* map kernel device: UART */
map_kernel_frame(
UART0_PADDR,
UART0_PPTR,
VMKernelOnly,
vm_attributes_new(
false, /* armExecuteNever */
false, /* armParityEnabled */
false /* armPageCacheable */
)
);
#endif
}
#define TIMER_INTERVAL_US (CONFIG_TIMER_TICK_MS * 1000)
#define TIMER_MHZ 24ULL
#define TIMER_TICKS (TIMER_MHZ * TIMER_INTERVAL_US)
#define TIMER0_OFFSET 0xC00
#define TIMER_CTL_EN_FLAG BIT(0)
#define TIMER_CTL_RELOAD_FLAG BIT(1)
#define TMR0_IRQ_EN_FLAG BIT(0)
#define TMR0_IRQ_PEND_FLAG BIT(0)
static volatile struct TIMER_map {
uint32_t tmr_irq_en_reg; /* Timer IRQ Enable Register 0x00 */
uint32_t tmr_irq_sta_reg; /* Timer Status Register 0x04 */
uint32_t tmr_reserved01[2];
uint32_t tmr0_ctrl_reg; /* Timer 0 Control Register 0x10 */
uint32_t tmr0_intv_value_reg; /* Timer 0 Interval Value Register 0x14 */
uint32_t tmr0_cur_value_reg; /* Timer 0 Current Value Register 0x18 */
} *timer = (volatile void*)(TIMER0_PPTR + TIMER0_OFFSET);
/**
DONT_TRANSLATE
*/
void
resetTimer(void)
{
timer->tmr_irq_sta_reg = TMR0_IRQ_PEND_FLAG;
}
/* Configure gptimer11 as kernel preemption timer */
/**
DONT_TRANSLATE
*/
BOOT_CODE void
initTimer(void)
{
/* Set the reload value */
timer->tmr0_intv_value_reg = TIMER_TICKS;
/* Enables interrupt */
timer->tmr_irq_en_reg = TMR0_IRQ_EN_FLAG;
/* Set autoreload and start the timer */
timer->tmr0_ctrl_reg = TIMER_CTL_EN_FLAG | TIMER_CTL_RELOAD_FLAG;
}

View file

@ -0,0 +1,48 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#include <stdint.h>
#include <util.h>
#include <machine/io.h>
#include <plat/machine/devices.h>
#ifdef DEBUG
#define UTHR 0x00 /* UART Transmit Holding Register */
#define ULSR 0x14 /* UART Line Status Register */
#define ULSR_THRE 0x20 /* Transmit Holding Register Empty */
#define UART_REG(x) ((volatile uint32_t *)(UART0_PPTR + (x)))
void
allwinnerA20_uart_putchar(char c)
{
while ((*UART_REG(ULSR) & ULSR_THRE) == 0);
*UART_REG(UTHR) = c;
if (c == '\n') {
allwinnerA20_uart_putchar('\r');
}
}
void putDebugChar(unsigned char c)
{
while ((*UART_REG(ULSR) & ULSR_THRE) == 0);
*UART_REG(UTHR) = c;
}
unsigned char getDebugChar(void)
{
return 0;
}
#endif

View file

@ -0,0 +1,42 @@
/*
* Copyright 2015, DornerWorks, Ltd.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#include <arch/machine.h>
static inline word_t
readACR(void)
{
word_t ACR;
asm volatile ("mrc p15,0,%0,c1,c0,1" : "=r"(ACR));
return ACR;
}
static inline void
writeACR(word_t ACR)
{
asm volatile ("mcr p15,0,%0,c1,c0,1" : : "r"(ACR));
}
void
initL2Cache(void)
{
cleanInvalidateL1Caches();
/*
* Set the L2EN bit in the Auxially Control Register.
*
* We assume the C bit is already set in the system control register (from
* head.S), and that the L2 Cache Auxilliary Control Register is correct
* (as per reset).
*/
writeACR(readACR() | 0x2);
cleanInvalidateL1Caches();
}

View file

@ -51,6 +51,7 @@ const p_region_t BOOT_RODATA dev_p_regs[] = {
{ /* .start = */ DMTIMER5_PADDR, /* .end = */ DMTIMER5_PADDR + (1 << PAGE_BITS) },
{ /* .start = */ DMTIMER6_PADDR, /* .end = */ DMTIMER6_PADDR + (1 << PAGE_BITS) },
{ /* .start = */ DMTIMER7_PADDR, /* .end = */ DMTIMER7_PADDR + (1 << PAGE_BITS) },
{ /* .start = */ WDT1_PADDR, /* .end = */ WDT1_PADDR + (1 << PAGE_BITS) },
/* Board devices. */
/* TODO: This should ultimately be replaced with a more general solution. */
};
@ -93,6 +94,18 @@ map_kernel_devices(void)
)
);
/* map kernel device: WDT1 */
map_kernel_frame(
WDT1_PADDR,
WDT1_PPTR,
VMKernelOnly,
vm_attributes_new(
false, /* armExecuteNever */
false, /* armParityEnabled */
false /* armPageCacheable */
)
);
#ifdef DEBUG
/* map kernel device: UART */
map_kernel_frame(
@ -108,6 +121,12 @@ map_kernel_devices(void)
#endif
}
#define INTCPS_SYSCONFIG_SOFTRESET BIT(1)
#define INTCPS_SYSSTATUS_RESETDONE BIT(0)
#define INTCPS_CONTROL_NEWIRQAGR BIT(0)
#define INTCPS_SIR_IRQ_SPURIOUSIRQFLAG 0xffffff80
/*
* The struct below is used to discourage the compiler from generating literals
* for every single address we might access.
@ -136,11 +155,11 @@ volatile struct INTC_map {
uint32_t intcps_isr_clear;
uint32_t intcps_pending_irq;
uint32_t intcps_pending_fiq;
} intcps_n[3];
uint32_t padding5[8];
uint32_t intcps_ilr[96];
} intcps_n[4];
uint32_t intcps_ilr[128];
} *intc = (volatile void*)INTC_PPTR;
/**
DONT_TRANSLATE
*/
@ -148,23 +167,30 @@ volatile struct INTC_map {
interrupt_t
getActiveIRQ(void)
{
interrupt_t irq = intc->intcps_sir_irq;
uint32_t intcps_sir_irq = intc->intcps_sir_irq;
interrupt_t irq = (interrupt_t)(intcps_sir_irq & 0x7f);
/* Ignore spurious interrupts. */
if ((irq & ~0b1111111) == 0) {
assert(irq <= maxIRQ);
if ((intcps_sir_irq & INTCPS_SIR_IRQ_SPURIOUSIRQFLAG) == 0) {
assert((irq / 32) < (sizeof intc->intcps_n / sizeof intc->intcps_n[0]));
if (intc->intcps_n[irq / 32].intcps_pending_irq & (1 << (irq & 31))) {
return irq;
} else {
/* XXX happening a lot for irq=66! */
}
} else {
/* XXX - should never happen? */
printf("spurious irq %d / %x\n", irq, intcps_sir_irq);
}
/* No interrupt. */
return 0xff;
return irqInvalid;
}
/* Check for pending IRQ */
bool_t isIRQPending(void)
{
return getActiveIRQ() != 0xff;
return getActiveIRQ() != irqInvalid;
}
/* Enable or disable irq according to the 'disable' flag. */
@ -174,6 +200,7 @@ bool_t isIRQPending(void)
void
maskInterrupt(bool_t disable, interrupt_t irq)
{
assert(irq <= maxIRQ);
if (disable) {
intc->intcps_n[irq / 32].intcps_mir_set = 1 << (irq & 31);
} else {
@ -185,22 +212,19 @@ maskInterrupt(bool_t disable, interrupt_t irq)
bool_t
isReservedIRQ(interrupt_t irq)
{
return false;
return irq == KERNEL_TIMER_IRQ;
}
/* Handle a platform-reserved IRQ. */
void handleReservedIRQ(irq_t irq)
{
/* We shouldn't be receiving any reserved IRQs anyway. */
maskInterrupt(true, irq);
return;
printf("Received reserved IRQ: %d\n", (int)irq);
}
void
ackInterrupt(irq_t irq)
{
intc->intcps_control = 1;
intc->intcps_control = INTCPS_CONTROL_NEWIRQAGR;
/* Ensure the ack has hit the interrupt controller before potentially
* re-enabling interrupts. */
dsb();
@ -255,6 +279,27 @@ resetTimer(void)
ackInterrupt(DMTIMER0_IRQ);
}
#define WDT_REG(base, off) ((volatile uint32_t *)((base) + (off)))
#define WDT_REG_WWPS 0x34
#define WDT_REG_WSPR 0x48
#define WDT_WWPS_PEND_WSPR BIT(4)
static BOOT_CODE void
disableWatchdog(void)
{
uint32_t wdt = WDT1_PPTR;
// am335x ref man, sec 20.4.3.8
*WDT_REG(wdt, WDT_REG_WSPR) = 0xaaaa;
while ((*WDT_REG(wdt, WDT_REG_WWPS) & WDT_WWPS_PEND_WSPR)) {
continue;
}
*WDT_REG(wdt, WDT_REG_WSPR) = 0x5555;
while ((*WDT_REG(wdt, WDT_REG_WWPS) & WDT_WWPS_PEND_WSPR)) {
continue;
}
}
/* Configure dmtimer0 as kernel preemption timer */
/**
DONT_TRANSLATE
@ -264,11 +309,14 @@ initTimer(void)
{
int timeout;
disableWatchdog();
timer->cfg = TIOCP_CFG_SOFTRESET;
for (timeout = 10000; (timer->cfg & TIOCP_CFG_SOFTRESET) && timeout > 0; timeout--)
;
if (!timeout) {
printf("init timer failed\n");
return;
}
@ -293,12 +341,15 @@ initTimer(void)
BOOT_CODE void
initIRQController(void)
{
/* Do nothing */
intc->intcps_sysconfig = INTCPS_SYSCONFIG_SOFTRESET;
while (!(intc->intcps_sysstatus & INTCPS_SYSSTATUS_RESETDONE)) ;
}
void
handleSpuriousIRQ(void)
{
/* Do nothing */
/* Reset and re-enable IRQs. */
intc->intcps_control = INTCPS_CONTROL_NEWIRQAGR;
dsb();
}