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:
Martin Stein 2017-11-24 13:47:53 +01:00 committed by Christian Helmuth
parent c9bcce57e8
commit adfb1a77e2
4 changed files with 81 additions and 243 deletions

View File

@ -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_ */

View File

@ -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));
} }

View File

@ -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_ */

View File

@ -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);
} }