mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01: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:
committed by
Christian Helmuth
parent
7db602faec
commit
f79d5d640f
@@ -3,6 +3,7 @@ REP_INC_DIR += src/core/board/rpi3
|
|||||||
# add C++ sources
|
# add C++ sources
|
||||||
SRC_CC += kernel/vm_thread_off.cc
|
SRC_CC += kernel/vm_thread_off.cc
|
||||||
SRC_CC += platform_services.cc
|
SRC_CC += platform_services.cc
|
||||||
|
SRC_CC += spec/arm/bcm2835_pic.cc
|
||||||
SRC_CC += spec/arm/bcm2837_pic.cc
|
SRC_CC += spec/arm/bcm2837_pic.cc
|
||||||
|
|
||||||
NR_OF_CPUS = 4
|
NR_OF_CPUS = 4
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ Bootstrap::Platform::Board::Board()
|
|||||||
Memory_region { ::Board::LOCAL_IRQ_CONTROLLER_BASE,
|
Memory_region { ::Board::LOCAL_IRQ_CONTROLLER_BASE,
|
||||||
::Board::LOCAL_IRQ_CONTROLLER_SIZE },
|
::Board::LOCAL_IRQ_CONTROLLER_SIZE },
|
||||||
Memory_region { ::Board::IRQ_CONTROLLER_BASE,
|
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/bcm2835_system_timer.h>
|
||||||
#include <spec/arm_v6/cpu.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_ */
|
#endif /* _CORE__SPEC__RPI__BOARD_H_ */
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
namespace Board {
|
namespace Board {
|
||||||
|
|
||||||
using namespace Hw::Rpi3_board;
|
using namespace Hw::Rpi3_board;
|
||||||
|
class Pic : public Bcm2837_pic { };
|
||||||
|
|
||||||
enum { TIMER_IRQ = 1 };
|
enum { TIMER_IRQ = 1 };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
using namespace Genode;
|
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 scheduled_frame)
|
||||||
{
|
{
|
||||||
uint32_t const max_frame = 0x3fff;
|
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)
|
Usb_dwc_otg::Usb_dwc_otg(Global_interrupt_controller &global_irq_ctrl)
|
||||||
:
|
:
|
||||||
Mmio { Platform::mmio_to_virt(Board::USB_DWC_OTG_BASE) },
|
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())
|
if (!_is_sof())
|
||||||
return false;
|
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 }
|
_usb { global_irq_ctrl }
|
||||||
{
|
{
|
||||||
mask();
|
mask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Board::Pic::take_request(unsigned &irq)
|
bool Board::Bcm2835_pic::take_request(unsigned &irq)
|
||||||
{
|
{
|
||||||
/* read GPU IRQ status mask */
|
/* read GPU IRQ status mask */
|
||||||
uint32_t const p1 = read<Irq_pending_gpu_1>(),
|
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 */
|
/* search for lowest set bit in pending masks */
|
||||||
for (unsigned i = 0; i < NR_OF_IRQ; i++) {
|
for (unsigned i = 0; i < NR_OF_IRQ; i++) {
|
||||||
|
|
||||||
if (!_is_pending(i, p1, p2))
|
if (!_is_pending(i, p1, p2))
|
||||||
continue;
|
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_basic>(~0);
|
||||||
write<Irq_disable_gpu_1>(~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); }
|
if (i < 32) { write<Irq_enable_gpu_1>(1 << i); }
|
||||||
else { write<Irq_enable_gpu_2>(1 << (i - 32)); }
|
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); }
|
if (i < 32) { write<Irq_disable_gpu_1>(1 << i); }
|
||||||
else { write<Irq_disable_gpu_2>(1 << (i - 32)); }
|
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 {
|
namespace Board {
|
||||||
|
|
||||||
class Global_interrupt_controller;
|
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:
|
public:
|
||||||
|
|
||||||
@@ -128,7 +128,8 @@ class Board::Pic : Genode::Mmio
|
|||||||
|
|
||||||
public:
|
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);
|
bool take_request(unsigned &irq);
|
||||||
void finish_request() { }
|
void finish_request() { }
|
||||||
|
|||||||
@@ -16,13 +16,14 @@
|
|||||||
#include <platform.h>
|
#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();
|
unsigned cpu = Genode::Cpu::executing_id();
|
||||||
Core_irq_source<0>::access_t src = 0;
|
Core_irq_source<0>::access_t src = 0;
|
||||||
@@ -49,11 +50,17 @@ bool Board::Pic::take_request(unsigned & irq)
|
|||||||
return true;
|
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;
|
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;
|
unsigned v = enable ? 1 : 0;
|
||||||
switch (cpu) {
|
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;
|
unsigned v = enable ? 1 : 0;
|
||||||
switch (cpu) {
|
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) {
|
switch (i) {
|
||||||
case TIMER_IRQ: _timer_irq(cpu, true); return;
|
case TIMER_IRQ: _timer_irq(cpu, true); return;
|
||||||
case IPI: _ipi(cpu, true); return;
|
case IPI: _ipi(cpu, true); return;
|
||||||
}
|
}
|
||||||
|
if (cpu == 0) _bcm2835_pic.unmask(i, cpu);
|
||||||
Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Pic::mask(unsigned const i)
|
void Board::Bcm2837_pic::mask(unsigned const i)
|
||||||
{
|
{
|
||||||
unsigned cpu = Genode::Cpu::executing_id();
|
unsigned cpu = Genode::Cpu::executing_id();
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case TIMER_IRQ: _timer_irq(cpu, false); return;
|
case TIMER_IRQ: _timer_irq(cpu, false); return;
|
||||||
case IPI: _ipi(cpu, false); return;
|
case IPI: _ipi(cpu, false); return;
|
||||||
}
|
}
|
||||||
|
if (cpu == 0) _bcm2835_pic.mask(i);
|
||||||
Genode::raw("irq of peripherals != timer not implemented yet! (irq=", 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) {
|
switch (cpu_target) {
|
||||||
case 0: write<Core_mailbox_set<0>>(1); return;
|
case 0: write<Core_mailbox_set<0>>(1); return;
|
||||||
|
|||||||
@@ -16,14 +16,16 @@
|
|||||||
|
|
||||||
#include <util/mmio.h>
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
#include <spec/arm/bcm2835_pic.h>
|
||||||
|
|
||||||
namespace Board {
|
namespace Board {
|
||||||
|
|
||||||
class Global_interrupt_controller { };
|
/* Global_interrupt_controller from Bcm2835_pic */
|
||||||
class Pic;
|
class Bcm2837_pic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Board::Pic : Genode::Mmio
|
class Board::Bcm2837_pic : Genode::Mmio
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -45,7 +47,20 @@ class Board::Pic : Genode::Mmio
|
|||||||
struct Core_mailbox_irq_control : Register<0x50+CPU_NUM*0x4, 32> {};
|
struct Core_mailbox_irq_control : Register<0x50+CPU_NUM*0x4, 32> {};
|
||||||
|
|
||||||
template <unsigned CPU_NUM>
|
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>
|
template <unsigned CPU_NUM>
|
||||||
struct Core_mailbox_set : Register<0x80+CPU_NUM*0x10, 32> {};
|
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 _ipi(unsigned cpu, bool enable);
|
||||||
void _timer_irq(unsigned cpu, bool enable);
|
void _timer_irq(unsigned cpu, bool enable);
|
||||||
|
|
||||||
|
Bcm2835_pic _bcm2835_pic;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Pic(Global_interrupt_controller &);
|
Bcm2837_pic(Global_interrupt_controller &);
|
||||||
|
|
||||||
bool take_request(unsigned &irq);
|
bool take_request(unsigned &irq);
|
||||||
void finish_request() { }
|
void finish_request() { }
|
||||||
|
|||||||
@@ -29,11 +29,17 @@ namespace Hw::Rpi3_board {
|
|||||||
UART_SIZE = 0x1000,
|
UART_SIZE = 0x1000,
|
||||||
UART_CLOCK = 250000000,
|
UART_CLOCK = 250000000,
|
||||||
|
|
||||||
IRQ_CONTROLLER_BASE = 0x3f00b000,
|
IRQ_CONTROLLER_BASE = 0x3f00b200,
|
||||||
IRQ_CONTROLLER_SIZE = 0x1000,
|
IRQ_CONTROLLER_SIZE = 0x1000,
|
||||||
|
|
||||||
LOCAL_IRQ_CONTROLLER_BASE = 0x40000000,
|
LOCAL_IRQ_CONTROLLER_BASE = 0x40000000,
|
||||||
LOCAL_IRQ_CONTROLLER_SIZE = 0x1000,
|
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_ */
|
||||||
Reference in New Issue
Block a user