mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-01 16:58:29 +00:00
ed52d5a211
Instead of holding SPEC-variable dependent files and directories inline within the repository structure, move them into 'spec' subdirectories at the corresponding levels, e.g.: repos/base/include/spec repos/base/mk/spec repos/base/lib/mk/spec repos/base/src/core/spec ... Moreover, this commit removes the 'platform' directories. That term was used in an overloaded sense. All SPEC-relative 'platform' directories are now named 'spec'. Other files, like for instance those related to the kernel/architecture specific startup library, where moved from 'platform' directories to explicit, more meaningful places like e.g.: 'src/lib/startup'. Fix #1673
143 lines
3.2 KiB
C++
143 lines
3.2 KiB
C++
/*
|
|
* \brief RTC/CMOS clock driver
|
|
* \author Christian Helmuth
|
|
* \author Markus Partheymueller
|
|
* \date 2007-04-18
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2007-2015 Genode Labs GmbH
|
|
* Copyright (C) 2012 Intel Corporation
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
/* Genode */
|
|
#include <base/env.h>
|
|
#include <base/sleep.h>
|
|
#include <base/rpc_server.h>
|
|
#include <root/component.h>
|
|
#include <cap_session/connection.h>
|
|
#include <rtc_session/rtc_session.h>
|
|
#include <base/printf.h>
|
|
#include <io_port_session/connection.h>
|
|
|
|
#include "rtc.h"
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
enum RTC
|
|
{
|
|
RTC_SECONDS = 0,
|
|
RTC_SECONDS_ALARM = 1,
|
|
RTC_MINUTES = 2,
|
|
RTC_MINUTES_ALARM = 3,
|
|
RTC_HOURS = 4,
|
|
RTC_HOURS_ALARM = 5,
|
|
RTC_DAY_OF_WEEK = 6,
|
|
RTC_DAY_OF_MONTH = 7,
|
|
RTC_MONTH = 8,
|
|
RTC_YEAR = 9,
|
|
|
|
RTC_REG_A = 10,
|
|
RTC_REG_B = 11,
|
|
RTC_REG_C = 12,
|
|
RTC_REG_D = 13,
|
|
|
|
RTC_FREQ_SELECT = RTC_REG_A,
|
|
RTC_UIP = 0x80,
|
|
RTC_DIV_CTL = 0x70,
|
|
RTC_REF_CLCK_4MHZ = 0x00,
|
|
RTC_REF_CLCK_1MHZ = 0x10,
|
|
RTC_REF_CLCK_32KHZ = 0x20,
|
|
RTC_DIV_RESET1 = 0x60,
|
|
RTC_DIV_RESET2 = 0x70,
|
|
RTC_RATE_SELECT = 0x0F,
|
|
|
|
RTC_CONTROL = RTC_REG_B,
|
|
RTC_SET = 0x80,
|
|
RTC_PIE = 0x40,
|
|
RTC_AIE = 0x20,
|
|
RTC_UIE = 0x10,
|
|
RTC_SQWE = 0x08,
|
|
RTC_DM_BINARY = 0x04,
|
|
RTC_24H = 0x02,
|
|
RTC_DST_EN = 0x01,
|
|
|
|
RTC_PORT_BASE = 0x70,
|
|
RTC_PORT_ADDR = RTC_PORT_BASE,
|
|
RTC_PORT_DATA = RTC_PORT_BASE + 1,
|
|
RTC_PORT_SIZE = 2,
|
|
};
|
|
|
|
|
|
/*
|
|
* Our RTC port session
|
|
*/
|
|
static Io_port_connection & rtc_ports()
|
|
{
|
|
static Io_port_connection inst(RTC_PORT_BASE, RTC_PORT_SIZE);
|
|
|
|
return inst;
|
|
}
|
|
|
|
|
|
static inline unsigned cmos_read(unsigned char addr)
|
|
{
|
|
unsigned char val;
|
|
rtc_ports().outb(RTC_PORT_ADDR, addr);
|
|
// iodelay();
|
|
val = rtc_ports().inb(RTC_PORT_DATA);
|
|
// iodelay();
|
|
return val;
|
|
}
|
|
|
|
|
|
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
|
|
#define BCD_TO_BIN(val) ((val) = ((val) & 15) + ((val) >> 4) * 10)
|
|
#define BIN_TO_BCD(val) ((val) = (((val)/10) << 4) + (val) % 10)
|
|
|
|
|
|
Rtc::Timestamp Rtc::get_time(void)
|
|
{
|
|
unsigned year, mon, day, hour, min, sec;
|
|
int i;
|
|
|
|
/* The Linux interpretation of the CMOS clock register contents:
|
|
* When the Update-In-Progress (UIP) flag goes from 1 to 0, the
|
|
* RTC registers show the second which has precisely just started.
|
|
* Let's hope other operating systems interpret the RTC the same way. */
|
|
|
|
/* read RTC exactly on falling edge of update flag */
|
|
for (i = 0 ; i < 1000000 ; i++)
|
|
if (cmos_read(RTC_FREQ_SELECT) & RTC_UIP) break;
|
|
|
|
for (i = 0 ; i < 1000000 ; i++)
|
|
if (!(cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) break;
|
|
|
|
do {
|
|
sec = cmos_read(RTC_SECONDS);
|
|
min = cmos_read(RTC_MINUTES);
|
|
hour = cmos_read(RTC_HOURS);
|
|
day = cmos_read(RTC_DAY_OF_MONTH);
|
|
mon = cmos_read(RTC_MONTH);
|
|
year = cmos_read(RTC_YEAR);
|
|
} while (sec != cmos_read(RTC_SECONDS));
|
|
|
|
/* convert BCD to binary format if needed */
|
|
if (!(cmos_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
|
|
BCD_TO_BIN(sec);
|
|
BCD_TO_BIN(min);
|
|
BCD_TO_BIN(hour);
|
|
BCD_TO_BIN(day);
|
|
BCD_TO_BIN(mon);
|
|
BCD_TO_BIN(year);
|
|
}
|
|
|
|
if ((year += 1900) < 1970) year += 100;
|
|
|
|
return Timestamp { 0, sec, min, hour, day, mon, year };
|
|
}
|