1*da2014a2SPaul Mundt /* 2*da2014a2SPaul Mundt * arch/sh/boards/dreamcast/rtc.c 3*da2014a2SPaul Mundt * 4*da2014a2SPaul Mundt * Dreamcast AICA RTC routines. 5*da2014a2SPaul Mundt * 6*da2014a2SPaul Mundt * Copyright (c) 2001, 2002 M. R. Brown <mrbrown@0xd6.org> 7*da2014a2SPaul Mundt * Copyright (c) 2002 Paul Mundt <lethal@chaoticdreams.org> 8*da2014a2SPaul Mundt * 9*da2014a2SPaul Mundt * Released under the terms of the GNU GPL v2.0. 10*da2014a2SPaul Mundt * 11*da2014a2SPaul Mundt */ 12*da2014a2SPaul Mundt 13*da2014a2SPaul Mundt #include <linux/time.h> 14*da2014a2SPaul Mundt #include <asm/rtc.h> 15*da2014a2SPaul Mundt #include <asm/io.h> 16*da2014a2SPaul Mundt 17*da2014a2SPaul Mundt /* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in 18*da2014a2SPaul Mundt seconds) to get the standard Unix Epoch when getting the time, and add 19*da2014a2SPaul Mundt 20 years when setting the time. */ 20*da2014a2SPaul Mundt #define TWENTY_YEARS ((20 * 365LU + 5) * 86400) 21*da2014a2SPaul Mundt 22*da2014a2SPaul Mundt /* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit 23*da2014a2SPaul Mundt registers.*/ 24*da2014a2SPaul Mundt #define AICA_RTC_SECS_H 0xa0710000 25*da2014a2SPaul Mundt #define AICA_RTC_SECS_L 0xa0710004 26*da2014a2SPaul Mundt 27*da2014a2SPaul Mundt /** 28*da2014a2SPaul Mundt * aica_rtc_gettimeofday - Get the time from the AICA RTC 29*da2014a2SPaul Mundt * @ts: pointer to resulting timespec 30*da2014a2SPaul Mundt * 31*da2014a2SPaul Mundt * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch. 32*da2014a2SPaul Mundt */ 33*da2014a2SPaul Mundt static void aica_rtc_gettimeofday(struct timespec *ts) 34*da2014a2SPaul Mundt { 35*da2014a2SPaul Mundt unsigned long val1, val2; 36*da2014a2SPaul Mundt 37*da2014a2SPaul Mundt do { 38*da2014a2SPaul Mundt val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | 39*da2014a2SPaul Mundt (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); 40*da2014a2SPaul Mundt 41*da2014a2SPaul Mundt val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | 42*da2014a2SPaul Mundt (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); 43*da2014a2SPaul Mundt } while (val1 != val2); 44*da2014a2SPaul Mundt 45*da2014a2SPaul Mundt ts->tv_sec = val1 - TWENTY_YEARS; 46*da2014a2SPaul Mundt 47*da2014a2SPaul Mundt /* Can't get nanoseconds with just a seconds counter. */ 48*da2014a2SPaul Mundt ts->tv_nsec = 0; 49*da2014a2SPaul Mundt } 50*da2014a2SPaul Mundt 51*da2014a2SPaul Mundt /** 52*da2014a2SPaul Mundt * aica_rtc_settimeofday - Set the AICA RTC to the current time 53*da2014a2SPaul Mundt * @secs: contains the time_t to set 54*da2014a2SPaul Mundt * 55*da2014a2SPaul Mundt * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter. 56*da2014a2SPaul Mundt */ 57*da2014a2SPaul Mundt static int aica_rtc_settimeofday(const time_t secs) 58*da2014a2SPaul Mundt { 59*da2014a2SPaul Mundt unsigned long val1, val2; 60*da2014a2SPaul Mundt unsigned long adj = secs + TWENTY_YEARS; 61*da2014a2SPaul Mundt 62*da2014a2SPaul Mundt do { 63*da2014a2SPaul Mundt ctrl_outl((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H); 64*da2014a2SPaul Mundt ctrl_outl((adj & 0xffff), AICA_RTC_SECS_L); 65*da2014a2SPaul Mundt 66*da2014a2SPaul Mundt val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | 67*da2014a2SPaul Mundt (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); 68*da2014a2SPaul Mundt 69*da2014a2SPaul Mundt val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | 70*da2014a2SPaul Mundt (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); 71*da2014a2SPaul Mundt } while (val1 != val2); 72*da2014a2SPaul Mundt 73*da2014a2SPaul Mundt return 0; 74*da2014a2SPaul Mundt } 75*da2014a2SPaul Mundt 76*da2014a2SPaul Mundt void aica_time_init(void) 77*da2014a2SPaul Mundt { 78*da2014a2SPaul Mundt rtc_sh_get_time = aica_rtc_gettimeofday; 79*da2014a2SPaul Mundt rtc_sh_set_time = aica_rtc_settimeofday; 80*da2014a2SPaul Mundt } 81*da2014a2SPaul Mundt 82