[target][raspberry pi 2] add preliminary support for raspberry pi 2

-add support for the bcm2835 family (-36 variant in this case)
-add target and project for raspberry pi 2
This commit is contained in:
Travis Geiselbrecht
2015-03-02 01:55:08 -08:00
parent f55d8edd74
commit 239d66cfe6
8 changed files with 774 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2015 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.
*/
#pragma once
#define SDRAM_BASE 0
#define BCM_PERIPH_BASE_PHYS (0x3f000000U)
#define BCM_PERIPH_SIZE (0x01100000U)
#define BCM_PERIPH_BASE_VIRT (0xe0000000U)
/* pointer to 'local' peripherals at 0x40000000 */
#define BCM_LOCAL_PERIPH_BASE_VIRT (BCM_PERIPH_BASE_VIRT + 0x01000000)
#define IC0_BASE (BCM_PERIPH_BASE_VIRT + 0x2000)
#define ST_BASE (BCM_PERIPH_BASE_VIRT + 0x3000)
#define MPHI_BASE (BCM_PERIPH_BASE_VIRT + 0x6000)
#define DMA_BASE (BCM_PERIPH_BASE_VIRT + 0x7000)
#define ARM_BASE (BCM_PERIPH_BASE_VIRT + 0xB000)
#define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000)
#define PCM_CLOCK_BASE (BCM_PERIPH_BASE_VIRT + 0x101098)
#define RNG_BASE (BCM_PERIPH_BASE_VIRT + 0x104000)
#define GPIO_BASE (BCM_PERIPH_BASE_VIRT + 0x200000)
#define UART0_BASE (BCM_PERIPH_BASE_VIRT + 0x201000)
#define MMCI0_BASE (BCM_PERIPH_BASE_VIRT + 0x202000)
#define I2S_BASE (BCM_PERIPH_BASE_VIRT + 0x203000)
#define SPI0_BASE (BCM_PERIPH_BASE_VIRT + 0x204000)
#define BSC0_BASE (BCM_PERIPH_BASE_VIRT + 0x205000)
#define UART1_BASE (BCM_PERIPH_BASE_VIRT + 0x215000)
#define EMMC_BASE (BCM_PERIPH_BASE_VIRT + 0x300000)
#define SMI_BASE (BCM_PERIPH_BASE_VIRT + 0x600000)
#define BSC1_BASE (BCM_PERIPH_BASE_VIRT + 0x804000)
#define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000)
#define MCORE_BASE (BCM_PERIPH_BASE_VIRT + 0x0000)
#define ARMCTRL_BASE (ARM_BASE + 0x000)
#define ARMCTRL_INTC_BASE (ARM_BASE + 0x200)
#define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400)
#define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800)
#define ARM_LOCAL_BASE (BCM_LOCAL_PERIPH_BASE_VIRT)
/* interrupts */
#define ARM_IRQ1_BASE 0
#define INTERRUPT_TIMER0 (ARM_IRQ1_BASE + 0)
#define INTERRUPT_TIMER1 (ARM_IRQ1_BASE + 1)
#define INTERRUPT_TIMER2 (ARM_IRQ1_BASE + 2)
#define INTERRUPT_TIMER3 (ARM_IRQ1_BASE + 3)
#define INTERRUPT_CODEC0 (ARM_IRQ1_BASE + 4)
#define INTERRUPT_CODEC1 (ARM_IRQ1_BASE + 5)
#define INTERRUPT_CODEC2 (ARM_IRQ1_BASE + 6)
#define INTERRUPT_VC_JPEG (ARM_IRQ1_BASE + 7)
#define INTERRUPT_ISP (ARM_IRQ1_BASE + 8)
#define INTERRUPT_VC_USB (ARM_IRQ1_BASE + 9)
#define INTERRUPT_VC_3D (ARM_IRQ1_BASE + 10)
#define INTERRUPT_TRANSPOSER (ARM_IRQ1_BASE + 11)
#define INTERRUPT_MULTICORESYNC0 (ARM_IRQ1_BASE + 12)
#define INTERRUPT_MULTICORESYNC1 (ARM_IRQ1_BASE + 13)
#define INTERRUPT_MULTICORESYNC2 (ARM_IRQ1_BASE + 14)
#define INTERRUPT_MULTICORESYNC3 (ARM_IRQ1_BASE + 15)
#define INTERRUPT_DMA0 (ARM_IRQ1_BASE + 16)
#define INTERRUPT_DMA1 (ARM_IRQ1_BASE + 17)
#define INTERRUPT_VC_DMA2 (ARM_IRQ1_BASE + 18)
#define INTERRUPT_VC_DMA3 (ARM_IRQ1_BASE + 19)
#define INTERRUPT_DMA4 (ARM_IRQ1_BASE + 20)
#define INTERRUPT_DMA5 (ARM_IRQ1_BASE + 21)
#define INTERRUPT_DMA6 (ARM_IRQ1_BASE + 22)
#define INTERRUPT_DMA7 (ARM_IRQ1_BASE + 23)
#define INTERRUPT_DMA8 (ARM_IRQ1_BASE + 24)
#define INTERRUPT_DMA9 (ARM_IRQ1_BASE + 25)
#define INTERRUPT_DMA10 (ARM_IRQ1_BASE + 26)
#define INTERRUPT_DMA11 (ARM_IRQ1_BASE + 27)
#define INTERRUPT_DMA12 (ARM_IRQ1_BASE + 28)
#define INTERRUPT_AUX (ARM_IRQ1_BASE + 29)
#define INTERRUPT_ARM (ARM_IRQ1_BASE + 30)
#define INTERRUPT_VPUDMA (ARM_IRQ1_BASE + 31)
#define ARM_IRQ2_BASE 32
#define INTERRUPT_HOSTPORT (ARM_IRQ2_BASE + 0)
#define INTERRUPT_VIDEOSCALER (ARM_IRQ2_BASE + 1)
#define INTERRUPT_CCP2TX (ARM_IRQ2_BASE + 2)
#define INTERRUPT_SDC (ARM_IRQ2_BASE + 3)
#define INTERRUPT_DSI0 (ARM_IRQ2_BASE + 4)
#define INTERRUPT_AVE (ARM_IRQ2_BASE + 5)
#define INTERRUPT_CAM0 (ARM_IRQ2_BASE + 6)
#define INTERRUPT_CAM1 (ARM_IRQ2_BASE + 7)
#define INTERRUPT_HDMI0 (ARM_IRQ2_BASE + 8)
#define INTERRUPT_HDMI1 (ARM_IRQ2_BASE + 9)
#define INTERRUPT_PIXELVALVE1 (ARM_IRQ2_BASE + 10)
#define INTERRUPT_I2CSPISLV (ARM_IRQ2_BASE + 11)
#define INTERRUPT_DSI1 (ARM_IRQ2_BASE + 12)
#define INTERRUPT_PWA0 (ARM_IRQ2_BASE + 13)
#define INTERRUPT_PWA1 (ARM_IRQ2_BASE + 14)
#define INTERRUPT_CPR (ARM_IRQ2_BASE + 15)
#define INTERRUPT_SMI (ARM_IRQ2_BASE + 16)
#define INTERRUPT_GPIO0 (ARM_IRQ2_BASE + 17)
#define INTERRUPT_GPIO1 (ARM_IRQ2_BASE + 18)
#define INTERRUPT_GPIO2 (ARM_IRQ2_BASE + 19)
#define INTERRUPT_GPIO3 (ARM_IRQ2_BASE + 20)
#define INTERRUPT_VC_I2C (ARM_IRQ2_BASE + 21)
#define INTERRUPT_VC_SPI (ARM_IRQ2_BASE + 22)
#define INTERRUPT_VC_I2SPCM (ARM_IRQ2_BASE + 23)
#define INTERRUPT_VC_SDIO (ARM_IRQ2_BASE + 24)
#define INTERRUPT_VC_UART (ARM_IRQ2_BASE + 25)
#define INTERRUPT_SLIMBUS (ARM_IRQ2_BASE + 26)
#define INTERRUPT_VEC (ARM_IRQ2_BASE + 27)
#define INTERRUPT_CPG (ARM_IRQ2_BASE + 28)
#define INTERRUPT_RNG (ARM_IRQ2_BASE + 29)
#define INTERRUPT_VC_ARASANSDIO (ARM_IRQ2_BASE + 30)
#define INTERRUPT_AVSPMON (ARM_IRQ2_BASE + 31)
/* ARM interrupts, which are mostly mirrored from bank 1 and 2 */
#define ARM_IRQ0_BASE 64
#define INTERRUPT_ARM_TIMER (ARM_IRQ0_BASE + 0)
#define INTERRUPT_ARM_MAILBOX (ARM_IRQ0_BASE + 1)
#define INTERRUPT_ARM_DOORBELL_0 (ARM_IRQ0_BASE + 2)
#define INTERRUPT_ARM_DOORBELL_1 (ARM_IRQ0_BASE + 3)
#define INTERRUPT_VPU0_HALTED (ARM_IRQ0_BASE + 4)
#define INTERRUPT_VPU1_HALTED (ARM_IRQ0_BASE + 5)
#define INTERRUPT_ILLEGAL_TYPE0 (ARM_IRQ0_BASE + 6)
#define INTERRUPT_ILLEGAL_TYPE1 (ARM_IRQ0_BASE + 7)
#define INTERRUPT_PENDING1 (ARM_IRQ0_BASE + 8)
#define INTERRUPT_PENDING2 (ARM_IRQ0_BASE + 9)
#define INTERRUPT_JPEG (ARM_IRQ0_BASE + 10)
#define INTERRUPT_USB (ARM_IRQ0_BASE + 11)
#define INTERRUPT_3D (ARM_IRQ0_BASE + 12)
#define INTERRUPT_DMA2 (ARM_IRQ0_BASE + 13)
#define INTERRUPT_DMA3 (ARM_IRQ0_BASE + 14)
#define INTERRUPT_I2C (ARM_IRQ0_BASE + 15)
#define INTERRUPT_SPI (ARM_IRQ0_BASE + 16)
#define INTERRUPT_I2SPCM (ARM_IRQ0_BASE + 17)
#define INTERRUPT_SDIO (ARM_IRQ0_BASE + 18)
#define INTERRUPT_UART (ARM_IRQ0_BASE + 19)
#define INTERRUPT_ARASANSDIO (ARM_IRQ0_BASE + 20)
#define ARM_IRQ_LOCAL_BASE 96
#define INTERRUPT_ARM_LOCAL_CNTPSIRQ (ARM_IRQ_LOCAL_BASE + 0)
#define INTERRUPT_ARM_LOCAL_CNTPNSIRQ (ARM_IRQ_LOCAL_BASE + 1)
#define INTERRUPT_ARM_LOCAL_CNTHPIRQ (ARM_IRQ_LOCAL_BASE + 2)
#define INTERRUPT_ARM_LOCAL_CNTVIRQ (ARM_IRQ_LOCAL_BASE + 3)
#define INTERRUPT_ARM_LOCAL_MAILBOX0 (ARM_IRQ_LOCAL_BASE + 4)
#define INTERRUPT_ARM_LOCAL_MAILBOX1 (ARM_IRQ_LOCAL_BASE + 5)
#define INTERRUPT_ARM_LOCAL_MAILBOX2 (ARM_IRQ_LOCAL_BASE + 6)
#define INTERRUPT_ARM_LOCAL_MAILBOX3 (ARM_IRQ_LOCAL_BASE + 7)
#define INTERRUPT_ARM_LOCAL_GPU_FAST (ARM_IRQ_LOCAL_BASE + 8)
#define INTERRUPT_ARM_LOCAL_PMU_FAST (ARM_IRQ_LOCAL_BASE + 9)
#define INTERRUPT_ARM_LOCAL_ZERO (ARM_IRQ_LOCAL_BASE + 10)
#define INTERRUPT_ARM_LOCAL_TIMER (ARM_IRQ_LOCAL_BASE + 11)
#define MAX_INT INTERRUPT_ARM_LOCAL_TIMER

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2015 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.
*/
#pragma once
#include <platform/bcm2835.h>
#define GICBASE(n) (CPUPRIV_BASE_PHYS)
#define GICC_OFFSET (0x0100)
#define GICD_OFFSET (0x1000)

