mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
timer/epit: remove unused code
* use correct/more modern types * get rid of old code that was for the public use of the EPIT backend * merge Epit_base into Time_source
This commit is contained in:
parent
c9bcce57e8
commit
adfb1a77e2
@ -1,195 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Driver base for the Enhanced Periodic Interrupt Timer (Freescale)
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Martin Stein
|
|
||||||
* \author Stefan Kalkowski
|
|
||||||
* \date 2012-10-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU General Public License version 2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _EPIT_H_
|
|
||||||
#define _EPIT_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <util/mmio.h>
|
|
||||||
|
|
||||||
namespace Genode { class Epit_base; }
|
|
||||||
|
|
||||||
|
|
||||||
class Genode::Epit_base : public Mmio
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
enum { TICS_PER_MS = 66000 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Control register
|
|
||||||
*/
|
|
||||||
struct Cr : Register<0x0, 32>
|
|
||||||
{
|
|
||||||
struct En : Bitfield<0, 1> { }; /* enable timer */
|
|
||||||
|
|
||||||
struct En_mod : Bitfield<1, 1> /* reload on enable */
|
|
||||||
{
|
|
||||||
enum { RELOAD = 1 };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Oci_en : Bitfield<2, 1> { }; /* interrupt on compare */
|
|
||||||
|
|
||||||
struct Rld : Bitfield<3, 1> /* reload or roll-over */
|
|
||||||
{
|
|
||||||
enum { RELOAD_FROM_LR = 1 };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Prescaler : Bitfield<4, 12> /* clock input divisor */
|
|
||||||
{
|
|
||||||
enum { DIVIDE_BY_1 = 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Swr : Bitfield<16, 1> { }; /* software reset bit */
|
|
||||||
struct Iovw : Bitfield<17, 1> { }; /* enable overwrite */
|
|
||||||
struct Dbg_en : Bitfield<18, 1> { }; /* enable in debug mode */
|
|
||||||
struct Wait_en : Bitfield<19, 1> { }; /* enable in wait mode */
|
|
||||||
struct Doz_en : Bitfield<20, 1> { }; /* enable in doze mode */
|
|
||||||
struct Stop_en : Bitfield<21, 1> { }; /* enable in stop mode */
|
|
||||||
|
|
||||||
struct Om : Bitfield<22, 2> /* mode of the output pin */
|
|
||||||
{
|
|
||||||
enum { DISCONNECTED = 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Clk_src : Bitfield<24, 2> /* select clock input */
|
|
||||||
{
|
|
||||||
enum { HIGH_FREQ_REF_CLK = 2 };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register value that configures the timer for a one-shot run
|
|
||||||
*/
|
|
||||||
static access_t prepare_one_shot()
|
|
||||||
{
|
|
||||||
return En::bits(0) |
|
|
||||||
En_mod::bits(En_mod::RELOAD) |
|
|
||||||
Oci_en::bits(1) |
|
|
||||||
Rld::bits(Rld::RELOAD_FROM_LR) |
|
|
||||||
Prescaler::bits(Prescaler::DIVIDE_BY_1) |
|
|
||||||
Swr::bits(0) |
|
|
||||||
Iovw::bits(0) |
|
|
||||||
Dbg_en::bits(0) |
|
|
||||||
Wait_en::bits(0) |
|
|
||||||
Doz_en::bits(0) |
|
|
||||||
Stop_en::bits(0) |
|
|
||||||
Om::bits(Om::DISCONNECTED) |
|
|
||||||
Clk_src::bits(Clk_src::HIGH_FREQ_REF_CLK);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status register
|
|
||||||
*/
|
|
||||||
struct Sr : Register<0x4, 32>
|
|
||||||
{
|
|
||||||
struct Ocif : Bitfield<0, 1> { }; /* IRQ status, write 1 clears */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Lr : Register<0x8, 32> { }; /* load value register */
|
|
||||||
struct Cmpr : Register<0xc, 32> { }; /* compare value register */
|
|
||||||
struct Cnt : Register<0x10, 32> { }; /* counter register */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable timer and clear its interrupt output
|
|
||||||
*/
|
|
||||||
void _reset()
|
|
||||||
{
|
|
||||||
/* wait until ongoing reset operations are finished */
|
|
||||||
while (read<Cr::Swr>()) ;
|
|
||||||
|
|
||||||
/* disable timer */
|
|
||||||
write<Cr::En>(0);
|
|
||||||
|
|
||||||
/* clear interrupt */
|
|
||||||
write<Sr::Ocif>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _start_one_shot(unsigned const tics)
|
|
||||||
{
|
|
||||||
/* stop timer */
|
|
||||||
_reset();
|
|
||||||
|
|
||||||
/* configure timer for a one-shot */
|
|
||||||
write<Cr>(Cr::prepare_one_shot());
|
|
||||||
write<Lr>(tics);
|
|
||||||
write<Cmpr>(0);
|
|
||||||
|
|
||||||
/* start timer */
|
|
||||||
write<Cr::En>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Epit_base(addr_t base) : Mmio(base) { _reset(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start single timeout run
|
|
||||||
*
|
|
||||||
* \param tics delay of timer interrupt
|
|
||||||
*/
|
|
||||||
void start_one_shot(unsigned const tics)
|
|
||||||
{
|
|
||||||
_start_one_shot(tics);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the timer from a one-shot run
|
|
||||||
*
|
|
||||||
* \return last native timer value of the one-shot run
|
|
||||||
*/
|
|
||||||
unsigned stop_one_shot(bool &wrap)
|
|
||||||
{
|
|
||||||
/* disable timer */
|
|
||||||
write<Cr::En>(0);
|
|
||||||
return value(wrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate microseconds to a native timer value
|
|
||||||
*/
|
|
||||||
unsigned us_to_tics(unsigned const us) const
|
|
||||||
{
|
|
||||||
return (1ULL * us * TICS_PER_MS) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate native timer value to microseconds
|
|
||||||
*/
|
|
||||||
unsigned tics_to_us(unsigned const tics) const
|
|
||||||
{
|
|
||||||
return (1ULL * tics * 1000) / TICS_PER_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return current native timer value
|
|
||||||
*/
|
|
||||||
unsigned value(bool &wrapped) const
|
|
||||||
{
|
|
||||||
unsigned cnt = read<Cnt>();
|
|
||||||
wrapped = (bool)read<Sr::Ocif>();
|
|
||||||
return wrapped ? read<Cnt>() : cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current maximum programmed timeout value
|
|
||||||
*/
|
|
||||||
unsigned current_max_value() const { return read<Lr>(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _EPIT_H_ */
|
|
@ -19,47 +19,61 @@
|
|||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
Microseconds Timer::Time_source::max_timeout() const {
|
|
||||||
return Microseconds(_epit.tics_to_us(~0U)); }
|
|
||||||
|
|
||||||
void Timer::Time_source::schedule_timeout(Microseconds duration,
|
void Timer::Time_source::schedule_timeout(Genode::Microseconds duration,
|
||||||
Timeout_handler &handler)
|
Timeout_handler &handler)
|
||||||
{
|
{
|
||||||
/*
|
/* on duration 0 trigger directly at function end and set max timeout */
|
||||||
* Program max timeout in case of duration 0 to avoid lost of accuracy
|
unsigned long const us = duration.value ? duration.value
|
||||||
* due to wraps when value is chosen too small. Send instead a signal
|
: max_timeout().value;
|
||||||
* manually at end of this method.
|
unsigned long const ticks = (1ULL * us * TICKS_PER_MS) / 1000;
|
||||||
*/
|
|
||||||
unsigned const tics = _epit.us_to_tics(duration.value ? duration.value
|
|
||||||
: max_timeout().value);
|
|
||||||
|
|
||||||
_handler = &handler;
|
_handler = &handler;
|
||||||
|
|
||||||
_timer_irq.ack_irq();
|
_timer_irq.ack_irq();
|
||||||
|
|
||||||
_epit.start_one_shot(tics);
|
/* wait until ongoing reset operations are finished */
|
||||||
|
while (read<Cr::Swr>()) ;
|
||||||
|
|
||||||
|
/* disable timer */
|
||||||
|
write<Cr::En>(0);
|
||||||
|
|
||||||
|
/* clear interrupt */
|
||||||
|
write<Sr::Ocif>(1);
|
||||||
|
|
||||||
|
/* configure timer for a one-shot */
|
||||||
|
write<Cr>(Cr::prepare_one_shot());
|
||||||
|
write<Lr>(ticks);
|
||||||
|
write<Cmpr>(0);
|
||||||
|
|
||||||
|
/* start timer */
|
||||||
|
write<Cr::En>(1);
|
||||||
|
|
||||||
/* trigger for a timeout 0 immediately the signal */
|
/* trigger for a timeout 0 immediately the signal */
|
||||||
if (!duration.value)
|
if (!duration.value) {
|
||||||
Signal_transmitter(_signal_handler).submit();
|
Signal_transmitter(_signal_handler).submit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Duration Timer::Time_source::curr_time()
|
Duration Timer::Time_source::curr_time()
|
||||||
{
|
{
|
||||||
/* read EPIT status */
|
/* read timer status */
|
||||||
bool wrapped = false;
|
unsigned long diff_ticks = 0;
|
||||||
unsigned const max_value = _epit.current_max_value();
|
Lr::access_t const max_value = read<Lr>();
|
||||||
unsigned const tic_value = _epit.value(wrapped);
|
Cnt::access_t cnt = read<Cnt>();
|
||||||
unsigned passed_tics = 0;
|
bool const wrapped = read<Sr::Ocif>();
|
||||||
|
|
||||||
if (_irq && wrapped)
|
/* determine how many ticks have passed */
|
||||||
passed_tics += max_value;
|
if (_irq && wrapped) {
|
||||||
|
cnt = read<Cnt>();
|
||||||
|
diff_ticks += max_value;
|
||||||
|
}
|
||||||
|
diff_ticks += max_value - cnt;
|
||||||
|
unsigned long const diff_us = timer_ticks_to_us(diff_ticks, TICKS_PER_MS);
|
||||||
|
|
||||||
passed_tics += max_value - tic_value;
|
/* update time only on IRQs and if rate is under 1000 per second */
|
||||||
|
if (_irq || diff_us > 1000) {
|
||||||
if (_irq || _epit.tics_to_us(passed_tics) > 1000)
|
_curr_time.add(Genode::Microseconds(diff_us));
|
||||||
_curr_time_us += _epit.tics_to_us(passed_tics);
|
}
|
||||||
|
return _curr_time;
|
||||||
return Duration(Microseconds(_curr_time_us));
|
|
||||||
}
|
}
|
||||||
|
@ -17,31 +17,51 @@
|
|||||||
#define _TIME_SOURCE_H_
|
#define _TIME_SOURCE_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/attached_io_mem_dataspace.h>
|
|
||||||
#include <irq_session/connection.h>
|
#include <irq_session/connection.h>
|
||||||
#include <os/duration.h>
|
#include <os/attached_mmio.h>
|
||||||
|
#include <drivers/timer/util.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <signalled_time_source.h>
|
#include <signalled_time_source.h>
|
||||||
|
|
||||||
#include "epit.h"
|
namespace Timer { class Time_source; }
|
||||||
|
|
||||||
namespace Timer {
|
|
||||||
|
|
||||||
using Microseconds = Genode::Microseconds;
|
|
||||||
using Duration = Genode::Duration;
|
|
||||||
class Time_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Timer::Time_source : public Genode::Signalled_time_source
|
class Timer::Time_source : public Genode::Attached_mmio,
|
||||||
|
public Genode::Signalled_time_source
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Attached_io_mem_dataspace _io_mem;
|
enum { TICKS_PER_MS = 66000 };
|
||||||
Genode::Irq_connection _timer_irq;
|
|
||||||
Genode::Epit_base _epit;
|
struct Cr : Register<0x0, 32>
|
||||||
unsigned long long mutable _curr_time_us { 0 };
|
{
|
||||||
|
struct En : Bitfield<0, 1> { };
|
||||||
|
struct En_mod : Bitfield<1, 1> { enum { RELOAD = 1 }; };
|
||||||
|
struct Oci_en : Bitfield<2, 1> { };
|
||||||
|
struct Rld : Bitfield<3, 1> { enum { RELOAD_FROM_LR = 1 }; };
|
||||||
|
struct Swr : Bitfield<16, 1> { };
|
||||||
|
struct Clk_src : Bitfield<24, 2> { enum { HIGH_FREQ_REF_CLK = 2 }; };
|
||||||
|
|
||||||
|
static access_t prepare_one_shot()
|
||||||
|
{
|
||||||
|
access_t cr = 0;
|
||||||
|
En_mod::set(cr, En_mod::RELOAD);
|
||||||
|
Oci_en::set(cr, 1);
|
||||||
|
Rld::set(cr, Rld::RELOAD_FROM_LR);
|
||||||
|
Clk_src::set(cr, Clk_src::HIGH_FREQ_REF_CLK);
|
||||||
|
return cr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sr : Register<0x4, 32> { struct Ocif : Bitfield<0, 1> { }; };
|
||||||
|
struct Lr : Register<0x8, 32> { };
|
||||||
|
struct Cmpr : Register<0xc, 32> { };
|
||||||
|
struct Cnt : Register<0x10, 32> { };
|
||||||
|
|
||||||
|
Genode::Irq_connection _timer_irq;
|
||||||
|
Genode::Duration _curr_time { Genode::Microseconds(0) };
|
||||||
|
Genode::Microseconds const _max_timeout { Genode::timer_ticks_to_us(~0U, TICKS_PER_MS) };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -52,9 +72,9 @@ class Timer::Time_source : public Genode::Signalled_time_source
|
|||||||
** Genode::Time_source **
|
** Genode::Time_source **
|
||||||
*************************/
|
*************************/
|
||||||
|
|
||||||
Duration curr_time() override;
|
Genode::Duration curr_time() override;
|
||||||
void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
|
void schedule_timeout(Genode::Microseconds duration, Timeout_handler &handler) override;
|
||||||
Microseconds max_timeout() const override;
|
Genode::Microseconds max_timeout() const override { return _max_timeout; };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _TIME_SOURCE_H_ */
|
#endif /* _TIME_SOURCE_H_ */
|
||||||
|
@ -24,10 +24,9 @@ using namespace Genode;
|
|||||||
|
|
||||||
Timer::Time_source::Time_source(Env &env)
|
Timer::Time_source::Time_source(Env &env)
|
||||||
:
|
:
|
||||||
|
Attached_mmio(env, Wand_quad::EPIT_2_MMIO_BASE, Wand_quad::EPIT_2_MMIO_SIZE),
|
||||||
Signalled_time_source(env),
|
Signalled_time_source(env),
|
||||||
_io_mem(env, Wand_quad::EPIT_2_MMIO_BASE, Wand_quad::EPIT_2_MMIO_SIZE),
|
_timer_irq(env, Wand_quad::EPIT_2_IRQ)
|
||||||
_timer_irq(env, Wand_quad::EPIT_2_IRQ),
|
|
||||||
_epit(reinterpret_cast<addr_t>(_io_mem.local_addr<addr_t>()))
|
|
||||||
{
|
{
|
||||||
_timer_irq.sigh(_signal_handler);
|
_timer_irq.sigh(_signal_handler);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user