diff --git a/base-hw/mk/spec-hw_rpi.mk b/base-hw/mk/spec-hw_rpi.mk new file mode 100644 index 0000000000..7c3550bafe --- /dev/null +++ b/base-hw/mk/spec-hw_rpi.mk @@ -0,0 +1,15 @@ +# +# \brief Build configurations specific to base-hw and Raspberry Pi +# \author Norman Feske +# \date 2013-04-05 +# + +# denote wich specs are also fullfilled by this spec +SPECS += hw platform_rpi + +# set address where to link the text segment at +LD_TEXT_ADDR ?= 0x400000 + +# include implied specs +include $(call select_from_repositories,mk/spec-hw.mk) +include $(call select_from_repositories,mk/spec-platform_rpi.mk) diff --git a/base-hw/src/core/platform.cc b/base-hw/src/core/platform.cc index ad68c2b8a6..3ad3a689a6 100644 --- a/base-hw/src/core/platform.cc +++ b/base-hw/src/core/platform.cc @@ -123,7 +123,14 @@ Platform::Platform() : unsigned const psl2 = get_page_size_log2(); init_alloc(&_core_mem_alloc, _ram_regions, _core_only_ram_regions, psl2); init_alloc(&_irq_alloc, _irq_regions, _core_only_irq_regions); - init_alloc(&_io_mem_alloc, _mmio_regions, _core_only_mmio_regions, psl2); + + /* + * Use byte granuarity for MMIO regions because on some platforms, devices + * driven by core share a physical page with devices driven outside of + * core. Using byte granuarlity allows handing out the MMIO page to trusted + * user-level device drivers. + */ + init_alloc(&_io_mem_alloc, _mmio_regions, _core_only_mmio_regions, 0); /* add boot modules to ROM FS */ Bm_header * header = &_boot_module_headers_begin; diff --git a/base-hw/src/core/rpi/board.h b/base-hw/src/core/rpi/board.h new file mode 100644 index 0000000000..79b40b73fa --- /dev/null +++ b/base-hw/src/core/rpi/board.h @@ -0,0 +1,24 @@ +/* + * \brief Board driver for core + * \author Norman Feske + * \date 2013-04-05 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _RPI__BOARD_H_ +#define _RPI__BOARD_H_ + +/* Genode includes */ +#include + +namespace Genode { struct Board; } + +struct Genode::Board : Genode::Board_base { static void prepare_kernel() { } }; + +#endif /* _RPI__BOARD_H_ */ diff --git a/base-hw/src/core/rpi/cpu.h b/base-hw/src/core/rpi/cpu.h new file mode 100644 index 0000000000..30652180bb --- /dev/null +++ b/base-hw/src/core/rpi/cpu.h @@ -0,0 +1,23 @@ +/* + * \brief CPU definition for Raspberry Pi + * \author Norman Feske + * \date 2013-04-11 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _RPI__CPU_H_ +#define _RPI__CPU_H_ + +/* core includes */ +#include + +namespace Genode { struct Cpu : Arm_v6::Cpu { }; } + +#endif /* _RPI__CPU_H_ */ + diff --git a/base-hw/src/core/rpi/pic.h b/base-hw/src/core/rpi/pic.h new file mode 100644 index 0000000000..3d13f78656 --- /dev/null +++ b/base-hw/src/core/rpi/pic.h @@ -0,0 +1,124 @@ +/* + * \brief Interrupt controller for kernel + * \author Norman Feske + * \date 2013-04-05 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _RPI__PIC_H_ +#define _RPI__PIC_H_ + +/* Genode includes */ +#include +#include + +/* core includes */ +#include + +namespace Kernel +{ + class Pic : Genode::Mmio + { + struct Irq_pending_basic : Register<0x0, 32> + { + struct Timer : Bitfield<0, 1> { }; + struct Gpu : Bitfield<8, 2> { }; + }; + + struct Irq_pending_gpu_1 : Register<0x04, 32> { }; + struct Irq_pending_gpu_2 : Register<0x08, 32> { }; + struct Irq_enable_gpu_1 : Register<0x10, 32> { }; + struct Irq_enable_gpu_2 : Register<0x14, 32> { }; + + struct Irq_enable_basic : Register<0x18, 32> { }; + + struct Irq_disable_gpu_1 : Register<0x1c, 32> { }; + struct Irq_disable_gpu_2 : Register<0x20, 32> { }; + struct Irq_disable_basic : Register<0x24, 32> { }; + + private: + + typedef Genode::uint32_t uint32_t; + + /** + * Return true if specified interrupt is pending + */ + static bool _is_pending(unsigned i, uint32_t p1, uint32_t p2) + { + return i < 32 ? (p1 & (1 << i)) : (p2 & (1 << (i - 32))); + } + + public: + + Pic() : Genode::Mmio(Genode::Board::IRQ_CONTROLLER_BASE) { } + + bool take_request(unsigned &irq) + { + /* read basic IRQ status mask */ + uint32_t const p = read(); + + + /* read GPU IRQ status mask */ + uint32_t const p1 = read(), + p2 = read(); + + if (Irq_pending_basic::Timer::get(p)) { + irq = 0; + return true; + } + + /* search for lowest set bit in pending masks */ + for (unsigned i = 0; i < 64; i++) { + if (!_is_pending(i, p1, p2)) + continue; + + irq = Genode::Board_base::GPU_IRQ_BASE + i; + return true; + } + + return false; + } + + void finish_request() { } + + void unmask() { PDBG("not implemented"); } + + void mask() { PDBG("not implemented"); } + + void unmask(unsigned const i) + { + if (i < 8) + write(1 << i); + + else if (i < 32 + 8) { + write(1 << (i - 8)); + write(1 << 8); + + } else { + write(1 << (i - 8 - 32)); + write(1 << 9); + } + } + + void mask(unsigned const i) + { + if (i < 8) + write(1 << i); + + else if (i < 32 + 8) + write(1 << (i - 8)); + + else + write(1 << (i - 8 - 32)); + } + }; +} + +#endif /* _RPI__PIC_H_ */ + diff --git a/base-hw/src/core/rpi/platform_support.cc b/base-hw/src/core/rpi/platform_support.cc new file mode 100644 index 0000000000..3c00c3112e --- /dev/null +++ b/base-hw/src/core/rpi/platform_support.cc @@ -0,0 +1,81 @@ +/* + * \brief Platform implementations specific for base-hw and Raspberry Pi + * \author Norman Feske + * \date 2013-04-05 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* core includes */ +#include +#include + +using namespace Genode; + + +Native_region * Platform::_ram_regions(unsigned const i) +{ + static Native_region _regions[] = + { + { Board::RAM_0_BASE, Board::RAM_0_SIZE } + }; + return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; +} + + +Native_region * Platform::_irq_regions(unsigned const i) +{ + static Native_region _regions[] = + { + { 0, 64 } + }; + return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; +} + + +Native_region * Platform::_core_only_irq_regions(unsigned const i) +{ + static Native_region _regions[] = + { + /* system timer */ + { Board::SYSTEM_TIMER_IRQ, 1 }, + + /* UART */ + { Board::PL011_0_IRQ, 1 }, + + }; + return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; +} + + +Native_region * Platform::_mmio_regions(unsigned const i) +{ + static Native_region _regions[] = + { + { 0x20000000, 0x22000000 }, + }; + return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; +} + + +Native_region * Platform::_core_only_mmio_regions(unsigned const i) +{ + static Native_region _regions[] = + { + /* UART */ + { Board::PL011_0_MMIO_BASE, Board::PL011_0_MMIO_SIZE }, + + /* system timer */ + { Board::SYSTEM_TIMER_MMIO_BASE, Board::SYSTEM_TIMER_MMIO_SIZE }, + + /* IRQ controller */ + { Board::IRQ_CONTROLLER_BASE, Board::IRQ_CONTROLLER_SIZE }, + }; + return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; +} + diff --git a/base-hw/src/core/rpi/target.mk b/base-hw/src/core/rpi/target.mk new file mode 100644 index 0000000000..dcb792293b --- /dev/null +++ b/base-hw/src/core/rpi/target.mk @@ -0,0 +1,41 @@ +# +# \brief Build config for Genodes core process +# \author Norman Feske +# \date 2013-04-05 +# + +# declare wich specs must be given to build this target +REQUIRES = platform_rpi + +# add include paths +INC_DIR += $(REP_DIR)/src/core/rpi + +# add C++ sources +SRC_CC += platform_services.cc \ + platform_support.cc + +# add assembly sources +SRC_S += mode_transition.s \ + boot_modules.s \ + crt0.s + +# declare source paths +vpath platform_services.cc $(BASE_DIR)/src/core +vpath platform_support.cc $(REP_DIR)/src/core/rpi +vpath mode_transition.s $(REP_DIR)/src/core/arm_v6 +vpath crt0.s $(REP_DIR)/src/core/arm + +# +# Check if there are other images wich shall be linked to core. +# If not use a dummy boot-modules file wich includes only the symbols. +# +ifeq ($(wildcard $(BUILD_BASE_DIR)/boot_modules.s),) + vpath boot_modules.s $(REP_DIR)/src/core/arm +else + INC_DIR += $(BUILD_BASE_DIR) + vpath boot_modules.s $(BUILD_BASE_DIR) +endif + +# include less specific target parts +include $(REP_DIR)/src/core/target.inc + diff --git a/base-hw/src/core/rpi/timer.h b/base-hw/src/core/rpi/timer.h new file mode 100644 index 0000000000..be9a56aeea --- /dev/null +++ b/base-hw/src/core/rpi/timer.h @@ -0,0 +1,77 @@ +/* + * \brief Timer for kernel + * \author Norman Feske + * \date 2013-04-05 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _RPI__TIMER_H_ +#define _RPI__TIMER_H_ + +/* Genode includes */ +#include +#include +#include +#include + +namespace Kernel { class Timer; } + + +class Kernel::Timer : public Genode::Mmio +{ + /* + * The timer channel 0 apparently does not work on the Raspberry Pi. + * So we use channel 1. + */ + + struct Cs : Register<0x0, 32> + { + struct Status : Bitfield<1, 1> { }; + }; + + struct Clo : Register<0x4, 32> { }; + struct Cmp : Register<0x10, 32> { }; + + private: + + typedef Genode::uint32_t uint32_t; + typedef Genode::Board_base Board_base; + + public: + + Timer() : Mmio(Board_base::SYSTEM_TIMER_MMIO_BASE) { } + + enum { IRQ = Board_base::SYSTEM_TIMER_IRQ }; + + inline void start_one_shot(uint32_t const tics) + { + write(0); + write(read() + tics); + write(1); + } + + static uint32_t ms_to_tics(unsigned const ms) + { + return (Board_base::SYSTEM_TIMER_CLOCK / 1000) * ms; + } + + unsigned stop_one_shot() + { + return read(); + } + + void clear_interrupt() + { + write(1); + read(); + } +}; + +#endif /* _RPI__TIMER_H_ */ + diff --git a/base-hw/src/core/rpi/tlb.h b/base-hw/src/core/rpi/tlb.h new file mode 100644 index 0000000000..dd520a53ca --- /dev/null +++ b/base-hw/src/core/rpi/tlb.h @@ -0,0 +1,47 @@ +/* + * \brief Translation lookaside buffer + * \author Norman Feske + * \author Martin stein + * \date 2012-08-30 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _RPI__TLB_H_ +#define _RPI__TLB_H_ + +/* core includes */ +#include +#include + +namespace Genode +{ + struct Page_flags : Arm::Page_flags { }; + + class Tlb : public Arm_v6::Section_table { }; + + /** + * Translation lookaside buffer of core + */ + class Core_tlb : public Tlb + { + public: + + /** + * Constructor - ensures that core never gets a pagefault + */ + Core_tlb() + { + map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0); + map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1); + } + }; +} + +#endif /* _RPI__TLB_H_ */ + diff --git a/base/include/platform/rpi/drivers/board_base.h b/base/include/platform/rpi/drivers/board_base.h new file mode 100644 index 0000000000..c4e886d0cc --- /dev/null +++ b/base/include/platform/rpi/drivers/board_base.h @@ -0,0 +1,57 @@ +/* + * \brief Board definitions for the Raspberry Pi + * \author Norman Feske + * \date 2013-04-05 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__PLATFORM__BOARD_BASE_H_ +#define _INCLUDE__PLATFORM__BOARD_BASE_H_ + +/* Genode includes */ +#include + +namespace Genode +{ + struct Board_base + { + enum { + RAM_0_BASE = 0x00000000, + RAM_0_SIZE = 0x10000000, /* XXX ? */ + + MMIO_0_BASE = 0x20000000, + MMIO_0_SIZE = 0x02000000, + + /* + * IRQ numbers 0..7 refer to the basic IRQs. + * IRQ numbers 8..39 refer to GPU IRQs 0..31. + * IRQ numbers 40..71 refer to GPU IRQs 32..63. + */ + GPU_IRQ_BASE = 8, + + SYSTEM_TIMER_IRQ = GPU_IRQ_BASE + 1, + SYSTEM_TIMER_MMIO_BASE = 0x20003000, + SYSTEM_TIMER_MMIO_SIZE = 0x1000, + SYSTEM_TIMER_CLOCK = 1000000, + + PL011_0_IRQ = 57, + PL011_0_MMIO_BASE = 0x20201000, + PL011_0_MMIO_SIZE = 0x1000, + PL011_0_CLOCK = 3000000, + + IRQ_CONTROLLER_BASE = 0x2000b200, + IRQ_CONTROLLER_SIZE = 0x100, + + SECURITY_EXTENSION = 0, + }; + }; +} + +#endif /* _INCLUDE__PLATFORM__BOARD_BASE_H_ */ + diff --git a/base/mk/spec-platform_rpi.mk b/base/mk/spec-platform_rpi.mk new file mode 100644 index 0000000000..0bb1a0bf03 --- /dev/null +++ b/base/mk/spec-platform_rpi.mk @@ -0,0 +1,15 @@ +# +# \brief Build-system configurations for Raspberry Pi +# \author Norman Feske +# \date 2013-04-05 +# + +# denote wich specs are also fullfilled by this spec +SPECS += arm_v6 pl011 + +# add repository relative include paths +REP_INC_DIR += include/platform/rpi + +# include implied specs +include $(call select_from_repositories,mk/spec-arm_v6.mk) +include $(call select_from_repositories,mk/spec-pl011.mk) diff --git a/os/lib/mk/hw_rpi/timer.mk b/os/lib/mk/hw_rpi/timer.mk new file mode 100644 index 0000000000..9669f7c41d --- /dev/null +++ b/os/lib/mk/hw_rpi/timer.mk @@ -0,0 +1,3 @@ +INC_DIR += $(REP_DIR)/src/drivers/timer/hw $(REP_DIR)/src/drivers/timer/hw/rpi + +include $(REP_DIR)/lib/mk/timer.inc diff --git a/os/src/drivers/timer/hw/rpi/platform_timer_base.h b/os/src/drivers/timer/hw/rpi/platform_timer_base.h new file mode 100644 index 0000000000..f67ac68727 --- /dev/null +++ b/os/src/drivers/timer/hw/rpi/platform_timer_base.h @@ -0,0 +1,50 @@ +/* + * \brief User-level timer driver for Raspberry Pi + * \author Norman Feske + * \date 2013-04-11 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _HW__RPI__PLATFORM_TIMER_BASE_H_ +#define _HW__RPI__PLATFORM_TIMER_BASE_H_ + +/* Genode includes */ +#include +#include + +/* + * On the BCM2835, the timer is driven by the APB clock (250 MHz). The prescale + * register (not present in the normal SP804) has a reset value of 126. Hence, + * the effective timer clock is 1,984 MHz. + * + * The timer device is on the same physical page as the IRQ controller. Hence, + * we open an IO_MEM session with a range smaller than page size as argument. + * The dataspace base address will correspond to 0x2000b000. + */ +enum { TIMER_IRQ = 0, + TIMER_MMIO_BASE = 0x2000b400, + TIMER_MMIO_OFFSET = 0x400, + TIMER_MMIO_SIZE = 0x100, + TIMER_CLOCK = 1984*1000 }; + +struct Platform_timer_base +: + Genode::Attached_io_mem_dataspace, + Genode::Sp804_base +{ + enum { IRQ = TIMER_IRQ }; + + Platform_timer_base() : + Attached_io_mem_dataspace(TIMER_MMIO_BASE, TIMER_MMIO_SIZE), + Sp804_base((Genode::addr_t)local_addr() + TIMER_MMIO_OFFSET) + { } +}; + +#endif /* _HW__RPI__PLATFORM_TIMER_BASE_H_ */ + diff --git a/tool/builddir/etc/build.conf.hw_rpi b/tool/builddir/etc/build.conf.hw_rpi new file mode 100644 index 0000000000..9c370116a3 --- /dev/null +++ b/tool/builddir/etc/build.conf.hw_rpi @@ -0,0 +1 @@ +REPOSITORIES += $(GENODE_DIR)/base-hw diff --git a/tool/create_builddir b/tool/create_builddir index 3e8170c582..b7ebab33e1 100755 --- a/tool/create_builddir +++ b/tool/create_builddir @@ -32,6 +32,7 @@ usage: @echo " 'hw_imx31'" @echo " 'hw_imx53'" @echo " 'hw_arndale'" + @echo " 'hw_rpi'" @echo " 'foc_x86_32'" @echo " 'foc_x86_64'" @echo " 'foc_pbxa9'" @@ -206,6 +207,9 @@ hw_imx53:: hw_arndale:: @echo "SPECS = genode hw_arndale" > $(BUILD_DIR)/etc/specs.conf +hw_rpi:: + @echo "SPECS = genode hw_rpi" > $(BUILD_DIR)/etc/specs.conf + lx_hybrid_x86:: @echo "CROSS_DEV_PREFIX =" > $(BUILD_DIR)/etc/tools.conf @echo "SPECS += always_hybrid" >> $(BUILD_DIR)/etc/specs.conf