mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 22:47:50 +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;
|
||||
|
||||
Microseconds Timer::Time_source::max_timeout() const {
|
||||
return Microseconds(_epit.tics_to_us(~0U)); }
|
||||
|
||||
void Timer::Time_source::schedule_timeout(Microseconds duration,
|
||||
Timeout_handler &handler)
|
||||
void Timer::Time_source::schedule_timeout(Genode::Microseconds duration,
|
||||
Timeout_handler &handler)
|
||||
{
|
||||
/*
|
||||
* Program max timeout in case of duration 0 to avoid lost of accuracy
|
||||
* due to wraps when value is chosen too small. Send instead a signal
|
||||
* manually at end of this method.
|
||||
*/
|
||||
unsigned const tics = _epit.us_to_tics(duration.value ? duration.value
|
||||
: max_timeout().value);
|
||||
/* on duration 0 trigger directly at function end and set max timeout */
|
||||
unsigned long const us = duration.value ? duration.value
|
||||
: max_timeout().value;
|
||||
unsigned long const ticks = (1ULL * us * TICKS_PER_MS) / 1000;
|
||||
|
||||
_handler = &handler;
|
||||
|
||||
_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 */
|
||||
if (!duration.value)
|
||||
if (!duration.value) {
|
||||
Signal_transmitter(_signal_handler).submit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Duration Timer::Time_source::curr_time()
|
||||
{
|
||||
/* read EPIT status */
|
||||
bool wrapped = false;
|
||||
unsigned const max_value = _epit.current_max_value();
|
||||
unsigned const tic_value = _epit.value(wrapped);
|
||||
unsigned passed_tics = 0;
|
||||
/* read timer status */
|
||||
unsigned long diff_ticks = 0;
|
||||
Lr::access_t const max_value = read<Lr>();
|
||||
Cnt::access_t cnt = read<Cnt>();
|
||||
bool const wrapped = read<Sr::Ocif>();
|
||||
|
||||
if (_irq && wrapped)
|
||||
passed_tics += max_value;
|
||||
/* determine how many ticks have passed */
|
||||
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;
|
||||
|
||||
if (_irq || _epit.tics_to_us(passed_tics) > 1000)
|
||||
_curr_time_us += _epit.tics_to_us(passed_tics);
|
||||
|
||||
return Duration(Microseconds(_curr_time_us));
|
||||
/* update time only on IRQs and if rate is under 1000 per second */
|
||||
if (_irq || diff_us > 1000) {
|
||||
_curr_time.add(Genode::Microseconds(diff_us));
|
||||
}
|
||||
return _curr_time;
|
||||
}
|
||||
|
@ -17,31 +17,51 @@
|
||||
#define _TIME_SOURCE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
#include <irq_session/connection.h>
|
||||
#include <os/duration.h>
|
||||
#include <os/attached_mmio.h>
|
||||
#include <drivers/timer/util.h>
|
||||
|
||||
/* local includes */
|
||||
#include <signalled_time_source.h>
|
||||
|
||||
#include "epit.h"
|
||||
|
||||
namespace Timer {
|
||||
|
||||
using Microseconds = Genode::Microseconds;
|
||||
using Duration = Genode::Duration;
|
||||
class Time_source;
|
||||
}
|
||||
namespace Timer { 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:
|
||||
|
||||
Genode::Attached_io_mem_dataspace _io_mem;
|
||||
Genode::Irq_connection _timer_irq;
|
||||
Genode::Epit_base _epit;
|
||||
unsigned long long mutable _curr_time_us { 0 };
|
||||
enum { TICKS_PER_MS = 66000 };
|
||||
|
||||
struct Cr : Register<0x0, 32>
|
||||
{
|
||||
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:
|
||||
|
||||
@ -52,9 +72,9 @@ class Timer::Time_source : public Genode::Signalled_time_source
|
||||
** Genode::Time_source **
|
||||
*************************/
|
||||
|
||||
Duration curr_time() override;
|
||||
void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
|
||||
Microseconds max_timeout() const override;
|
||||
Genode::Duration curr_time() override;
|
||||
void schedule_timeout(Genode::Microseconds duration, Timeout_handler &handler) override;
|
||||
Genode::Microseconds max_timeout() const override { return _max_timeout; };
|
||||
};
|
||||
|
||||
#endif /* _TIME_SOURCE_H_ */
|
||||
|
@ -24,10 +24,9 @@ using namespace Genode;
|
||||
|
||||
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),
|
||||
_io_mem(env, Wand_quad::EPIT_2_MMIO_BASE, Wand_quad::EPIT_2_MMIO_SIZE),
|
||||
_timer_irq(env, Wand_quad::EPIT_2_IRQ),
|
||||
_epit(reinterpret_cast<addr_t>(_io_mem.local_addr<addr_t>()))
|
||||
_timer_irq(env, Wand_quad::EPIT_2_IRQ)
|
||||
{
|
||||
_timer_irq.sigh(_signal_handler);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user