Merge remote-tracking branch 'qemu/master'
[qemu/ar7.git] / hw / arm / s3c24xx_rtc.c
blobb39ee721356c1249219aa7928656c5431a85555c
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 "qemu/osdep.h"
13 #include "cpu.h"
14 #include "qemu/bcd.h" /* to_bcd */
15 #include "hw/hw.h"
16 #include "exec/address-spaces.h" /* get_system_memory */
18 #include "s3c24xx.h"
21 /* RTC Control RW Byte */
22 #define S3C_REG_RTCCON 0
23 /* Tick time count RW Byte */
24 #define S3C_REG_TICNT 1
25 /* RTC Alarm Control RW Byte */
26 #define S3C_REG_RTCALM 4
27 /* Alarm second */
28 #define S3C_REG_ALMSEC 5
29 /* Alarm minute */
30 #define S3C_REG_ALMMIN 6
31 /* Alarm hour */
32 #define S3C_REG_ALMHOUR 7
33 /* Alarm day */
34 #define S3C_REG_ALMDATE 8
35 /* Alarm month */
36 #define S3C_REG_ALMMON 9
37 /* Alarm year */
38 #define S3C_REG_ALMYEAR 10
39 /* RTC Round Reset */
40 #define S3C_REG_RTCRST 11
41 /* BCD Second */
42 #define S3C_REG_BCDSEC 12
43 /* BCD Minute */
44 #define S3C_REG_BCDMIN 13
45 /* BCD Hour */
46 #define S3C_REG_BCDHOUR 14
47 /* BCD Day */
48 #define S3C_REG_BCDDATE 15
49 /* BCD Day of week */
50 #define S3C_REG_BCDDAY 16
51 /* BCD Month */
52 #define S3C_REG_BCDMON 17
53 /* BCD Year */
54 #define S3C_REG_BCDYEAR 18
56 /* Real Time clock state */
57 struct s3c24xx_rtc_state_s {
58 MemoryRegion mmio;
59 uint32_t rtc_reg[19];
63 static void update_time(struct s3c24xx_rtc_state_s *s)
65 time_t ti;
66 struct tm *tm;
67 /* update the RTC registers from system time */
68 time(&ti);
69 tm = gmtime(&ti);
70 s->rtc_reg[S3C_REG_BCDSEC] = to_bcd(tm->tm_sec);
71 s->rtc_reg[S3C_REG_BCDMIN] = to_bcd(tm->tm_min);
72 s->rtc_reg[S3C_REG_BCDHOUR] = to_bcd(tm->tm_hour);
73 s->rtc_reg[S3C_REG_BCDDATE] = to_bcd(tm->tm_mday);
74 s->rtc_reg[S3C_REG_BCDDAY] = to_bcd(tm->tm_wday + 1);
75 s->rtc_reg[S3C_REG_BCDMON] = to_bcd(tm->tm_mon + 1);
76 s->rtc_reg[S3C_REG_BCDYEAR] = to_bcd(tm->tm_year - 100);
79 static void s3c24xx_rtc_write(void *opaque, hwaddr addr_,
80 uint64_t value, unsigned size)
82 struct s3c24xx_rtc_state_s *s = opaque;
83 int addr = (addr_ - 0x40) >> 2;
84 if (addr < 0 || addr > 18)
85 addr = 18;
87 s->rtc_reg[addr] = value;
90 static uint64_t s3c24xx_rtc_read(void *opaque, hwaddr addr_,
91 unsigned size)
93 struct s3c24xx_rtc_state_s *s = opaque;
94 int addr = (addr_ - 0x40) >> 2;
96 if (addr < 0 || addr > 18)
97 addr = 18;
99 update_time(s);
101 return s->rtc_reg[addr];
104 static const MemoryRegionOps s3c24xx_rtc_ops = {
105 .read = s3c24xx_rtc_read,
106 .write = s3c24xx_rtc_write,
107 .endianness = DEVICE_NATIVE_ENDIAN,
108 .valid = {
109 .min_access_size = 1,
110 .max_access_size = 4
114 struct s3c24xx_rtc_state_s *s3c24xx_rtc_init(hwaddr base_addr)
116 struct s3c24xx_rtc_state_s *s = g_new0(struct s3c24xx_rtc_state_s, 1);
118 /* there are only 19 real registers but they start at offset 0x40 into the
119 * range so we have 35 registers mapped
121 memory_region_init_io(&s->mmio, OBJECT(s), &s3c24xx_rtc_ops, s, "s3c24xx.rtc", 35 * 4);
122 memory_region_add_subregion(get_system_memory(), base_addr, &s->mmio);
124 /* set the RTC so it appears active */
125 s->rtc_reg[S3C_REG_RTCCON] = 1;
127 return s;