mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-13 04:38:20 +00:00
usb rpi: get rid of local hardware timer
We used a hardware timer locally in the RPI USB driver because a timer connection was not precise enough to fullfill the host controllers requirements. With the modern timer connection interface, however, reading out time at a connection is microseconds precise and we can remove the local timer. But we cannot use the same timer connection for doing legacy-interface stuff like usleep (currently used in LX kit) and modern-interface stuff like curr_time. Thus, we open two connections for now. Ref #2400
This commit is contained in:
committed by
Christian Helmuth
parent
b6efa7f6f9
commit
47dc708887
@ -38,9 +38,6 @@ namespace Lx {
|
|||||||
unsigned long *jiffies_ptr = nullptr);
|
unsigned long *jiffies_ptr = nullptr);
|
||||||
|
|
||||||
void timer_update_jiffies();
|
void timer_update_jiffies();
|
||||||
|
|
||||||
typedef unsigned long (*jiffies_update_func)(void);
|
|
||||||
void register_jiffies_func(jiffies_update_func func);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/attached_io_mem_dataspace.h>
|
|
||||||
#include <io_mem_session/connection.h>
|
#include <io_mem_session/connection.h>
|
||||||
#include <util/mmio.h>
|
#include <util/mmio.h>
|
||||||
#include <platform_session/connection.h>
|
#include <platform_session/connection.h>
|
||||||
@ -21,8 +20,7 @@
|
|||||||
/* emulation */
|
/* emulation */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <lx_emul.h>
|
#include <lx_emul.h>
|
||||||
#include <lx_kit/timer.h>
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
|
|
||||||
/* dwc-otg */
|
/* dwc-otg */
|
||||||
#define new new_
|
#define new new_
|
||||||
@ -31,124 +29,9 @@
|
|||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
namespace Genode { template <unsigned long> class Sp804_base; }
|
|
||||||
|
|
||||||
unsigned dwc_irq();
|
unsigned dwc_irq();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic driver for the ARM SP804 timer
|
|
||||||
*/
|
|
||||||
template <unsigned long CLK>
|
|
||||||
class Genode::Sp804_base : public Mmio
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
TICS_PER_MS = CLK / 1000,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds value that shall be loaded to the timer value register
|
|
||||||
*/
|
|
||||||
struct Load : Register<0x0, 32> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer value register
|
|
||||||
*/
|
|
||||||
struct Value : Register<0x4, 32> { enum { MAX_VALUE = 0xffffffff }; };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer control register
|
|
||||||
*/
|
|
||||||
struct Control : Register<0x8, 8>
|
|
||||||
{
|
|
||||||
struct Oneshot : Bitfield<0,1> { };
|
|
||||||
struct Size : Bitfield<1,1> { };
|
|
||||||
struct Pre : Bitfield<2,2> { };
|
|
||||||
struct Int_en : Bitfield<5,1> { };
|
|
||||||
struct Mode : Bitfield<6,1> { };
|
|
||||||
struct Timer_en : Bitfield<7,1> { };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the timer interrupt
|
|
||||||
*/
|
|
||||||
struct Int_clr : Register<0xc, 1> { };
|
|
||||||
|
|
||||||
unsigned _last_tick = Value::MAX_VALUE;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor, clears interrupt output
|
|
||||||
*/
|
|
||||||
Sp804_base(addr_t const mmio_base) : Mmio(mmio_base)
|
|
||||||
{
|
|
||||||
/* clear irq */
|
|
||||||
write<Int_clr>(1);
|
|
||||||
|
|
||||||
/* disabble and configure */
|
|
||||||
write<typename Control::Timer_en>(0);
|
|
||||||
write<Control>(Control::Mode::bits(0) | /* free running */
|
|
||||||
Control::Int_en::bits(0) | /* IRQ disabled */
|
|
||||||
Control::Pre::bits(0) | /* clk divider 1 */
|
|
||||||
Control::Size::bits(1) | /* 32 bit */
|
|
||||||
Control::Oneshot::bits(0)); /* one-shot off */
|
|
||||||
|
|
||||||
/* start */
|
|
||||||
write<Load>(Value::MAX_VALUE);
|
|
||||||
write<typename Control::Timer_en>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long update_jiffies()
|
|
||||||
{
|
|
||||||
unsigned tick = read<Value>();
|
|
||||||
|
|
||||||
/* timer runs backwards */
|
|
||||||
unsigned delta = ticks_to_ms(_last_tick - tick);
|
|
||||||
|
|
||||||
/* delta < 1 jiffie */
|
|
||||||
if (!msecs_to_jiffies(delta))
|
|
||||||
return jiffies;
|
|
||||||
|
|
||||||
jiffies += msecs_to_jiffies(delta);
|
|
||||||
_last_tick = tick;
|
|
||||||
return jiffies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate native timer value to milliseconds
|
|
||||||
*/
|
|
||||||
static unsigned long ticks_to_ms(unsigned long const tics) {
|
|
||||||
return tics / TICS_PER_MS; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum { TIMER_MMIO_BASE = 0x2000b400,
|
|
||||||
TIMER_MMIO_SIZE = 0x100,
|
|
||||||
TIMER_CLOCK = 992*1000 };
|
|
||||||
|
|
||||||
struct Platform_timer : Attached_io_mem_dataspace,
|
|
||||||
Sp804_base<TIMER_CLOCK>
|
|
||||||
{
|
|
||||||
Platform_timer() :
|
|
||||||
Attached_io_mem_dataspace(TIMER_MMIO_BASE, TIMER_MMIO_SIZE),
|
|
||||||
Sp804_base((Genode::addr_t)local_addr<void>())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
static Platform_timer &instance()
|
|
||||||
{
|
|
||||||
static Platform_timer _timer;
|
|
||||||
return _timer;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned long jiffies_update_func()
|
|
||||||
{
|
|
||||||
return Platform_timer::instance().update_jiffies();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************
|
/************************************************
|
||||||
** Resource info passed to the dwc_otg driver **
|
** Resource info passed to the dwc_otg driver **
|
||||||
************************************************/
|
************************************************/
|
||||||
@ -280,12 +163,6 @@ extern "C" int module_smsc95xx_driver_init();
|
|||||||
|
|
||||||
void platform_hcd_init(Services *services)
|
void platform_hcd_init(Services *services)
|
||||||
{
|
{
|
||||||
/* enable timer */
|
|
||||||
Platform_timer::instance();
|
|
||||||
|
|
||||||
/* use costum jiffies update function and the Sp804 timer */
|
|
||||||
Lx::register_jiffies_func(jiffies_update_func);
|
|
||||||
|
|
||||||
/* enable USB power */
|
/* enable USB power */
|
||||||
Platform::Connection platform;
|
Platform::Connection platform;
|
||||||
platform.power_state(Platform::Session::POWER_USB_HCD, true);
|
platform.power_state(Platform::Session::POWER_USB_HCD, true);
|
||||||
|
@ -81,11 +81,11 @@ class Lx_kit::Timer : public Lx::Timer
|
|||||||
|
|
||||||
unsigned long &_jiffies;
|
unsigned long &_jiffies;
|
||||||
::Timer::Connection _timer_conn;
|
::Timer::Connection _timer_conn;
|
||||||
|
::Timer::Connection _timer_conn_modern;
|
||||||
Lx_kit::List<Context> _list;
|
Lx_kit::List<Context> _list;
|
||||||
Lx::Task _timer_task;
|
Lx::Task _timer_task;
|
||||||
Genode::Signal_handler<Lx_kit::Timer> _dispatcher;
|
Genode::Signal_handler<Lx_kit::Timer> _dispatcher;
|
||||||
Genode::Tslab<Context, 32 * sizeof(Context)> _timer_alloc;
|
Genode::Tslab<Context, 32 * sizeof(Context)> _timer_alloc;
|
||||||
Lx::jiffies_update_func _jiffies_func = nullptr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup local timer
|
* Lookup local timer
|
||||||
@ -177,6 +177,7 @@ class Lx_kit::Timer : public Lx::Timer
|
|||||||
:
|
:
|
||||||
_jiffies(jiffies),
|
_jiffies(jiffies),
|
||||||
_timer_conn(env),
|
_timer_conn(env),
|
||||||
|
_timer_conn_modern(env),
|
||||||
_timer_task(Timer::run_timer, reinterpret_cast<void*>(this),
|
_timer_task(Timer::run_timer, reinterpret_cast<void*>(this),
|
||||||
"timer", Lx::Task::PRIORITY_2, Lx::scheduler()),
|
"timer", Lx::Task::PRIORITY_2, Lx::scheduler()),
|
||||||
_dispatcher(ep, *this, &Lx_kit::Timer::_handle),
|
_dispatcher(ep, *this, &Lx_kit::Timer::_handle),
|
||||||
@ -292,10 +293,7 @@ class Lx_kit::Timer : public Lx::Timer
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update_jiffies() {
|
void update_jiffies() {
|
||||||
_jiffies = _jiffies_func ? _jiffies_func() : msecs_to_jiffies(_timer_conn.elapsed_ms()); }
|
_jiffies = usecs_to_jiffies(_timer_conn_modern.curr_time().trunc_to_plain_us().value); }
|
||||||
|
|
||||||
void register_jiffies_func(Lx::jiffies_update_func func) {
|
|
||||||
_jiffies_func = func; }
|
|
||||||
|
|
||||||
void usleep(unsigned us) {
|
void usleep(unsigned us) {
|
||||||
_timer_conn.usleep(us); }
|
_timer_conn.usleep(us); }
|
||||||
@ -319,9 +317,3 @@ void Lx::timer_update_jiffies()
|
|||||||
{
|
{
|
||||||
timer().update_jiffies();
|
timer().update_jiffies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Lx::register_jiffies_func(jiffies_update_func func)
|
|
||||||
{
|
|
||||||
dynamic_cast<Lx_kit::Timer &>(timer()).register_jiffies_func(func);
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user