diff --git a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk index cb2f25c584..900c04198b 100644 --- a/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk +++ b/repos/base-hw/lib/mk/spec/arm_v8/core-hw-rpi3.mk @@ -3,6 +3,7 @@ REP_INC_DIR += src/core/board/rpi3 # add C++ sources SRC_CC += kernel/vm_thread_off.cc SRC_CC += platform_services.cc +SRC_CC += spec/arm/bcm2835_pic.cc SRC_CC += spec/arm/bcm2837_pic.cc NR_OF_CPUS = 4 diff --git a/repos/base-hw/src/bootstrap/board/rpi3/platform.cc b/repos/base-hw/src/bootstrap/board/rpi3/platform.cc index 5b34d91e72..3c869bb13c 100644 --- a/repos/base-hw/src/bootstrap/board/rpi3/platform.cc +++ b/repos/base-hw/src/bootstrap/board/rpi3/platform.cc @@ -26,7 +26,9 @@ Bootstrap::Platform::Board::Board() Memory_region { ::Board::LOCAL_IRQ_CONTROLLER_BASE, ::Board::LOCAL_IRQ_CONTROLLER_SIZE }, Memory_region { ::Board::IRQ_CONTROLLER_BASE, - ::Board::IRQ_CONTROLLER_SIZE }) + ::Board::IRQ_CONTROLLER_SIZE }, + Memory_region { ::Board::USB_DWC_OTG_BASE, + ::Board::USB_DWC_OTG_SIZE }) { } diff --git a/repos/base-hw/src/core/board/rpi/board.h b/repos/base-hw/src/core/board/rpi/board.h index d03503548a..634ba616dd 100644 --- a/repos/base-hw/src/core/board/rpi/board.h +++ b/repos/base-hw/src/core/board/rpi/board.h @@ -23,6 +23,9 @@ #include #include -namespace Board { using namespace Hw::Rpi_board; }; +namespace Board { + using namespace Hw::Rpi_board; + class Pic : public Bcm2835_pic { }; +}; #endif /* _CORE__SPEC__RPI__BOARD_H_ */ diff --git a/repos/base-hw/src/core/board/rpi3/board.h b/repos/base-hw/src/core/board/rpi3/board.h index b7573b4c75..9a97b18975 100644 --- a/repos/base-hw/src/core/board/rpi3/board.h +++ b/repos/base-hw/src/core/board/rpi3/board.h @@ -25,6 +25,7 @@ namespace Board { using namespace Hw::Rpi3_board; + class Pic : public Bcm2837_pic { }; enum { TIMER_IRQ = 1 }; }; diff --git a/repos/base-hw/src/core/spec/arm/bcm2835_pic.cc b/repos/base-hw/src/core/spec/arm/bcm2835_pic.cc index 6462eda7a5..1632a1fff0 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2835_pic.cc +++ b/repos/base-hw/src/core/spec/arm/bcm2835_pic.cc @@ -18,8 +18,8 @@ using namespace Genode; -bool Board::Pic::Usb_dwc_otg::_need_trigger_sof(uint32_t host_frame, - uint32_t scheduled_frame) +bool Board::Bcm2835_pic::Usb_dwc_otg::_need_trigger_sof(uint32_t host_frame, + uint32_t scheduled_frame) { uint32_t const max_frame = 0x3fff; @@ -37,7 +37,7 @@ bool Board::Pic::Usb_dwc_otg::_need_trigger_sof(uint32_t host_frame, } -Board::Pic:: +Board::Bcm2835_pic:: Usb_dwc_otg::Usb_dwc_otg(Global_interrupt_controller &global_irq_ctrl) : Mmio { Platform::mmio_to_virt(Board::USB_DWC_OTG_BASE) }, @@ -49,7 +49,7 @@ Usb_dwc_otg::Usb_dwc_otg(Global_interrupt_controller &global_irq_ctrl) } -bool Board::Pic::Usb_dwc_otg::handle_sof() +bool Board::Bcm2835_pic::Usb_dwc_otg::handle_sof() { if (!_is_sof()) return false; @@ -72,16 +72,18 @@ bool Board::Pic::Usb_dwc_otg::handle_sof() } -Board::Pic::Pic(Global_interrupt_controller &global_irq_ctrl) +Board::Bcm2835_pic::Bcm2835_pic(Global_interrupt_controller &global_irq_ctrl, + Genode::addr_t irq_ctrl_base) : - Mmio { Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE) }, + Mmio(Platform::mmio_to_virt(irq_ctrl_base ? irq_ctrl_base + : (Genode::addr_t) Board::IRQ_CONTROLLER_BASE)), _usb { global_irq_ctrl } { mask(); } -bool Board::Pic::take_request(unsigned &irq) +bool Board::Bcm2835_pic::take_request(unsigned &irq) { /* read GPU IRQ status mask */ uint32_t const p1 = read(), @@ -89,6 +91,7 @@ bool Board::Pic::take_request(unsigned &irq) /* search for lowest set bit in pending masks */ for (unsigned i = 0; i < NR_OF_IRQ; i++) { + if (!_is_pending(i, p1, p2)) continue; @@ -106,7 +109,7 @@ bool Board::Pic::take_request(unsigned &irq) } -void Board::Pic::mask() +void Board::Bcm2835_pic::mask() { write(~0); write(~0); @@ -114,18 +117,18 @@ void Board::Pic::mask() } -void Board::Pic::unmask(unsigned const i, unsigned) +void Board::Bcm2835_pic::unmask(unsigned const i, unsigned) { if (i < 32) { write(1 << i); } else { write(1 << (i - 32)); } } -void Board::Pic::mask(unsigned const i) +void Board::Bcm2835_pic::mask(unsigned const i) { if (i < 32) { write(1 << i); } else { write(1 << (i - 32)); } } -void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { } +void Board::Bcm2835_pic::irq_mode(unsigned, unsigned, unsigned) { } diff --git a/repos/base-hw/src/core/spec/arm/bcm2835_pic.h b/repos/base-hw/src/core/spec/arm/bcm2835_pic.h index 26dfed467b..a26e7d7ed2 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2835_pic.h +++ b/repos/base-hw/src/core/spec/arm/bcm2835_pic.h @@ -20,7 +20,7 @@ namespace Board { class Global_interrupt_controller; - class Pic; + class Bcm2835_pic; } @@ -38,7 +38,7 @@ class Board::Global_interrupt_controller }; -class Board::Pic : Genode::Mmio +class Board::Bcm2835_pic : Genode::Mmio { public: @@ -128,7 +128,8 @@ class Board::Pic : Genode::Mmio public: - Pic(Global_interrupt_controller &global_irq_ctrl); + Bcm2835_pic(Global_interrupt_controller &global_irq_ctrl, + Genode::addr_t irq_ctrl_base = 0); bool take_request(unsigned &irq); void finish_request() { } diff --git a/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc b/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc index 87bedca8a2..02363938cc 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc +++ b/repos/base-hw/src/core/spec/arm/bcm2837_pic.cc @@ -16,13 +16,14 @@ #include -Board::Pic::Pic(Global_interrupt_controller &) +Board::Bcm2837_pic::Bcm2837_pic(Global_interrupt_controller &global_irq_ctrl) : - Genode::Mmio(Genode::Platform::mmio_to_virt(Board::LOCAL_IRQ_CONTROLLER_BASE)) + Genode::Mmio(Genode::Platform::mmio_to_virt(Board::LOCAL_IRQ_CONTROLLER_BASE)), + _bcm2835_pic(global_irq_ctrl, Board::IRQ_CONTROLLER_BASE) { } -bool Board::Pic::take_request(unsigned & irq) +bool Board::Bcm2837_pic::take_request(unsigned & irq) { unsigned cpu = Genode::Cpu::executing_id(); Core_irq_source<0>::access_t src = 0; @@ -49,11 +50,17 @@ bool Board::Pic::take_request(unsigned & irq) return true; } + // Gpu interrupt + if (cpu == 0 && Core_irq_source<0>::Gpu::get(src)) { + auto result = _bcm2835_pic.take_request(irq); + return result; + } + return false; } -void Board::Pic::_timer_irq(unsigned cpu, bool enable) +void Board::Bcm2837_pic::_timer_irq(unsigned cpu, bool enable) { unsigned v = enable ? 1 : 0; switch (cpu) { @@ -74,7 +81,7 @@ void Board::Pic::_timer_irq(unsigned cpu, bool enable) } -void Board::Pic::_ipi(unsigned cpu, bool enable) +void Board::Bcm2837_pic::_ipi(unsigned cpu, bool enable) { unsigned v = enable ? 1 : 0; switch (cpu) { @@ -95,33 +102,31 @@ void Board::Pic::_ipi(unsigned cpu, bool enable) } -void Board::Pic::unmask(unsigned const i, unsigned cpu) +void Board::Bcm2837_pic::unmask(unsigned const i, unsigned cpu) { switch (i) { case TIMER_IRQ: _timer_irq(cpu, true); return; case IPI: _ipi(cpu, true); return; } - - Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")"); + if (cpu == 0) _bcm2835_pic.unmask(i, cpu); } -void Board::Pic::mask(unsigned const i) +void Board::Bcm2837_pic::mask(unsigned const i) { unsigned cpu = Genode::Cpu::executing_id(); switch (i) { case TIMER_IRQ: _timer_irq(cpu, false); return; case IPI: _ipi(cpu, false); return; } - - Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")"); + if (cpu == 0) _bcm2835_pic.mask(i); } -void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { } +void Board::Bcm2837_pic::irq_mode(unsigned, unsigned, unsigned) { } -void Board::Pic::send_ipi(unsigned cpu_target) +void Board::Bcm2837_pic::send_ipi(unsigned cpu_target) { switch (cpu_target) { case 0: write>(1); return; diff --git a/repos/base-hw/src/core/spec/arm/bcm2837_pic.h b/repos/base-hw/src/core/spec/arm/bcm2837_pic.h index 3bdb3838e4..f474a345c1 100644 --- a/repos/base-hw/src/core/spec/arm/bcm2837_pic.h +++ b/repos/base-hw/src/core/spec/arm/bcm2837_pic.h @@ -16,14 +16,16 @@ #include +#include + namespace Board { - class Global_interrupt_controller { }; - class Pic; + /* Global_interrupt_controller from Bcm2835_pic */ + class Bcm2837_pic; } -class Board::Pic : Genode::Mmio +class Board::Bcm2837_pic : Genode::Mmio { public: @@ -45,7 +47,20 @@ class Board::Pic : Genode::Mmio struct Core_mailbox_irq_control : Register<0x50+CPU_NUM*0x4, 32> {}; template - struct Core_irq_source : Register<0x60+CPU_NUM*0x4, 32> {}; + struct Core_irq_source : Register<0x60+CPU_NUM*0x4, 32> { + struct CntPsIrq : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<0, 1> { }; + struct CntPnIrq : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<1, 1> { }; + struct CntHpIrq : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<2, 1> { }; + struct CntVIrq : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<3, 1> { }; + struct MBox0 : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<4, 1> { }; + struct MBox1 : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<5, 1> { }; + struct MBox2 : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<6, 1> { }; + struct MBox3 : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<7, 1> { }; + struct Gpu : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<8, 1> { }; + struct Pmu : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<9, 1> { }; + struct Axi : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<10, 1> { }; + struct Timer : Register<0x60+CPU_NUM*0x4, 32>::template Bitfield<11, 1> { }; + }; template struct Core_mailbox_set : Register<0x80+CPU_NUM*0x10, 32> {}; @@ -56,9 +71,11 @@ class Board::Pic : Genode::Mmio void _ipi(unsigned cpu, bool enable); void _timer_irq(unsigned cpu, bool enable); + Bcm2835_pic _bcm2835_pic; + public: - Pic(Global_interrupt_controller &); + Bcm2837_pic(Global_interrupt_controller &); bool take_request(unsigned &irq); void finish_request() { } diff --git a/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h b/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h index f40088f329..2d8433d471 100644 --- a/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h +++ b/repos/base-hw/src/include/hw/spec/arm_64/rpi3_board.h @@ -29,11 +29,17 @@ namespace Hw::Rpi3_board { UART_SIZE = 0x1000, UART_CLOCK = 250000000, - IRQ_CONTROLLER_BASE = 0x3f00b000, + IRQ_CONTROLLER_BASE = 0x3f00b200, IRQ_CONTROLLER_SIZE = 0x1000, LOCAL_IRQ_CONTROLLER_BASE = 0x40000000, LOCAL_IRQ_CONTROLLER_SIZE = 0x1000, + + USB_DWC_OTG_BASE = 0x3f980000, + USB_DWC_OTG_SIZE = 0x20000, + + /* USB host controller */ + DWC_IRQ = 9, }; }; diff --git a/repos/base/include/drivers/platform/bcm2837_control.h b/repos/base/include/drivers/platform/bcm2837_control.h new file mode 100644 index 0000000000..d5f200621c --- /dev/null +++ b/repos/base/include/drivers/platform/bcm2837_control.h @@ -0,0 +1,61 @@ +/* + * \brief Driver for the platform specific functionality for bcm2837 + * \author Tomasz Gajewski + * \date 2019-12-28 + */ + +/* + * Copyright (C) 2011-2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__DRIVERS__PLATFORM__BCM2837_CONTROL_H_ +#define _INCLUDE__DRIVERS__PLATFORM__BCM2837_CONTROL_H_ + +/* Genode includes */ +#include + + +namespace Genode { class Bcm2837_control; } + + +class Genode::Bcm2837_control : Mmio +{ + public: + + struct ControlRegister : public Register<0x0, 32> + { + struct CoreTimeClockSource : Bitfield<8,1> { }; + struct TimerIncrement : Bitfield<9,1> { }; + }; + + struct CoreTimerPrescaler : public Register<0x8, 32> + { + }; + + inline Bcm2837_control(addr_t const base); + + inline void initialize_timer_frequency(); +}; + + +Genode::Bcm2837_control::Bcm2837_control(addr_t const base) +: + Mmio(base) +{ } + + +void Genode::Bcm2837_control::initialize_timer_frequency() +{ + /* + * Set prescaler value to achieve divider value equal to 1. + * Value taken from chapter "3.1.1 Timer clock" from QA7_rev3.4.pdf + * document describing the BCM2836 chip. + */ + write(0x80000000); +} + + +#endif /* _INCLUDE__DRIVERS__PLATFORM__BCM2837_CONTROL_H_ */