ls7a_rtc.c (e5c0367e2bbcf730e96614f63ea7575885fdde98) | ls7a_rtc.c (6935f132e595a03eb023b5e9a0703509b3f0c2a1) |
---|---|
1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Loongarch LS7A Real Time Clock emulation 4 * 5 * Copyright (C) 2021 Loongson Technology Corporation Limited 6 */ 7 8#include "qemu/osdep.h" --- 58 unchanged lines hidden (view full) --- 67 MemoryRegion iomem; 68 /* 69 * Needed to preserve the tick_count across migration, even if the 70 * absolute value of the rtc_clock is different on the source and 71 * destination. 72 */ 73 int64_t offset_toy; 74 int64_t offset_rtc; | 1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Loongarch LS7A Real Time Clock emulation 4 * 5 * Copyright (C) 2021 Loongson Technology Corporation Limited 6 */ 7 8#include "qemu/osdep.h" --- 58 unchanged lines hidden (view full) --- 67 MemoryRegion iomem; 68 /* 69 * Needed to preserve the tick_count across migration, even if the 70 * absolute value of the rtc_clock is different on the source and 71 * destination. 72 */ 73 int64_t offset_toy; 74 int64_t offset_rtc; |
75 uint64_t save_toy_mon; 76 uint64_t save_toy_year; 77 uint64_t save_rtc; | |
78 int64_t data; 79 int tidx; 80 uint32_t toymatch[3]; 81 uint32_t toytrim; 82 uint32_t cntrctl; 83 uint32_t rtctrim; 84 uint32_t rtccount; 85 uint32_t rtcmatch[3]; --- 49 unchanged lines hidden (view full) --- 135 val = FIELD_DP32(val, TOY, MON, tm.tm_mon + 1); 136 val = FIELD_DP32(val, TOY, DAY, tm.tm_mday); 137 val = FIELD_DP32(val, TOY, HOUR, tm.tm_hour); 138 val = FIELD_DP32(val, TOY, MIN, tm.tm_min); 139 val = FIELD_DP32(val, TOY, SEC, tm.tm_sec); 140 return val; 141} 142 | 75 int64_t data; 76 int tidx; 77 uint32_t toymatch[3]; 78 uint32_t toytrim; 79 uint32_t cntrctl; 80 uint32_t rtctrim; 81 uint32_t rtccount; 82 uint32_t rtcmatch[3]; --- 49 unchanged lines hidden (view full) --- 132 val = FIELD_DP32(val, TOY, MON, tm.tm_mon + 1); 133 val = FIELD_DP32(val, TOY, DAY, tm.tm_mday); 134 val = FIELD_DP32(val, TOY, HOUR, tm.tm_hour); 135 val = FIELD_DP32(val, TOY, MIN, tm.tm_min); 136 val = FIELD_DP32(val, TOY, SEC, tm.tm_sec); 137 return val; 138} 139 |
143static inline uint64_t toy_time_to_val_year(struct tm tm) 144{ 145 uint64_t year; 146 147 year = tm.tm_year; 148 return year; 149} 150 | |
151static inline void toymatch_val_to_time(LS7ARtcState *s, uint64_t val, struct tm *tm) 152{ 153 qemu_get_timedate(tm, s->offset_toy); 154 tm->tm_sec = FIELD_EX32(val, TOY_MATCH, SEC); 155 tm->tm_min = FIELD_EX32(val, TOY_MATCH, MIN); 156 tm->tm_hour = FIELD_EX32(val, TOY_MATCH, HOUR); 157 tm->tm_mday = FIELD_EX32(val, TOY_MATCH, DAY); 158 tm->tm_mon = FIELD_EX32(val, TOY_MATCH, MON) - 1; --- 27 unchanged lines hidden (view full) --- 186 expire_ns = ticks_to_ns(val) - ticks_to_ns(s->offset_rtc); 187 timer_mod_ns(s->rtc_timer[num], expire_ns); 188 } 189} 190 191static void ls7a_toy_stop(LS7ARtcState *s) 192{ 193 int i; | 140static inline void toymatch_val_to_time(LS7ARtcState *s, uint64_t val, struct tm *tm) 141{ 142 qemu_get_timedate(tm, s->offset_toy); 143 tm->tm_sec = FIELD_EX32(val, TOY_MATCH, SEC); 144 tm->tm_min = FIELD_EX32(val, TOY_MATCH, MIN); 145 tm->tm_hour = FIELD_EX32(val, TOY_MATCH, HOUR); 146 tm->tm_mday = FIELD_EX32(val, TOY_MATCH, DAY); 147 tm->tm_mon = FIELD_EX32(val, TOY_MATCH, MON) - 1; --- 27 unchanged lines hidden (view full) --- 175 expire_ns = ticks_to_ns(val) - ticks_to_ns(s->offset_rtc); 176 timer_mod_ns(s->rtc_timer[num], expire_ns); 177 } 178} 179 180static void ls7a_toy_stop(LS7ARtcState *s) 181{ 182 int i; |
194 struct tm tm; 195 /* 196 * save time when disabled toy, 197 * because toy time not add counters. 198 */ 199 qemu_get_timedate(&tm, s->offset_toy); 200 s->save_toy_mon = toy_time_to_val_mon(tm); 201 s->save_toy_year = toy_time_to_val_year(tm); | |
202 203 /* delete timers, and when re-enabled, recaculate expire time */ 204 for (i = 0; i < TIMER_NUMS; i++) { 205 timer_del(s->toy_timer[i]); 206 } 207} 208 209static void ls7a_rtc_stop(LS7ARtcState *s) 210{ 211 int i; | 183 184 /* delete timers, and when re-enabled, recaculate expire time */ 185 for (i = 0; i < TIMER_NUMS; i++) { 186 timer_del(s->toy_timer[i]); 187 } 188} 189 190static void ls7a_rtc_stop(LS7ARtcState *s) 191{ 192 int i; |
212 uint64_t time; | |
213 | 193 |
214 /* save rtc time */ 215 time = ls7a_rtc_ticks() + s->offset_rtc; 216 s->save_rtc = time; 217 | |
218 /* delete timers, and when re-enabled, recaculate expire time */ 219 for (i = 0; i < TIMER_NUMS; i++) { 220 timer_del(s->rtc_timer[i]); 221 } 222} 223 224static void ls7a_toy_start(LS7ARtcState *s) 225{ 226 int i; 227 uint64_t expire_time, now; 228 struct tm tm = {}; | 194 /* delete timers, and when re-enabled, recaculate expire time */ 195 for (i = 0; i < TIMER_NUMS; i++) { 196 timer_del(s->rtc_timer[i]); 197 } 198} 199 200static void ls7a_toy_start(LS7ARtcState *s) 201{ 202 int i; 203 uint64_t expire_time, now; 204 struct tm tm = {}; |
229 /* 230 * need to recaculate toy offset 231 * and expire time when enable it. 232 */ 233 toy_val_to_time_mon(s->save_toy_mon, &tm); 234 toy_val_to_time_year(s->save_toy_year, &tm); | |
235 | 205 |
236 s->offset_toy = qemu_timedate_diff(&tm); | |
237 now = qemu_clock_get_ms(rtc_clock); 238 239 /* recaculate expire time and enable timer */ 240 for (i = 0; i < TIMER_NUMS; i++) { 241 toymatch_val_to_time(s, s->toymatch[i], &tm); 242 expire_time = now + (qemu_timedate_diff(&tm) - s->offset_toy) * 1000; 243 timer_mod(s->toy_timer[i], expire_time); 244 } 245} 246 247static void ls7a_rtc_start(LS7ARtcState *s) 248{ 249 int i; | 206 now = qemu_clock_get_ms(rtc_clock); 207 208 /* recaculate expire time and enable timer */ 209 for (i = 0; i < TIMER_NUMS; i++) { 210 toymatch_val_to_time(s, s->toymatch[i], &tm); 211 expire_time = now + (qemu_timedate_diff(&tm) - s->offset_toy) * 1000; 212 timer_mod(s->toy_timer[i], expire_time); 213 } 214} 215 216static void ls7a_rtc_start(LS7ARtcState *s) 217{ 218 int i; |
250 uint64_t expire_time, now; | 219 uint64_t expire_time; |
251 | 220 |
252 /* 253 * need to recaculate rtc offset 254 * and expire time when enable it. 255 */ 256 now = ls7a_rtc_ticks(); 257 s->offset_rtc = s->save_rtc - now; 258 | |
259 /* recaculate expire time and enable timer */ 260 for (i = 0; i < TIMER_NUMS; i++) { 261 expire_time = ticks_to_ns(s->rtcmatch[i]) - ticks_to_ns(s->offset_rtc); 262 timer_mod_ns(s->rtc_timer[i], expire_time); 263 } 264} 265 266static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, unsigned size) 267{ 268 LS7ARtcState *s = LS7A_RTC(opaque); 269 struct tm tm; 270 int val = 0; 271 272 switch (addr) { 273 case SYS_TOYREAD0: | 221 /* recaculate expire time and enable timer */ 222 for (i = 0; i < TIMER_NUMS; i++) { 223 expire_time = ticks_to_ns(s->rtcmatch[i]) - ticks_to_ns(s->offset_rtc); 224 timer_mod_ns(s->rtc_timer[i], expire_time); 225 } 226} 227 228static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, unsigned size) 229{ 230 LS7ARtcState *s = LS7A_RTC(opaque); 231 struct tm tm; 232 int val = 0; 233 234 switch (addr) { 235 case SYS_TOYREAD0: |
274 /* if toy disabled, read save toy time */ | |
275 if (toy_enabled(s)) { 276 qemu_get_timedate(&tm, s->offset_toy); 277 val = toy_time_to_val_mon(tm); 278 } else { | 236 if (toy_enabled(s)) { 237 qemu_get_timedate(&tm, s->offset_toy); 238 val = toy_time_to_val_mon(tm); 239 } else { |
279 /* read save mon val */ 280 val = s->save_toy_mon; | 240 /* return 0 when toy disabled */ 241 val = 0; |
281 } 282 break; 283 case SYS_TOYREAD1: | 242 } 243 break; 244 case SYS_TOYREAD1: |
284 /* if toy disabled, read save toy time */ | |
285 if (toy_enabled(s)) { 286 qemu_get_timedate(&tm, s->offset_toy); 287 val = tm.tm_year; 288 } else { | 245 if (toy_enabled(s)) { 246 qemu_get_timedate(&tm, s->offset_toy); 247 val = tm.tm_year; 248 } else { |
289 /* read save year val */ 290 val = s->save_toy_year; | 249 /* return 0 when toy disabled */ 250 val = 0; |
291 } 292 break; 293 case SYS_TOYMATCH0: 294 val = s->toymatch[0]; 295 break; 296 case SYS_TOYMATCH1: 297 val = s->toymatch[1]; 298 break; 299 case SYS_TOYMATCH2: 300 val = s->toymatch[2]; 301 break; 302 case SYS_RTCCTRL: 303 val = s->cntrctl; 304 break; 305 case SYS_RTCREAD0: | 251 } 252 break; 253 case SYS_TOYMATCH0: 254 val = s->toymatch[0]; 255 break; 256 case SYS_TOYMATCH1: 257 val = s->toymatch[1]; 258 break; 259 case SYS_TOYMATCH2: 260 val = s->toymatch[2]; 261 break; 262 case SYS_RTCCTRL: 263 val = s->cntrctl; 264 break; 265 case SYS_RTCREAD0: |
306 /* if rtc disabled, read save rtc time */ | |
307 if (rtc_enabled(s)) { 308 val = ls7a_rtc_ticks() + s->offset_rtc; 309 } else { | 266 if (rtc_enabled(s)) { 267 val = ls7a_rtc_ticks() + s->offset_rtc; 268 } else { |
310 val = s->save_rtc; | 269 /* return 0 when rtc disabled */ 270 val = 0; |
311 } 312 break; 313 case SYS_RTCMATCH0: 314 val = s->rtcmatch[0]; 315 break; 316 case SYS_RTCMATCH1: 317 val = s->rtcmatch[1]; 318 break; --- 133 unchanged lines hidden (view full) --- 452 for (i = 0; i < TIMER_NUMS; i++) { 453 d->toymatch[i] = 0; 454 d->rtcmatch[i] = 0; 455 d->toy_timer[i] = timer_new_ms(rtc_clock, toy_timer_cb, d); 456 d->rtc_timer[i] = timer_new_ms(rtc_clock, rtc_timer_cb, d); 457 } 458 d->offset_toy = 0; 459 d->offset_rtc = 0; | 271 } 272 break; 273 case SYS_RTCMATCH0: 274 val = s->rtcmatch[0]; 275 break; 276 case SYS_RTCMATCH1: 277 val = s->rtcmatch[1]; 278 break; --- 133 unchanged lines hidden (view full) --- 412 for (i = 0; i < TIMER_NUMS; i++) { 413 d->toymatch[i] = 0; 414 d->rtcmatch[i] = 0; 415 d->toy_timer[i] = timer_new_ms(rtc_clock, toy_timer_cb, d); 416 d->rtc_timer[i] = timer_new_ms(rtc_clock, rtc_timer_cb, d); 417 } 418 d->offset_toy = 0; 419 d->offset_rtc = 0; |
460 d->save_toy_mon = 0; 461 d->save_toy_year = 0; 462 d->save_rtc = 0; | |
463 464} 465 466/* delete timer and clear reg when reset */ 467static void ls7a_rtc_reset(DeviceState *dev) 468{ 469 int i; 470 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); --- 39 unchanged lines hidden (view full) --- 510 .name = "ls7a_rtc", 511 .version_id = 1, 512 .minimum_version_id = 1, 513 .pre_save = ls7a_rtc_pre_save, 514 .post_load = ls7a_rtc_post_load, 515 .fields = (VMStateField[]) { 516 VMSTATE_INT64(offset_toy, LS7ARtcState), 517 VMSTATE_INT64(offset_rtc, LS7ARtcState), | 420 421} 422 423/* delete timer and clear reg when reset */ 424static void ls7a_rtc_reset(DeviceState *dev) 425{ 426 int i; 427 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); --- 39 unchanged lines hidden (view full) --- 467 .name = "ls7a_rtc", 468 .version_id = 1, 469 .minimum_version_id = 1, 470 .pre_save = ls7a_rtc_pre_save, 471 .post_load = ls7a_rtc_post_load, 472 .fields = (VMStateField[]) { 473 VMSTATE_INT64(offset_toy, LS7ARtcState), 474 VMSTATE_INT64(offset_rtc, LS7ARtcState), |
518 VMSTATE_UINT64(save_toy_mon, LS7ARtcState), 519 VMSTATE_UINT64(save_toy_year, LS7ARtcState), 520 VMSTATE_UINT64(save_rtc, LS7ARtcState), | |
521 VMSTATE_UINT32_ARRAY(toymatch, LS7ARtcState, TIMER_NUMS), 522 VMSTATE_UINT32_ARRAY(rtcmatch, LS7ARtcState, TIMER_NUMS), 523 VMSTATE_UINT32(cntrctl, LS7ARtcState), 524 VMSTATE_END_OF_LIST() 525 } 526}; 527 528static void ls7a_rtc_class_init(ObjectClass *klass, void *data) --- 21 unchanged lines hidden --- | 475 VMSTATE_UINT32_ARRAY(toymatch, LS7ARtcState, TIMER_NUMS), 476 VMSTATE_UINT32_ARRAY(rtcmatch, LS7ARtcState, TIMER_NUMS), 477 VMSTATE_UINT32(cntrctl, LS7ARtcState), 478 VMSTATE_END_OF_LIST() 479 } 480}; 481 482static void ls7a_rtc_class_init(ObjectClass *klass, void *data) --- 21 unchanged lines hidden --- |