238
platform/bcm2835/intc.c Normal file
View File

@@ -0,0 +1,238 @@
/*
* Copyright (c) 2015 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 <trace.h>
#include <assert.h>
#include <err.h>
#include <bits.h>
#include <arch/arm.h>
#include <kernel/spinlock.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/bcm2835.h>
#define LOCAL_TRACE 0
/* global interrupt controller */
#define INTC_PEND0 (ARMCTRL_INTC_BASE + 0x0)
#define INTC_PEND1 (ARMCTRL_INTC_BASE + 0x4)
#define INTC_PEND2 (ARMCTRL_INTC_BASE + 0x8)
#define INTC_FAST (ARMCTRL_INTC_BASE + 0xc)
#define INTC_ENABLE1 (ARMCTRL_INTC_BASE + 0x10)
#define INTC_ENABLE2 (ARMCTRL_INTC_BASE + 0x14)
#define INTC_ENABLE3 (ARMCTRL_INTC_BASE + 0x18)
#define INTC_DISABLE1 (ARMCTRL_INTC_BASE + 0x1c)
#define INTC_DISABLE2 (ARMCTRL_INTC_BASE + 0x20)
#define INTC_DISABLE3 (ARMCTRL_INTC_BASE + 0x24)
/* per-cpu local interrupt controller bits.
* each is repeated 4 times, one per cpu.
*/
#define INTC_LOCAL_TIMER_INT_CONTROL0 (ARM_LOCAL_BASE + 0x40)
#define INTC_LOCAL_TIMER_INT_CONTROL1 (ARM_LOCAL_BASE + 0x44)
#define INTC_LOCAL_TIMER_INT_CONTROL2 (ARM_LOCAL_BASE + 0x48)
#define INTC_LOCAL_TIMER_INT_CONTROL3 (ARM_LOCAL_BASE + 0x4c)
#define INTC_LOCAL_MAILBOX_INT_CONTROL0 (ARM_LOCAL_BASE + 0x40)
#define INTC_LOCAL_MAILBOX_INT_CONTROL1 (ARM_LOCAL_BASE + 0x44)
#define INTC_LOCAL_MAILBOX_INT_CONTROL2 (ARM_LOCAL_BASE + 0x48)
#define INTC_LOCAL_MAILBOX_INT_CONTROL3 (ARM_LOCAL_BASE + 0x4c)
#define INTC_LOCAL_IRQ_PEND0 (ARM_LOCAL_BASE + 0x60)
#define INTC_LOCAL_IRQ_PEND1 (ARM_LOCAL_BASE + 0x64)
#define INTC_LOCAL_IRQ_PEND2 (ARM_LOCAL_BASE + 0x68)
#define INTC_LOCAL_IRQ_PEND3 (ARM_LOCAL_BASE + 0x6c)
#define INTC_LOCAL_FIQ_PEND0 (ARM_LOCAL_BASE + 0x70)
#define INTC_LOCAL_FIQ_PEND1 (ARM_LOCAL_BASE + 0x74)
#define INTC_LOCAL_FIQ_PEND2 (ARM_LOCAL_BASE + 0x78)
#define INTC_LOCAL_FIQ_PEND3 (ARM_LOCAL_BASE + 0x7c)
struct int_handler_struct {
int_handler handler;
void *arg;
};
static struct int_handler_struct int_handler_table[MAX_INT][SMP_MAX_CPUS];
static spin_lock_t lock = SPIN_LOCK_INITIAL_VALUE;
status_t mask_interrupt(unsigned int vector)
{
LTRACEF("vector %u\n", vector);
spin_lock_saved_state_t state;
spin_lock_irqsave(&lock, state);
if (vector >= INTERRUPT_ARM_LOCAL_CNTPSIRQ && vector <= INTERRUPT_ARM_LOCAL_CNTVIRQ) {
// local timer interrupts
uint cpu = arch_curr_cpu_num();
uintptr_t reg = INTC_LOCAL_TIMER_INT_CONTROL0 + cpu * 4;
*REG32(reg) &= (1 << (vector - INTERRUPT_ARM_LOCAL_CNTPSIRQ));
} else if (/* vector >= ARM_IRQ1_BASE && */ vector < (ARM_IRQ0_BASE + 32)) {
uintptr_t reg;
if (vector >= ARM_IRQ0_BASE)
reg = INTC_DISABLE3;
else if (vector >= ARM_IRQ2_BASE)
reg = INTC_DISABLE2;
else
reg = INTC_DISABLE1;
*REG32(reg) = 1 << (vector % 32);
} else {
PANIC_UNIMPLEMENTED;
}
spin_unlock_irqrestore(&lock, state);
return NO_ERROR;
}
status_t unmask_interrupt(unsigned int vector)
{
LTRACEF("vector %u\n", vector);
spin_lock_saved_state_t state;
spin_lock_irqsave(&lock, state);
if (vector >= INTERRUPT_ARM_LOCAL_CNTPSIRQ && vector <= INTERRUPT_ARM_LOCAL_CNTVIRQ) {
// local timer interrupts
uint cpu = arch_curr_cpu_num();
uintptr_t reg = INTC_LOCAL_TIMER_INT_CONTROL0 + cpu * 4;
*REG32(reg) |= (1 << (vector - INTERRUPT_ARM_LOCAL_CNTPSIRQ));
} else if (/* vector >= ARM_IRQ1_BASE && */ vector < (ARM_IRQ0_BASE + 32)) {
uintptr_t reg;
if (vector >= ARM_IRQ0_BASE)
reg = INTC_ENABLE3;
else if (vector >= ARM_IRQ2_BASE)
reg = INTC_ENABLE2;
else
reg = INTC_ENABLE1;
*REG32(reg) = 1 << (vector % 32);
} else {
PANIC_UNIMPLEMENTED;
}
spin_unlock_irqrestore(&lock, state);
return NO_ERROR;
}
void register_int_handler(unsigned int vector, int_handler handler, void *arg)
{
uint cpu = arch_curr_cpu_num();
if (vector >= MAX_INT)
panic("register_int_handler: vector out of range %d\n", vector);
spin_lock_saved_state_t state;
spin_lock_irqsave(&lock, state);
int_handler_table[vector][cpu].handler = handler;
int_handler_table[vector][cpu].arg = arg;
spin_unlock_irqrestore(&lock, state);
}
enum handler_return platform_irq(struct arm_iframe *frame)
{
uint vector;
uint cpu = arch_curr_cpu_num();
THREAD_STATS_INC(interrupts);
// see what kind of irq it is
uint32_t pend = *REG32(INTC_LOCAL_IRQ_PEND0 + cpu * 4);
pend &= ~(1 << (INTERRUPT_ARM_LOCAL_GPU_FAST % 32)); // mask out gpu interrupts
if (pend != 0) {
// it's a local interrupt
LTRACEF("local pend 0x%x\n", pend);
vector = ARM_IRQ_LOCAL_BASE + ctz(pend);
goto decoded;
}
// XXX disable for now, since all of the interesting irqs are mirrored into the other banks
#if 0
// look in bank 0 (ARM interrupts)
pend = *REG32(INTC_PEND0);
LTRACEF("pend0 0x%x\n", pend);
pend &= ~((1<<8)|(1<<9)); // mask out bit 8 and 9
if (pend != 0) {
// it's a bank 0 interrupt
vector = ARM_IRQ0_BASE + ctz(pend);
goto decoded;
}
#endif
// look for VC interrupt bank 1
pend = *REG32(INTC_PEND1);
LTRACEF("pend1 0x%x\n", pend);
if (pend != 0) {
// it's a bank 1 interrupt
vector = ARM_IRQ1_BASE + ctz(pend);
goto decoded;
}
// look for VC interrupt bank 2
pend = *REG32(INTC_PEND2);
LTRACEF("pend2 0x%x\n", pend);
if (pend != 0) {
// it's a bank 2 interrupt
vector = ARM_IRQ2_BASE + ctz(pend);
goto decoded;
}
vector = 0xffffffff;
decoded:
LTRACEF("vector %u\n", vector);
// dispatch the irq
enum handler_return ret = INT_NO_RESCHEDULE;
if (int_handler_table[vector][cpu].handler) {
ret = int_handler_table[vector][cpu].handler(int_handler_table[vector][cpu].arg);
} else {
panic("irq %u fired on cpu %u but no handler set!\n", vector, cpu);
}
return ret;
}
enum handler_return platform_fiq(struct arm_iframe *frame)
{
PANIC_UNIMPLEMENTED;
}
void intc_init(void)
{
// mask everything
*REG32(INTC_DISABLE1) = 0xffffffff;
*REG32(INTC_DISABLE2) = 0xffffffff;
*REG32(INTC_DISABLE3) = 0xffffffff;
}

