Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / hw / arm / s3c24xx_rtc.c
blobaba857829f5cb32fdac2e69e1b0ae4751d6f057d
1 /* hw/s3c24xx_rtc.c
3 * Samsung S3C24XX RTC emulation
5 * Copyright 2006, 2007, 2008 Daniel Silverstone and Vincent Sanders
7 * Copyright 2010, 2013 Stefan Weil
9 * This file is under the terms of the GNU General Public License Version 2.
12 #include "hw/hw.h"
13 #include "exec/address-spaces.h" /* get_system_memory */
15 #include "s3c24xx.h"
18 /* RTC Control RW Byte */
19 #define S3C_REG_RTCCON 0
20 /* Tick time count RW Byte */
21 #define S3C_REG_TICNT 1
22 /* RTC Alarm Control RW Byte */
23 #define S3C_REG_RTCALM 4
24 /* Alarm second */
25 #define S3C_REG_ALMSEC 5
26 /* Alarm minute */
27 #define S3C_REG_ALMMIN 6
28 /* Alarm hour */
29 #define S3C_REG_ALMHOUR 7
30 /* Alarm day */
31 #define S3C_REG_ALMDATE 8
32 /* Alarm month */
33 #define S3C_REG_ALMMON 9
34 /* Alarm year */
35 #define S3C_REG_ALMYEAR 10
36 /* RTC Round Reset */
37 #define S3C_REG_RTCRST 11
38 /* BCD Second */
39 #define S3C_REG_BCDSEC 12
40 /* BCD Minute */
41 #define S3C_REG_BCDMIN 13
42 /* BCD Hour */
43 #define S3C_REG_BCDHOUR 14
44 /* BCD Day */
45 #define S3C_REG_BCDDATE 15
46 /* BCD Day of week */
47 #define S3C_REG_BCDDAY 16
48 /* BCD Month */
49 #define S3C_REG_BCDMON 17
50 /* BCD Year */
51 #define S3C_REG_BCDYEAR 18
53 /* Real Time clock state */
54 struct s3c24xx_rtc_state_s {
55 MemoryRegion mmio;
56 uint32_t rtc_reg[19];
60 static void update_time(struct s3c24xx_rtc_state_s *s)
62 time_t ti;
63 struct tm *tm;
64 /* update the RTC registers from system time */
65 time(&ti);
66 tm = gmtime(&ti);
67 s->rtc_reg[S3C_REG_BCDSEC] = to_bcd(tm->tm_sec);
68 s->rtc_reg[S3C_REG_BCDMIN] = to_bcd(tm->tm_min);
69 s->rtc_reg[S3C_REG_BCDHOUR] = to_bcd(tm->tm_hour);
70 s->rtc_reg[S3C_REG_BCDDATE] = to_bcd(tm->tm_mday);
71 s->rtc_reg[S3C_REG_BCDDAY] = to_bcd(tm->tm_wday + 1);
72 s->rtc_reg[S3C_REG_BCDMON] = to_bcd(tm->tm_mon + 1);
73 s->rtc_reg[S3C_REG_BCDYEAR] = to_bcd(tm->tm_year - 100);
76 static void s3c24xx_rtc_write(void *opaque, hwaddr addr_,
77 uint64_t value, unsigned size)
79 struct s3c24xx_rtc_state_s *s = opaque;
80 int addr = (addr_ - 0x40) >> 2;
81 if (addr < 0 || addr > 18)
82 addr = 18;
84 s->rtc_reg[addr] = value;
87 static uint64_t s3c24xx_rtc_read(void *opaque, hwaddr addr_,
88 unsigned size)
90 struct s3c24xx_rtc_state_s *s = opaque;
91 int addr = (addr_ - 0x40) >> 2;
93 if (addr < 0 || addr > 18)
94 addr = 18;
96 update_time(s);
98 return s->rtc_reg[addr];
101 static const MemoryRegionOps s3c24xx_rtc_ops = {
102 .read = s3c24xx_rtc_read,
103 .write = s3c24xx_rtc_write,
104 .endianness = DEVICE_NATIVE_ENDIAN,
105 .valid = {
106 .min_access_size = 1,
107 .max_access_size = 4
111 struct s3c24xx_rtc_state_s *s3c24xx_rtc_init(hwaddr base_addr)
113 struct s3c24xx_rtc_state_s *s = g_new0(struct s3c24xx_rtc_state_s, 1);
115 /* there are only 19 real registers but they start at offset 0x40 into the
116 * range so we have 35 registers mapped
118 memory_region_init_io(&s->mmio, OBJECT(s), &s3c24xx_rtc_ops, s, "s3c24xx.rtc", 35 * 4);
119 memory_region_add_subregion(get_system_memory(), base_addr, &s->mmio);
121 /* set the RTC so it appears active */
122 s->rtc_reg[S3C_REG_RTCCON] = 1;
124 return s;