From 65136c22896e0642582cbbd84a66f7f423d3341b Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 4 Apr 2013 15:00:46 +0200 Subject: [PATCH] hw_arndale: use core local timer in kernel Ref #706 --- base-hw/src/core/arndale/timer.h | 10 +- base-hw/src/core/timer/exynos_mct.h | 160 +++++++++++++++++ base-hw/src/core/timer/exynos_pwm.h | 166 ------------------ .../platform/arndale/drivers/board_base.h | 5 + 4 files changed, 170 insertions(+), 171 deletions(-) create mode 100644 base-hw/src/core/timer/exynos_mct.h delete mode 100644 base-hw/src/core/timer/exynos_pwm.h diff --git a/base-hw/src/core/arndale/timer.h b/base-hw/src/core/arndale/timer.h index 26853ff173..777fec7370 100644 --- a/base-hw/src/core/arndale/timer.h +++ b/base-hw/src/core/arndale/timer.h @@ -16,24 +16,24 @@ /* core includes */ #include -#include +#include namespace Kernel { /** * Kernel timer */ - class Timer : public Exynos_pwm::Timer + class Timer : public Exynos_mct::Timer { public: - enum { IRQ = Genode::Board::PWM_IRQ_0 }; + enum { IRQ = Genode::Board::MCT_IRQ_L0 }; /** * Constructor */ - Timer() : Exynos_pwm::Timer(Genode::Board::PWM_MMIO_BASE, - Genode::Board::PWM_CLOCK) { } + Timer() : Exynos_mct::Timer(Genode::Board::MCT_MMIO_BASE, + Genode::Board::MCT_CLOCK) { } }; } diff --git a/base-hw/src/core/timer/exynos_mct.h b/base-hw/src/core/timer/exynos_mct.h new file mode 100644 index 0000000000..fced8e0d6e --- /dev/null +++ b/base-hw/src/core/timer/exynos_mct.h @@ -0,0 +1,160 @@ +/* + * \brief Timer for core + * \author Martin stein + * \date 2013-01-10 + */ + +/* + * Copyright (C) 2013 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 _TIMER__EXYNOS_MCT_H_ +#define _TIMER__EXYNOS_MCT_H_ + +/* Genode includes */ +#include + +namespace Exynos_mct +{ + using namespace Genode; + + /** + * Timer for core + */ + class Timer : public Mmio + { + enum { + PRESCALER = 1, + DIV_MUX = 0, + }; + + /** + * MCT configuration + */ + struct Mct_cfg : Register<0x0, 32> + { + struct Prescaler : Bitfield<0, 8> { }; + struct Div_mux : Bitfield<8, 3> { }; + struct Tick_mon_sel : Bitfield<11, 2> { }; + struct Int_mon_sel : Bitfield<13, 3> { }; + + /** + * Initialization value + */ + static access_t init_value() + { + return Prescaler::bits(PRESCALER) | + Div_mux::bits(DIV_MUX) | + Tick_mon_sel::bits(0) | + Int_mon_sel::bits(0); + } + }; + + /** + * Local timer 0 free running counter buffer + */ + struct L0_frcntb : Register<0x310, 32> { }; + + /** + * Local timer 0 free running counter observation + */ + struct L0_frcnto : Register<0x314, 32> { }; + + /** + * Local timer 0 configuration + */ + struct L0_tcon : Register<0x320, 32> { + struct Frc_start : Bitfield<3, 1> { }; + }; + + /** + * Local timer 0 expired status + */ + struct L0_int_cstat : Register<0x330, 32, true> { + struct Frcnt : Bitfield<1, 1> { }; + }; + + /** + * Local timer 0 interrupt enable + */ + struct L0_int_enb : Register<0x334, 32> { + struct Frceie : Bitfield<1, 1> { }; + }; + + /** + * Local timer 0 write status + */ + struct L0_wstat : Register<0x340, 32, true> { + struct Frcntb : Bitfield<2, 1> { }; + struct Tcon : Bitfield<3, 1> { }; + }; + + /** + * Write to reg that replies via ack bit and clear ack bit + */ + template + void _acked_write(typename DEST::Register_base::access_t const v) + { + typedef typename DEST::Register_base Dest; + typedef typename ACK::Bitfield_base Ack; + write(v); + while (!read()); + write(1); + } + + float const _tics_per_ms; + + /** + * Start and stop counting + */ + void _run(bool const run) { + _acked_write + (L0_tcon::Frc_start::bits(run)); } + + public: + + /** + * Constructor + */ + Timer(addr_t const base, unsigned const clk) + : Mmio(base), _tics_per_ms((float)clk / (PRESCALER + 1) / (1 << DIV_MUX) / 1000) + { + write(Mct_cfg::init_value()); + write(L0_int_enb::Frceie::bits(1)); + } + + /** + * Start a one-shot run + * + * \param tics native timer value used to assess the delay + * of the timer interrupt as of the call + */ + inline void start_one_shot(unsigned const tics) + { + _run(0); + _acked_write(tics); + _run(1); + } + + /** + * Translate milliseconds to a native timer value + */ + unsigned ms_to_tics(unsigned const ms) { + return ms * _tics_per_ms; } + + /** + * Stop the timer and return last timer value + */ + unsigned stop_one_shot() { return read(); } + + /** + * Clear interrupt output line + */ + void clear_interrupt() { write(1); } + }; +} + +#endif /* _TIMER__EXYNOS_MCT_H_ */ diff --git a/base-hw/src/core/timer/exynos_pwm.h b/base-hw/src/core/timer/exynos_pwm.h deleted file mode 100644 index 888b2b4322..0000000000 --- a/base-hw/src/core/timer/exynos_pwm.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * \brief Timer for core - * \author Martin stein - * \date 2013-01-10 - */ - -/* - * Copyright (C) 2013 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 _TIMER__EXYNOS_PWM_H_ -#define _TIMER__EXYNOS_PWM_H_ - -/* Genode includes */ -#include - -namespace Exynos_pwm -{ - using namespace Genode; - - /** - * Timer for core - * - * Exynos 5 PWM timer provides 5 independent 32 bit down count timers. - * This driver uses timer 0 only. - */ - class Timer : public Mmio - { - enum { PRESCALER = 2 }; - - /** - * Timer configuration 0 - */ - struct Cfg0 : Register<0x0, 32> - { - struct Prescaler0 : Bitfield<0, 8> - { - enum { DEFAULT = PRESCALER - 1 }; - }; - }; - - /** - * Timer configuration 1 - */ - struct Cfg1 : Register<0x4, 32> - { - struct Div0 : Bitfield<0, 4> { enum { DISABLE = 0 }; }; - }; - - /** - * Timer control - */ - struct Con : Register<0x8, 32> - { - struct Enable0 : Bitfield<0, 1> { }; - struct Update0 : Bitfield<1, 1> { }; - struct Invert_tout0 : Bitfield<2, 1> { }; - struct Auto_reload0 : Bitfield<3, 1> { }; - struct Deadzone_en : Bitfield<4, 1> { }; - - /** - * Initialization value - */ - static access_t init_value() - { - return Invert_tout0::bits(0) | - Auto_reload0::bits(0) | - Deadzone_en::bits(0); - } - }; - - /** - * Timer 0 count buffer - */ - struct Cntb0 : Register<0xc, 32> { }; - - /** - * Timer 0 compare buffer - */ - struct Cmpb0 : Register<0x10, 32> { }; - - /** - * Timer 0 count observation - */ - struct Cnto0 : Register<0x14, 32> { }; - - /** - * Timer IRQ control and status - */ - struct Int : Register<0x44, 32> - { - struct En0 : Bitfield<0, 1> { }; - struct En1 : Bitfield<1, 1> { }; - struct En2 : Bitfield<2, 1> { }; - struct En3 : Bitfield<3, 1> { }; - struct En4 : Bitfield<4, 1> { }; - struct Stat0 : Bitfield<5, 1> { }; - - /** - * Initialization value - */ - static access_t init_value() - { - return En0::bits(1) | - En1::bits(0) | - En2::bits(0) | - En3::bits(0) | - En4::bits(0); - } - }; - - float const _tics_per_ms; - - public: - - /** - * Constructor - */ - Timer(addr_t const base, unsigned const clk) - : Mmio(base), _tics_per_ms((float)clk / PRESCALER / 1000) - { - write(Cfg0::Prescaler0::DEFAULT); - write(Cfg1::Div0::DISABLE); - write(Int::init_value()); - write(Con::init_value()); - write(0); - } - - /** - * Start a one-shot run - * - * \param tics native timer value used to assess the delay - * of the timer interrupt as of the call - */ - inline void start_one_shot(uint32_t const tics) - { - write(tics); - write(0); - write(1); - write(0); - write(1); - } - - /** - * Translate milliseconds to a native timer value - */ - uint32_t ms_to_tics(unsigned const ms) { - return ms * _tics_per_ms; } - - /** - * Stop the timer and return last timer value - */ - unsigned stop_one_shot() { return read(); } - - /** - * Clear interrupt output line - */ - void clear_interrupt() { write(1); } - }; -} - -#endif /* _TIMER__EXYNOS_PWM_H_ */ - diff --git a/base/include/platform/arndale/drivers/board_base.h b/base/include/platform/arndale/drivers/board_base.h index d803a0c5fd..aef8878841 100644 --- a/base/include/platform/arndale/drivers/board_base.h +++ b/base/include/platform/arndale/drivers/board_base.h @@ -41,8 +41,13 @@ namespace Genode /* timer */ PWM_MMIO_BASE = 0x12dd0000, + PWM_MMIO_SIZE = 0x1000, PWM_CLOCK = 66000000, PWM_IRQ_0 = 68, + MCT_MMIO_BASE = 0x101c0000, + MCT_MMIO_SIZE = 0x1000, + MCT_CLOCK = 24000000, + MCT_IRQ_L0 = 152, /* if board provides security extension */ SECURITY_EXTENSION = 1,