112
platform/bcm2835/platform.c Normal file
View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2015 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 <reg.h>
#include <err.h>
#include <debug.h>
#include <dev/uart.h>
#include <arch.h>
#include <arch/arm.h>
#include <arch/arm/mmu.h>
#include <lk/init.h>
#include <kernel/vm.h>
#include <kernel/spinlock.h>
#include <dev/timer/arm_generic.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/bcm2835.h>
//#include "platform_p.h"
extern void intc_init(void);
/* 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 = MEMSIZE,
.flags = 0,
.name = "memory" },
/* peripherals */
{ .phys = BCM_PERIPH_BASE_PHYS,
.virt = BCM_PERIPH_BASE_VIRT,
.size = BCM_PERIPH_SIZE,
.flags = MMU_INITIAL_MAPPING_FLAG_DEVICE,
.name = "bcm peripherals" },
/* 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 = MEMSIZE,
.flags = PMM_ARENA_FLAG_KMAP,
};
void platform_init_mmu_mappings(void)
{
}
void platform_early_init(void)
{
uart_init_early();
intc_init();
arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 1000000);
/* add the main memory arena */
pmm_add_arena(&arena);
}
void platform_init(void)
{
uart_init();
}
#define DEBUG_UART 0
void platform_dputc(char c)
{
if (c == '\n')
uart_putc(DEBUG_UART, '\r');
uart_putc(DEBUG_UART, c);
}
int platform_dgetc(char *c, bool wait)
{
int ret = uart_getc(DEBUG_UART, wait);
if (ret == -1)
return -1;
*c = ret;
return 0;
}

