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