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"
14 #include "qemu/bcd.h" /* to_bcd */
16 #include "exec/address-spaces.h" /* get_system_memory */
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
28 #define S3C_REG_ALMSEC 5
30 #define S3C_REG_ALMMIN 6
32 #define S3C_REG_ALMHOUR 7
34 #define S3C_REG_ALMDATE 8
36 #define S3C_REG_ALMMON 9
38 #define S3C_REG_ALMYEAR 10
40 #define S3C_REG_RTCRST 11
42 #define S3C_REG_BCDSEC 12
44 #define S3C_REG_BCDMIN 13
46 #define S3C_REG_BCDHOUR 14
48 #define S3C_REG_BCDDATE 15
50 #define S3C_REG_BCDDAY 16
52 #define S3C_REG_BCDMON 17
54 #define S3C_REG_BCDYEAR 18
56 /* Real Time clock state */
57 struct s3c24xx_rtc_state_s
{
63 static void update_time(struct s3c24xx_rtc_state_s
*s
)
67 /* update the RTC registers from system time */
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)
87 s
->rtc_reg
[addr
] = value
;
90 static uint64_t s3c24xx_rtc_read(void *opaque
, hwaddr addr_
,
93 struct s3c24xx_rtc_state_s
*s
= opaque
;
94 int addr
= (addr_
- 0x40) >> 2;
96 if (addr
< 0 || addr
> 18)
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
,
109 .min_access_size
= 1,
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;