genode/repos/base-hw/src/core/spec/arm/exynos_mct.h

122 lines
2.6 KiB
C++

/*
* \brief Timer driver for core
* \author Martin stein
* \date 2013-01-10
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Kernel OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__CORE__SPEC__ARM__EXYNOS_MCT_H_
#define _SRC__CORE__SPEC__ARM__EXYNOS_MCT_H_
/* Kernel includes */
#include <util/mmio.h>
/* base-hw includes */
#include <kernel/types.h>
namespace Board { class Timer; }
struct Board::Timer : Genode::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> { };
};
/*****************
** Local timer **
*****************/
enum Local_timer_offset { L0 = 0x300, L1 = 0x400 };
struct Local : Genode::Mmio {
struct Tcntb : Register<0x0, 32> { };
struct Tcnto : Register<0x4, 32> { };
struct Icntb : Register<0x8, 32> { };
struct Icnto : Register<0xc, 32> { };
struct Frcntb : Register<0x10, 32> { };
struct Frcnto : Register<0x14, 32> { };
struct Tcon : Register<0x20, 32>
{
struct Timer_start : Bitfield<0, 1> { };
struct Irq_start : Bitfield<1, 1> { };
struct Irq_type : Bitfield<2, 1> { };
struct Frc_start : Bitfield<3, 1> { };
};
struct Int_cstat : Register<0x30, 32, true>
{
struct Intcnt : Bitfield<0, 1> { };
struct Frccnt : Bitfield<1, 1> { };
};
struct Int_enb : Register<0x34, 32>
{
struct Inteie : Bitfield<0, 1> { };
struct Frceie : Bitfield<1, 1> { };
};
struct Wstat : Register<0x40, 32, true>
{
struct Tcntb : Bitfield<0, 1> { };
struct Icntb : Bitfield<1, 1> { };
struct Frcntb : Bitfield<2, 1> { };
struct Tcon : Bitfield<3, 1> { };
};
Tcnto::access_t cnt = { 0 };
/**
* Write to reg that replies via ack bit and clear ack bit
*/
template <typename DEST, typename ACK>
void acked_write(typename DEST::Register_base::access_t const v)
{
typedef typename DEST::Register_base Dest;
typedef typename ACK::Bitfield_base Ack;
write<Dest>(v);
while (!read<Ack>());
write<Ack>(1);
}
void update_cnt() { cnt = read<Tcnto>(); }
Local(Genode::addr_t base);
};
/**
* Calculate amount of ticks per ms for specific input clock
*
* \param clock input clock
*/
Kernel::time_t static calc_ticks_per_ms(unsigned const clock) {
return clock / (PRESCALER + 1) / (1 << DIV_MUX) / 1000; }
Local local;
unsigned const ticks_per_ms;
unsigned const cpu_id;
Timer(unsigned cpu_id);
};
#endif /* _SRC__CORE__SPEC__ARM__EXYNOS_MCT_H_ */