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.
13 #include "exec/address-spaces.h" /* get_system_memory */
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
25 #define S3C_REG_ALMSEC 5
27 #define S3C_REG_ALMMIN 6
29 #define S3C_REG_ALMHOUR 7
31 #define S3C_REG_ALMDATE 8
33 #define S3C_REG_ALMMON 9
35 #define S3C_REG_ALMYEAR 10
37 #define S3C_REG_RTCRST 11
39 #define S3C_REG_BCDSEC 12
41 #define S3C_REG_BCDMIN 13
43 #define S3C_REG_BCDHOUR 14
45 #define S3C_REG_BCDDATE 15
47 #define S3C_REG_BCDDAY 16
49 #define S3C_REG_BCDMON 17
51 #define S3C_REG_BCDYEAR 18
53 /* Real Time clock state */
54 struct s3c24xx_rtc_state_s
{
60 static void update_time(struct s3c24xx_rtc_state_s
*s
)
64 /* update the RTC registers from system time */
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)
84 s
->rtc_reg
[addr
] = value
;
87 static uint64_t s3c24xx_rtc_read(void *opaque
, hwaddr addr_
,
90 struct s3c24xx_rtc_state_s
*s
= opaque
;
91 int addr
= (addr_
- 0x40) >> 2;
93 if (addr
< 0 || addr
> 18)
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
,
106 .min_access_size
= 1,
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;