mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 22:47:50 +00:00
hw: irq controller and timer improvements for Rpi
* renamed rpi pic to Bcm2835_pic * renamed rpi3 pic to Bcm2837_pic * added bcm2837 control for setting prescaler value (to fix timer_accuracy) * changed handling of all interrupts for rpi3 by cascading to bcm2835 pic * rpi3 irq controller base address made consistent with rpi * added usb controller memory region for pic on rpi3 (for SOF interrupts) Ref #3415
This commit is contained in:
parent
7db602faec
commit
f79d5d640f
@ -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
|
||||
|
@ -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 })
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include <spec/arm/bcm2835_system_timer.h>
|
||||
#include <spec/arm_v6/cpu.h>
|
||||
|
||||
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_ */
|
||||
|
@ -25,6 +25,7 @@
|
||||
namespace Board {
|
||||
|
||||
using namespace Hw::Rpi3_board;
|
||||
class Pic : public Bcm2837_pic { };
|
||||
|
||||
enum { TIMER_IRQ = 1 };
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Board::Pic::Usb_dwc_otg::_need_trigger_sof(uint32_t host_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<Irq_pending_gpu_1>(),
|
||||
@ -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<Irq_disable_basic>(~0);
|
||||
write<Irq_disable_gpu_1>(~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<Irq_enable_gpu_1>(1 << i); }
|
||||
else { write<Irq_enable_gpu_2>(1 << (i - 32)); }
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::mask(unsigned const i)
|
||||
void Board::Bcm2835_pic::mask(unsigned const i)
|
||||
{
|
||||
if (i < 32) { write<Irq_disable_gpu_1>(1 << i); }
|
||||
else { write<Irq_disable_gpu_2>(1 << (i - 32)); }
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { }
|
||||
void Board::Bcm2835_pic::irq_mode(unsigned, unsigned, unsigned) { }
|
||||
|
@ -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() { }
|
||||
|
@ -16,13 +16,14 @@
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
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<Core_mailbox_set<0>>(1); return;
|
||||
|
@ -16,14 +16,16 @@
|
||||
|
||||
#include <util/mmio.h>
|
||||
|
||||
#include <spec/arm/bcm2835_pic.h>
|
||||
|
||||
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 <unsigned CPU_NUM>
|
||||
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 <unsigned CPU_NUM>
|
||||
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() { }
|
||||
|
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
61
repos/base/include/drivers/platform/bcm2837_control.h
Normal file
61
repos/base/include/drivers/platform/bcm2837_control.h
Normal file
@ -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 <util/mmio.h>
|
||||
|
||||
|
||||
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<CoreTimerPrescaler>(0x80000000);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__PLATFORM__BCM2837_CONTROL_H_ */
|
Loading…
Reference in New Issue
Block a user