From 4bcd9169c0098b10ae295e46e048a8df3df0136f Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Tue, 16 Apr 2019 13:21:31 +0200 Subject: [PATCH] sel4: add timer for imx7d_sabre Fix #3292 --- .../src/timer/gpt/imx7d_sabre/target.mk | 1 + repos/base/src/timer/gpt/imx7/target.inc | 9 +++ repos/base/src/timer/gpt/imx7/timer.cc | 29 +++++++ repos/base/src/timer/gpt/time_source.cc | 76 +++++++++++++++++++ repos/base/src/timer/gpt/time_source.h | 76 +++++++++++++++++++ tool/run/boot_dir/sel4 | 5 +- 6 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 repos/base-sel4/src/timer/gpt/imx7d_sabre/target.mk create mode 100644 repos/base/src/timer/gpt/imx7/target.inc create mode 100644 repos/base/src/timer/gpt/imx7/timer.cc create mode 100644 repos/base/src/timer/gpt/time_source.cc create mode 100644 repos/base/src/timer/gpt/time_source.h diff --git a/repos/base-sel4/src/timer/gpt/imx7d_sabre/target.mk b/repos/base-sel4/src/timer/gpt/imx7d_sabre/target.mk new file mode 100644 index 000000000..9964666a4 --- /dev/null +++ b/repos/base-sel4/src/timer/gpt/imx7d_sabre/target.mk @@ -0,0 +1 @@ +include $(call select_from_repositories,src/timer/gpt/imx7/target.inc) diff --git a/repos/base/src/timer/gpt/imx7/target.inc b/repos/base/src/timer/gpt/imx7/target.inc new file mode 100644 index 000000000..88b315697 --- /dev/null +++ b/repos/base/src/timer/gpt/imx7/target.inc @@ -0,0 +1,9 @@ +TARGET = imx7_timer_drv +REQUIRES = arm_v7 +GEN_DIR := $(BASE_DIR)/src/timer +INC_DIR += $(GEN_DIR)/gpt +SRC_CC += gpt/time_source.cc gpt/imx7/timer.cc + +include $(GEN_DIR)/target.inc + +vpath %.cc $(GEN_DIR) diff --git a/repos/base/src/timer/gpt/imx7/timer.cc b/repos/base/src/timer/gpt/imx7/timer.cc new file mode 100644 index 000000000..b7d841ec5 --- /dev/null +++ b/repos/base/src/timer/gpt/imx7/timer.cc @@ -0,0 +1,29 @@ +/* + * \brief Time source for i.MX7 (GPT1) + * \author Stefan Kalkowski + * \date 2019-04-13 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* local include */ +#include + +using namespace Genode; + +enum { + MMIO_BASE = 0x302d0000, + MMIO_SIZE = 0x1000, + IRQ = 87, +}; + + +Timer::Time_source::Time_source(Env &env) +: Attached_mmio(env, MMIO_BASE, MMIO_SIZE), + Signalled_time_source(env), + _timer_irq(env, IRQ) { _initialize(); } diff --git a/repos/base/src/timer/gpt/time_source.cc b/repos/base/src/timer/gpt/time_source.cc new file mode 100644 index 000000000..f8ad6e0f7 --- /dev/null +++ b/repos/base/src/timer/gpt/time_source.cc @@ -0,0 +1,76 @@ +/* + * \brief Time source that uses the General Purpose Timer (Freescale) + * \author Stefan Kalkowski + * \date 2019-04-13 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* local includes */ +#include + +using namespace Genode; + + +void Timer::Time_source::schedule_timeout(Genode::Microseconds duration, + Timeout_handler &handler) +{ + _handler = &handler; + + /* set to minimum ticks value to not miss a too short timeout */ + Genode::uint32_t const ticks = + Genode::max(1UL, (duration.value * TICKS_PER_MS) / 1000); + + /* clear interrupts */ + if (read()) { + write(0xffffffff); + _timer_irq.ack_irq(); + } + + /* set new timeout */ + write(read() + ticks); +} + + +Duration Timer::Time_source::curr_time() +{ + Cnt::access_t cur_cnt = read(); + Genode::Microseconds us(timer_ticks_to_us(cur_cnt - _last_cnt, + TICKS_PER_MS)); + _last_cnt = cur_cnt; + _curr_time.add(us); + return _curr_time; +} + + +Genode::Microseconds Timer::Time_source::max_timeout() const +{ + static unsigned long max = timer_ticks_to_us(0xffffffff, TICKS_PER_MS); + return Genode::Microseconds(max); +} + + +void Timer::Time_source::_initialize() +{ + _timer_irq.sigh(_signal_handler); + + write(0); + write(0); + write(0); + write(0); + write(0); + write(0); + write(0); + write(Cr::Clk_src::HIGH_FREQ_REF_CLK); + while (read()) ; + write(0); + write(1); + write(1); + write(1); + write(1); +} diff --git a/repos/base/src/timer/gpt/time_source.h b/repos/base/src/timer/gpt/time_source.h new file mode 100644 index 000000000..f57197f6b --- /dev/null +++ b/repos/base/src/timer/gpt/time_source.h @@ -0,0 +1,76 @@ +/* + * \brief Time source that uses the General Purpose Timer (Freescale) + * \author Stefan Kalkowski + * \date 2019-04-13 + */ + +/* + * Copyright (C) 2019 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _TIME_SOURCE_H_ +#define _TIME_SOURCE_H_ + +/* Genode includes */ +#include +#include +#include + +/* local includes */ +#include + +namespace Timer { class Time_source; } + + +class Timer::Time_source : private Genode::Attached_mmio, + public Genode::Signalled_time_source +{ + private: + + enum { TICKS_PER_MS = 500 }; + + struct Cr : Register<0x0, 32> + { + struct En : Bitfield<0, 1> { }; + struct En_mod : Bitfield<1, 1> { }; + struct Clk_src : Bitfield<6, 3> { enum { HIGH_FREQ_REF_CLK = 2 }; }; + struct Frr : Bitfield<9, 1> { }; + struct Swr : Bitfield<15, 1> { }; + }; + + struct Pr : Register<0x4, 32> { }; + struct Sr : Register<0x8, 32> { }; + struct Ir : Register<0xc, 32> { }; + struct Ocr1 : Register<0x10, 32> { }; + struct Ocr2 : Register<0x14, 32> { }; + struct Ocr3 : Register<0x18, 32> { }; + struct Icr1 : Register<0x1c, 32> { }; + struct Icr2 : Register<0x20, 32> { }; + struct Cnt : Register<0x24, 32> { }; + + + Genode::Irq_connection _timer_irq; + Genode::Duration _curr_time { Genode::Microseconds(0) }; + Cnt::access_t _last_cnt { 0 }; + + void _initialize(); + + public: + + Time_source(Genode::Env &env); + + + /************************* + ** Genode::Time_source ** + *************************/ + + Genode::Duration curr_time() override; + void schedule_timeout(Genode::Microseconds duration, + Timeout_handler &handler) override; + Genode::Microseconds max_timeout() const override; +}; + +#endif /* _TIME_SOURCE_H_ */ diff --git a/tool/run/boot_dir/sel4 b/tool/run/boot_dir/sel4 index 4795127ac..680e1a763 100644 --- a/tool/run/boot_dir/sel4 +++ b/tool/run/boot_dir/sel4 @@ -1,8 +1,9 @@ proc binary_name_ld_lib_so { } { return "ld-sel4.lib.so" } proc binary_name_core_o { } { return "core-sel4.o" } proc binary_name_timer { } { - if {[have_spec imx6]} { return "imx6_timer_drv" } - if {[have_spec x86]} { return "pit_timer_drv" } + if {[have_spec imx6]} { return "imx6_timer_drv" } + if {[have_spec imx7d_sabre]} { return "imx7_timer_drv" } + if {[have_spec x86]} { return "pit_timer_drv" } puts "unknown platform - no timer driver" exit -1 }