From adfb1a77e22a15f9250a06de86422f4def78192a Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Fri, 24 Nov 2017 13:47:53 +0100 Subject: [PATCH] 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 --- repos/os/src/drivers/timer/epit/epit.h | 195 ------------------ .../os/src/drivers/timer/epit/time_source.cc | 68 +++--- repos/os/src/drivers/timer/epit/time_source.h | 56 +++-- .../src/drivers/timer/epit/wand_quad/timer.cc | 5 +- 4 files changed, 81 insertions(+), 243 deletions(-) delete mode 100644 repos/os/src/drivers/timer/epit/epit.h diff --git a/repos/os/src/drivers/timer/epit/epit.h b/repos/os/src/drivers/timer/epit/epit.h deleted file mode 100644 index 26cdceb5b5..0000000000 --- a/repos/os/src/drivers/timer/epit/epit.h +++ /dev/null @@ -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 - -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()) ; - - /* disable timer */ - write(0); - - /* clear interrupt */ - write(1); - } - - void _start_one_shot(unsigned const tics) - { - /* stop timer */ - _reset(); - - /* configure timer for a one-shot */ - write(Cr::prepare_one_shot()); - write(tics); - write(0); - - /* start timer */ - write(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(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(); - wrapped = (bool)read(); - return wrapped ? read() : cnt; - } - - /** - * Current maximum programmed timeout value - */ - unsigned current_max_value() const { return read(); } -}; - -#endif /* _EPIT_H_ */ diff --git a/repos/os/src/drivers/timer/epit/time_source.cc b/repos/os/src/drivers/timer/epit/time_source.cc index 95ba22755b..ea48d9beed 100644 --- a/repos/os/src/drivers/timer/epit/time_source.cc +++ b/repos/os/src/drivers/timer/epit/time_source.cc @@ -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()) ; + + /* disable timer */ + write(0); + + /* clear interrupt */ + write(1); + + /* configure timer for a one-shot */ + write(Cr::prepare_one_shot()); + write(ticks); + write(0); + + /* start timer */ + write(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(); + Cnt::access_t cnt = read(); + bool const wrapped = read(); - if (_irq && wrapped) - passed_tics += max_value; + /* determine how many ticks have passed */ + if (_irq && wrapped) { + cnt = read(); + 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; } diff --git a/repos/os/src/drivers/timer/epit/time_source.h b/repos/os/src/drivers/timer/epit/time_source.h index 2dd9c49bad..b7dbd03c2e 100644 --- a/repos/os/src/drivers/timer/epit/time_source.h +++ b/repos/os/src/drivers/timer/epit/time_source.h @@ -17,31 +17,51 @@ #define _TIME_SOURCE_H_ /* Genode includes */ -#include #include -#include +#include +#include /* local includes */ #include -#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_ */ diff --git a/repos/os/src/drivers/timer/epit/wand_quad/timer.cc b/repos/os/src/drivers/timer/epit/wand_quad/timer.cc index bf645232bb..f3aeade446 100644 --- a/repos/os/src/drivers/timer/epit/wand_quad/timer.cc +++ b/repos/os/src/drivers/timer/epit/wand_quad/timer.cc @@ -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(_io_mem.local_addr())) + _timer_irq(env, Wand_quad::EPIT_2_IRQ) { _timer_irq.sigh(_signal_handler); }