44
platform/bcm2835/rules.mk Normal file
View File

@@ -0,0 +1,44 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
ARCH := arm
ARM_CPU := cortex-a7
WITH_SMP := 0
MODULE_DEPS := \
dev/timer/arm_generic \
lib/cbuf
#lib/bio \
lib/cbuf \
lib/minip \
dev/interrupt/arm_gic \
dev/timer/arm_cortex_a9
GLOBAL_INCLUDES += \
$(LOCAL_DIR)/include
MODULE_SRCS += \
$(LOCAL_DIR)/intc.c \
$(LOCAL_DIR)/platform.c \
$(LOCAL_DIR)/uart.c \
# default to no sdram unless the target calls it out
ZYNQ_SDRAM_SIZE ?= 0
MEMBASE := 0x00000000
MEMSIZE ?= 0x10000000 # 256MB
KERNEL_LOAD_OFFSET := 0x00008000 # loaded 32KB into physical
# put our kernel at 0x80000000
KERNEL_BASE = 0x80000000
GLOBAL_DEFINES += \
MEMBASE=$(MEMBASE) \
MEMSIZE=$(MEMSIZE)
LINKER_SCRIPT += \
$(BUILDDIR)/system-onesegment.ld
include make/module.mk

158
platform/bcm2835/uart.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) 2015 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 <reg.h>
#include <stdio.h>
#include <trace.h>
#include <lib/cbuf.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/debug.h>
#include <platform/bcm2835.h>
/* TODO: extract this into a generic PL011 driver */
/* PL011 implementation */
#define UART_DR (0x00)
#define UART_RSR (0x04)
#define UART_TFR (0x18)
#define UART_ILPR (0x20)
#define UART_IBRD (0x24)
#define UART_FBRD (0x28)
#define UART_LCRH (0x2c)
#define UART_CR (0x30)
#define UART_IFLS (0x34)
#define UART_IMSC (0x38)
#define UART_TRIS (0x3c)
#define UART_TMIS (0x40)
#define UART_ICR (0x44)
#define UART_DMACR (0x48)
#define UARTREG(base, reg) (*REG32((base) + (reg)))
#define RXBUF_SIZE 16
#define NUM_UART 1
static cbuf_t uart_rx_buf[NUM_UART];
static inline uintptr_t uart_to_ptr(unsigned int n)
{
switch (n) {
default:
case 0: return UART0_BASE;
}
}
static enum handler_return uart_irq(void *arg)
{
bool resched = false;
uint port = (uint)arg;
uintptr_t base = uart_to_ptr(port);
/* read interrupt status and mask */
uint32_t isr = UARTREG(base, UART_TMIS);
if (isr & ((1<<6) | (1<<4))) { // rtmis, rxmis
UARTREG(base, UART_ICR) = (1<<4);
cbuf_t *rxbuf = &uart_rx_buf[port];
/* while fifo is not empty, read chars out of it */
while ((UARTREG(base, UART_TFR) & (1<<4)) == 0) {
char c = UARTREG(base, UART_DR);
cbuf_write_char(rxbuf, c, false);
resched = true;
}
}
return resched ? INT_RESCHEDULE : INT_NO_RESCHEDULE;
}
void uart_init(void)
{
for (size_t i = 0; i < NUM_UART; i++) {
// create circular buffer to hold received data
cbuf_initialize(&uart_rx_buf[i], RXBUF_SIZE);
// assumes interrupts are contiguous
register_int_handler(INTERRUPT_VC_UART + i, &uart_irq, (void *)i);
// clear all irqs
UARTREG(uart_to_ptr(i), UART_ICR) = 0x3ff;
// set fifo trigger level
UARTREG(uart_to_ptr(i), UART_IFLS) = 0; // 1/8 rxfifo, 1/8 txfifo
// enable rx interrupt
UARTREG(uart_to_ptr(i), UART_IMSC) = (1<<6)|(1<<4); // rtim, rxim
// enable receive
UARTREG(uart_to_ptr(i), UART_CR) |= (1<<9); // rxen
// enable interrupt
unmask_interrupt(INTERRUPT_VC_UART + i);
}
}
void uart_init_early(void)
{
for (size_t i = 0; i < NUM_UART; i++) {
UARTREG(uart_to_ptr(i), UART_CR) = (1<<8)|(1<<0); // tx_enable, uarten
}
}
int uart_putc(int port, char c)
{
uintptr_t base = uart_to_ptr(port);
/* spin while fifo is full */
while (UARTREG(base, UART_TFR) & (1<<5))
;
UARTREG(base, UART_DR) = c;
return 1;
}
int uart_getc(int port, bool wait)
{
cbuf_t *rxbuf = &uart_rx_buf[port];
char c;
if (cbuf_read_char(rxbuf, &c, wait) == 1)
return c;
return -1;
}
void uart_flush_tx(int port)
{
}
void uart_flush_rx(int port)
{
}
void uart_init_port(int port, uint baud)
{
}

11
project/rpi2-test.mk Normal file
View File

@@ -0,0 +1,11 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
TARGET := rpi2
MODULES += \
app/shell \
app/stringtests \
app/tests \
lib/cksum \
lib/debugcommands \

9
target/rpi2/rules.mk Normal file
View File

@@ -0,0 +1,9 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
GLOBAL_INCLUDES += \
$(LOCAL_DIR)/include
PLATFORM := bcm2835
#include make/module.mk