mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-11 06:54:18 +00:00
parent
777b093cad
commit
4d0cb175da
@ -7,7 +7,7 @@
|
|||||||
# add C++ sources
|
# add C++ sources
|
||||||
SRC_CC += spec/cortex_a9/board.cc
|
SRC_CC += spec/cortex_a9/board.cc
|
||||||
SRC_CC += spec/cortex_a9/cpu.cc
|
SRC_CC += spec/cortex_a9/cpu.cc
|
||||||
SRC_CC += spec/arm/cortex_a9_private_timer.cc
|
SRC_CC += spec/arm/cortex_a9_global_timer.cc
|
||||||
SRC_CC += spec/arm/gicv2.cc
|
SRC_CC += spec/arm/gicv2.cc
|
||||||
SRC_CC += spec/arm/kernel/lock.cc
|
SRC_CC += spec/arm/kernel/lock.cc
|
||||||
SRC_CC += kernel/vm_thread_off.cc
|
SRC_CC += kernel/vm_thread_off.cc
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <hw/spec/arm/imx6q_sabrelite_board.h>
|
#include <hw/spec/arm/imx6q_sabrelite_board.h>
|
||||||
|
|
||||||
/* base-hw Core includes */
|
/* base-hw Core includes */
|
||||||
#include <spec/arm/cortex_a9_private_timer.h>
|
#include <spec/arm/cortex_a9_global_timer.h>
|
||||||
#include <spec/cortex_a9/cpu.h>
|
#include <spec/cortex_a9/cpu.h>
|
||||||
|
|
||||||
namespace Board {
|
namespace Board {
|
||||||
@ -34,8 +34,8 @@ namespace Board {
|
|||||||
L2_cache & l2_cache();
|
L2_cache & l2_cache();
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CORTEX_A9_PRIVATE_TIMER_CLK = 396000000, /* timer clk runs half the CPU freq */
|
CORTEX_A9_GLOBAL_TIMER_CLK = 396000000, /* timer clk runs half the CPU freq */
|
||||||
CORTEX_A9_PRIVATE_TIMER_DIV = 100,
|
CORTEX_A9_GLOBAL_TIMER_DIV = 100,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <hw/spec/arm/nit6_solox_board.h>
|
#include <hw/spec/arm/nit6_solox_board.h>
|
||||||
|
|
||||||
/* base-hw Core includes */
|
/* base-hw Core includes */
|
||||||
#include <spec/arm/cortex_a9_private_timer.h>
|
#include <spec/arm/cortex_a9_global_timer.h>
|
||||||
#include <spec/cortex_a9/cpu.h>
|
#include <spec/cortex_a9/cpu.h>
|
||||||
|
|
||||||
namespace Board {
|
namespace Board {
|
||||||
@ -34,8 +34,8 @@ namespace Board {
|
|||||||
L2_cache & l2_cache();
|
L2_cache & l2_cache();
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CORTEX_A9_PRIVATE_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */
|
CORTEX_A9_GLOBAL_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */
|
||||||
CORTEX_A9_PRIVATE_TIMER_DIV = 100,
|
CORTEX_A9_GLOBAL_TIMER_DIV = 100,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <hw/spec/arm/pbxa9_board.h>
|
#include <hw/spec/arm/pbxa9_board.h>
|
||||||
|
|
||||||
/* base-hw Core includes */
|
/* base-hw Core includes */
|
||||||
#include <spec/arm/cortex_a9_private_timer.h>
|
#include <spec/arm/cortex_a9_global_timer.h>
|
||||||
#include <spec/cortex_a9/cpu.h>
|
#include <spec/cortex_a9/cpu.h>
|
||||||
|
|
||||||
namespace Board {
|
namespace Board {
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <hw/spec/arm/wand_quad_board.h>
|
#include <hw/spec/arm/wand_quad_board.h>
|
||||||
|
|
||||||
/* base-hw Core includes */
|
/* base-hw Core includes */
|
||||||
#include <spec/arm/cortex_a9_private_timer.h>
|
#include <spec/arm/cortex_a9_global_timer.h>
|
||||||
#include <spec/cortex_a9/cpu.h>
|
#include <spec/cortex_a9/cpu.h>
|
||||||
|
|
||||||
namespace Board {
|
namespace Board {
|
||||||
@ -35,8 +35,8 @@ namespace Board {
|
|||||||
L2_cache & l2_cache();
|
L2_cache & l2_cache();
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CORTEX_A9_PRIVATE_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */
|
CORTEX_A9_GLOBAL_TIMER_CLK = 500000000, /* timer clk runs half the CPU freq */
|
||||||
CORTEX_A9_PRIVATE_TIMER_DIV = 100,
|
CORTEX_A9_GLOBAL_TIMER_DIV = 100,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
113
repos/base-hw/src/core/spec/arm/cortex_a9_global_timer.cc
Normal file
113
repos/base-hw/src/core/spec/arm/cortex_a9_global_timer.cc
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* \brief Global timer implementation specific to Cortex A9
|
||||||
|
* \author Johannes Schlatow
|
||||||
|
* \date 2023-01-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/timer/util.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <kernel/cpu.h>
|
||||||
|
#include <kernel/timer.h>
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
|
using Device = Board::Timer;
|
||||||
|
using counter_t = Board::Timer::Counter::access_t;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TICS_PER_MS =
|
||||||
|
Board::CORTEX_A9_GLOBAL_TIMER_CLK /
|
||||||
|
Board::CORTEX_A9_GLOBAL_TIMER_DIV / 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Board::Timer::Timer(unsigned cpu_id)
|
||||||
|
:
|
||||||
|
Mmio(Platform::mmio_to_virt(Board::Cpu_mmio::GLOBAL_TIMER_MMIO_BASE))
|
||||||
|
{
|
||||||
|
enum { PRESCALER = Board::CORTEX_A9_GLOBAL_TIMER_DIV - 1 };
|
||||||
|
|
||||||
|
static_assert((TICS_PER_MS >= 1000),
|
||||||
|
"Bad TICS_PER_US value");
|
||||||
|
|
||||||
|
/* primary CPU sets initial timer value */
|
||||||
|
if (cpu_id == 0) {
|
||||||
|
write<Control::Timer_enable>(0);
|
||||||
|
write<Counter>(0, 0);
|
||||||
|
write<Counter>(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Control::access_t control = 0;
|
||||||
|
Control::Irq_enable::set(control, 1);
|
||||||
|
Control::Prescaler::set(control, PRESCALER);
|
||||||
|
Control::Timer_enable::set(control, 1);
|
||||||
|
write<Control>(control);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
time_t Board::Timer::current_ticks() const
|
||||||
|
{
|
||||||
|
uint32_t upper = read<Counter>(1);
|
||||||
|
uint32_t lower = read<Counter>(0);
|
||||||
|
uint32_t upper_new = read<Counter>(1);
|
||||||
|
|
||||||
|
while (upper != upper_new) {
|
||||||
|
upper = upper_new;
|
||||||
|
lower = read<Counter>(0);
|
||||||
|
upper_new = read<Counter>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (time_t)upper << 32 | (time_t)lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Timer::_start_one_shot(time_t const ticks)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* First unset the interrupt flag,
|
||||||
|
* otherwise if the tick is small enough, we loose an interrupt
|
||||||
|
*/
|
||||||
|
_device.write<Device::Interrupt_status::Event>(1);
|
||||||
|
|
||||||
|
/* Disable comparator before setting a new value */
|
||||||
|
_device.write<Device::Control::Comp_enable>(0);
|
||||||
|
|
||||||
|
time_t end_ticks = _device.current_ticks() + ticks;
|
||||||
|
_device.write<Device::Comparator>(end_ticks & 0xFFFFFFFF, 0);
|
||||||
|
_device.write<Device::Comparator>(end_ticks >> 32 , 1);
|
||||||
|
|
||||||
|
/* Enable comparator before setting a new value */
|
||||||
|
_device.write<Device::Control::Comp_enable>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
time_t Timer::ticks_to_us(time_t const ticks) const {
|
||||||
|
return timer_ticks_to_us(ticks, TICS_PER_MS); }
|
||||||
|
|
||||||
|
|
||||||
|
unsigned Timer::interrupt_id() const {
|
||||||
|
return Board::Cpu_mmio::GLOBAL_TIMER_IRQ; }
|
||||||
|
|
||||||
|
|
||||||
|
time_t Timer::us_to_ticks(time_t const us) const {
|
||||||
|
return (us / 1000) * TICS_PER_MS; }
|
||||||
|
|
||||||
|
|
||||||
|
time_t Timer::_duration() const {
|
||||||
|
return _device.current_ticks() - _time; }
|
||||||
|
|
||||||
|
|
||||||
|
time_t Timer::_max_value() const {
|
||||||
|
return TICS_PER_MS * 5000; }
|
66
repos/base-hw/src/core/spec/arm/cortex_a9_global_timer.h
Normal file
66
repos/base-hw/src/core/spec/arm/cortex_a9_global_timer.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* \brief Global timer implementation specific to Cortex A9
|
||||||
|
* \author Johannes Schlatow
|
||||||
|
* \date 2023-01-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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 _SRC__CORE__SPEC__ARM__CORTEX_A9_GLOBAL_TIMER_H_
|
||||||
|
#define _SRC__CORE__SPEC__ARM__CORTEX_A9_GLOBAL_TIMER_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
/* base-hw includes */
|
||||||
|
#include <kernel/types.h>
|
||||||
|
|
||||||
|
namespace Board { class Timer; }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer driver for core
|
||||||
|
*/
|
||||||
|
struct Board::Timer : Genode::Mmio
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Counter value registers
|
||||||
|
*/
|
||||||
|
struct Counter : Register_array<0x0, 32, 2, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer control register
|
||||||
|
*/
|
||||||
|
struct Control : Register<0x8, 32>
|
||||||
|
{
|
||||||
|
struct Timer_enable : Bitfield<0,1> { }; /* enable counting */
|
||||||
|
struct Comp_enable : Bitfield<1,1> { };
|
||||||
|
struct Irq_enable : Bitfield<2,1> { }; /* unmask interrupt */
|
||||||
|
struct Auto_increment : Bitfield<3,1> { };
|
||||||
|
struct Prescaler : Bitfield<8,8> { };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer interrupt status register
|
||||||
|
*/
|
||||||
|
struct Interrupt_status : Register<0xc, 32>
|
||||||
|
{
|
||||||
|
struct Event : Bitfield<0,1> { }; /* if counter hit zero */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparator registers
|
||||||
|
*/
|
||||||
|
struct Comparator : Register_array<0x10, 32, 2, 32> { };
|
||||||
|
|
||||||
|
Kernel::time_t current_ticks() const;
|
||||||
|
|
||||||
|
Timer(unsigned);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _SRC__CORE__SPEC__ARM__CORTEX_A9_GLOBAL_TIMER_H_ */
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Timer implementation specific to Cortex A9
|
|
||||||
* \author Stefan Kalkowski
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2016-01-07
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2016-2017 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <drivers/timer/util.h>
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <kernel/cpu.h>
|
|
||||||
#include <kernel/timer.h>
|
|
||||||
#include <platform.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
using namespace Kernel;
|
|
||||||
|
|
||||||
using Device = Board::Timer;
|
|
||||||
using counter_t = Board::Timer::Counter::access_t;
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TICS_PER_MS =
|
|
||||||
Board::CORTEX_A9_PRIVATE_TIMER_CLK /
|
|
||||||
Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000,
|
|
||||||
|
|
||||||
MAX_COUNTER_VAL = ~(counter_t)0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Board::Timer::Timer(unsigned)
|
|
||||||
:
|
|
||||||
Mmio(Platform::mmio_to_virt(Board::Cpu_mmio::PRIVATE_TIMER_MMIO_BASE))
|
|
||||||
{
|
|
||||||
enum { PRESCALER = Board::CORTEX_A9_PRIVATE_TIMER_DIV - 1 };
|
|
||||||
|
|
||||||
static_assert((TICS_PER_MS >= 1000) /*&&
|
|
||||||
(TICS_PER_US * 1000000 *
|
|
||||||
Board::CORTEX_A9_PRIVATE_TIMER_DIV) ==
|
|
||||||
Board::CORTEX_A9_PRIVATE_TIMER_CLK*/,
|
|
||||||
"Bad TICS_PER_US value");
|
|
||||||
|
|
||||||
write<Load>(0xffffffff);
|
|
||||||
Control::access_t control = 0;
|
|
||||||
Control::Irq_enable::set(control, 1);
|
|
||||||
Control::Prescaler::set(control, PRESCALER);
|
|
||||||
Control::Auto_reload::set(control, 1);
|
|
||||||
Control::Timer_enable::set(control, 1);
|
|
||||||
write<Control>(control);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Timer::_start_one_shot(time_t const ticks)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* First unset the interrupt flag,
|
|
||||||
* otherwise if the tick is small enough, we loose an interrupt
|
|
||||||
*/
|
|
||||||
_device.write<Device::Interrupt_status::Event>(1);
|
|
||||||
_device.write<Device::Counter>(ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
time_t Timer::ticks_to_us(time_t const ticks) const {
|
|
||||||
return timer_ticks_to_us(ticks, TICS_PER_MS); }
|
|
||||||
|
|
||||||
|
|
||||||
unsigned Timer::interrupt_id() const {
|
|
||||||
return Board::Cpu_mmio::PRIVATE_TIMER_IRQ; }
|
|
||||||
|
|
||||||
|
|
||||||
time_t Timer::us_to_ticks(time_t const us) const {
|
|
||||||
return (us / 1000) * TICS_PER_MS; }
|
|
||||||
|
|
||||||
|
|
||||||
time_t Timer::_duration() const
|
|
||||||
{
|
|
||||||
counter_t const start_counter_val { (counter_t)_last_timeout_duration };
|
|
||||||
counter_t const curr_counter_val { _device.read<Device::Counter>() };
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate result depending on whether the counter already wrapped or
|
|
||||||
* not. See the comment in the implementation of '_max_value' for an
|
|
||||||
* explanation why this comparison is done instead of checking the IRQ
|
|
||||||
* status and why it is sufficient.
|
|
||||||
*/
|
|
||||||
if (curr_counter_val > start_counter_val)
|
|
||||||
return start_counter_val + (MAX_COUNTER_VAL - curr_counter_val);
|
|
||||||
|
|
||||||
return start_counter_val - curr_counter_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
time_t Timer::_max_value() const
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We propagate a max timeout value far lower than the one required
|
|
||||||
* by the hardware. This is because on some platforms (Qemu 4.2.1 PBXA9),
|
|
||||||
* the IRQ status register is not reliable. Sometimes, it indicates an IRQ
|
|
||||||
* too early, i.e., shortly before the counter wraps. Therefore we have to
|
|
||||||
* accomplish wrap detection via counter comparison only. Therefore, we
|
|
||||||
* have to make sure that we always read out the counter before it hits
|
|
||||||
* the max timout value again. And, therefore, the max timeout value has
|
|
||||||
* to be far away from the first value the counter has after wrapping.
|
|
||||||
*/
|
|
||||||
return MAX_COUNTER_VAL >> 1;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Private Timer implementation specific to Cortex A9
|
|
||||||
* \author Martin stein
|
|
||||||
* \date 2011-12-13
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2011-2017 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 _SRC__CORE__SPEC__ARM__CORTEX_A9_PRIVATE_TIMER_H_
|
|
||||||
#define _SRC__CORE__SPEC__ARM__CORTEX_A9_PRIVATE_TIMER_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <util/mmio.h>
|
|
||||||
|
|
||||||
namespace Board { class Timer; }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer driver for core
|
|
||||||
*/
|
|
||||||
struct Board::Timer : Genode::Mmio
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Load value register
|
|
||||||
*/
|
|
||||||
struct Load : Register<0x0, 32> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Counter value register
|
|
||||||
*/
|
|
||||||
struct Counter : Register<0x4, 32> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer control register
|
|
||||||
*/
|
|
||||||
struct Control : Register<0x8, 32>
|
|
||||||
{
|
|
||||||
struct Timer_enable : Bitfield<0,1> { }; /* enable counting */
|
|
||||||
struct Auto_reload : Bitfield<1,1> { };
|
|
||||||
struct Irq_enable : Bitfield<2,1> { }; /* unmask interrupt */
|
|
||||||
struct Prescaler : Bitfield<8,8> { };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer interrupt status register
|
|
||||||
*/
|
|
||||||
struct Interrupt_status : Register<0xc, 32>
|
|
||||||
{
|
|
||||||
struct Event : Bitfield<0,1> { }; /* if counter hit zero */
|
|
||||||
};
|
|
||||||
|
|
||||||
Timer(unsigned);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _SRC__CORE__SPEC__ARM__CORTEX_A9_PRIVATE_TIMER_H_ */
|
|
@ -30,9 +30,9 @@ struct Hw::Cortex_a9_mmio
|
|||||||
IRQ_CONTROLLER_CPU_BASE = BASE + 0x100,
|
IRQ_CONTROLLER_CPU_BASE = BASE + 0x100,
|
||||||
IRQ_CONTROLLER_CPU_SIZE = 0x100,
|
IRQ_CONTROLLER_CPU_SIZE = 0x100,
|
||||||
|
|
||||||
PRIVATE_TIMER_MMIO_BASE = BASE + 0x600,
|
GLOBAL_TIMER_MMIO_BASE = BASE + 0x200,
|
||||||
PRIVATE_TIMER_MMIO_SIZE = 0x10,
|
GLOBAL_TIMER_MMIO_SIZE = 0x18,
|
||||||
PRIVATE_TIMER_IRQ = 29,
|
GLOBAL_TIMER_IRQ = 27,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ namespace Pbxa9 {
|
|||||||
SYSTEM_CONTROL_MMIO_BASE = 0x10000000,
|
SYSTEM_CONTROL_MMIO_BASE = 0x10000000,
|
||||||
|
|
||||||
/* CPU */
|
/* CPU */
|
||||||
CORTEX_A9_PRIVATE_TIMER_CLK = 100000000,
|
CORTEX_A9_GLOBAL_TIMER_CLK = 100000000,
|
||||||
CORTEX_A9_PRIVATE_TIMER_DIV = 100,
|
CORTEX_A9_GLOBAL_TIMER_DIV = 100,
|
||||||
CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000,
|
CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000,
|
||||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user