1 /* 2 * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms 3 * 4 * Copyright (c) 2003-2005, 2007, 2017 Jocelyn Mayer 5 * Copyright (c) 2013 Hervé Poussineau 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "qemu/osdep.h" 27 #include "qemu-common.h" 28 #include "hw/irq.h" 29 #include "hw/qdev-properties.h" 30 #include "hw/rtc/m48t59.h" 31 #include "qemu/timer.h" 32 #include "sysemu/runstate.h" 33 #include "sysemu/sysemu.h" 34 #include "hw/sysbus.h" 35 #include "exec/address-spaces.h" 36 #include "qapi/error.h" 37 #include "qemu/bcd.h" 38 #include "qemu/module.h" 39 #include "trace.h" 40 41 #include "m48t59-internal.h" 42 #include "migration/vmstate.h" 43 44 #define TYPE_M48TXX_SYS_BUS "sysbus-m48txx" 45 #define M48TXX_SYS_BUS_GET_CLASS(obj) \ 46 OBJECT_GET_CLASS(M48txxSysBusDeviceClass, (obj), TYPE_M48TXX_SYS_BUS) 47 #define M48TXX_SYS_BUS_CLASS(klass) \ 48 OBJECT_CLASS_CHECK(M48txxSysBusDeviceClass, (klass), TYPE_M48TXX_SYS_BUS) 49 #define M48TXX_SYS_BUS(obj) \ 50 OBJECT_CHECK(M48txxSysBusState, (obj), TYPE_M48TXX_SYS_BUS) 51 52 /* 53 * Chipset docs: 54 * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf 55 * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf 56 * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf 57 */ 58 59 typedef struct M48txxSysBusState { 60 SysBusDevice parent_obj; 61 M48t59State state; 62 MemoryRegion io; 63 } M48txxSysBusState; 64 65 typedef struct M48txxSysBusDeviceClass { 66 SysBusDeviceClass parent_class; 67 M48txxInfo info; 68 } M48txxSysBusDeviceClass; 69 70 static M48txxInfo m48txx_sysbus_info[] = { 71 { 72 .bus_name = "sysbus-m48t02", 73 .model = 2, 74 .size = 0x800, 75 },{ 76 .bus_name = "sysbus-m48t08", 77 .model = 8, 78 .size = 0x2000, 79 },{ 80 .bus_name = "sysbus-m48t59", 81 .model = 59, 82 .size = 0x2000, 83 } 84 }; 85 86 87 /* Fake timer functions */ 88 89 /* Alarm management */ 90 static void alarm_cb (void *opaque) 91 { 92 struct tm tm; 93 uint64_t next_time; 94 M48t59State *NVRAM = opaque; 95 96 qemu_set_irq(NVRAM->IRQ, 1); 97 if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && 98 (NVRAM->buffer[0x1FF4] & 0x80) == 0 && 99 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 100 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 101 /* Repeat once a month */ 102 qemu_get_timedate(&tm, NVRAM->time_offset); 103 tm.tm_mon++; 104 if (tm.tm_mon == 13) { 105 tm.tm_mon = 1; 106 tm.tm_year++; 107 } 108 next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset; 109 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 110 (NVRAM->buffer[0x1FF4] & 0x80) == 0 && 111 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 112 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 113 /* Repeat once a day */ 114 next_time = 24 * 60 * 60; 115 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 116 (NVRAM->buffer[0x1FF4] & 0x80) != 0 && 117 (NVRAM->buffer[0x1FF3] & 0x80) == 0 && 118 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 119 /* Repeat once an hour */ 120 next_time = 60 * 60; 121 } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && 122 (NVRAM->buffer[0x1FF4] & 0x80) != 0 && 123 (NVRAM->buffer[0x1FF3] & 0x80) != 0 && 124 (NVRAM->buffer[0x1FF2] & 0x80) == 0) { 125 /* Repeat once a minute */ 126 next_time = 60; 127 } else { 128 /* Repeat once a second */ 129 next_time = 1; 130 } 131 timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) + 132 next_time * 1000); 133 qemu_set_irq(NVRAM->IRQ, 0); 134 } 135 136 static void set_alarm(M48t59State *NVRAM) 137 { 138 int diff; 139 if (NVRAM->alrm_timer != NULL) { 140 timer_del(NVRAM->alrm_timer); 141 diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset; 142 if (diff > 0) 143 timer_mod(NVRAM->alrm_timer, diff * 1000); 144 } 145 } 146 147 /* RTC management helpers */ 148 static inline void get_time(M48t59State *NVRAM, struct tm *tm) 149 { 150 qemu_get_timedate(tm, NVRAM->time_offset); 151 } 152 153 static void set_time(M48t59State *NVRAM, struct tm *tm) 154 { 155 NVRAM->time_offset = qemu_timedate_diff(tm); 156 set_alarm(NVRAM); 157 } 158 159 /* Watchdog management */ 160 static void watchdog_cb (void *opaque) 161 { 162 M48t59State *NVRAM = opaque; 163 164 NVRAM->buffer[0x1FF0] |= 0x80; 165 if (NVRAM->buffer[0x1FF7] & 0x80) { 166 NVRAM->buffer[0x1FF7] = 0x00; 167 NVRAM->buffer[0x1FFC] &= ~0x40; 168 /* May it be a hw CPU Reset instead ? */ 169 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 170 } else { 171 qemu_set_irq(NVRAM->IRQ, 1); 172 qemu_set_irq(NVRAM->IRQ, 0); 173 } 174 } 175 176 static void set_up_watchdog(M48t59State *NVRAM, uint8_t value) 177 { 178 uint64_t interval; /* in 1/16 seconds */ 179 180 NVRAM->buffer[0x1FF0] &= ~0x80; 181 if (NVRAM->wd_timer != NULL) { 182 timer_del(NVRAM->wd_timer); 183 if (value != 0) { 184 interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F); 185 timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) + 186 ((interval * 1000) >> 4)); 187 } 188 } 189 } 190 191 /* Direct access to NVRAM */ 192 void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val) 193 { 194 struct tm tm; 195 int tmp; 196 197 trace_m48txx_nvram_mem_write(addr, val); 198 199 /* check for NVRAM access */ 200 if ((NVRAM->model == 2 && addr < 0x7f8) || 201 (NVRAM->model == 8 && addr < 0x1ff8) || 202 (NVRAM->model == 59 && addr < 0x1ff0)) { 203 goto do_write; 204 } 205 206 /* TOD access */ 207 switch (addr) { 208 case 0x1FF0: 209 /* flags register : read-only */ 210 break; 211 case 0x1FF1: 212 /* unused */ 213 break; 214 case 0x1FF2: 215 /* alarm seconds */ 216 tmp = from_bcd(val & 0x7F); 217 if (tmp >= 0 && tmp <= 59) { 218 NVRAM->alarm.tm_sec = tmp; 219 NVRAM->buffer[0x1FF2] = val; 220 set_alarm(NVRAM); 221 } 222 break; 223 case 0x1FF3: 224 /* alarm minutes */ 225 tmp = from_bcd(val & 0x7F); 226 if (tmp >= 0 && tmp <= 59) { 227 NVRAM->alarm.tm_min = tmp; 228 NVRAM->buffer[0x1FF3] = val; 229 set_alarm(NVRAM); 230 } 231 break; 232 case 0x1FF4: 233 /* alarm hours */ 234 tmp = from_bcd(val & 0x3F); 235 if (tmp >= 0 && tmp <= 23) { 236 NVRAM->alarm.tm_hour = tmp; 237 NVRAM->buffer[0x1FF4] = val; 238 set_alarm(NVRAM); 239 } 240 break; 241 case 0x1FF5: 242 /* alarm date */ 243 tmp = from_bcd(val & 0x3F); 244 if (tmp != 0) { 245 NVRAM->alarm.tm_mday = tmp; 246 NVRAM->buffer[0x1FF5] = val; 247 set_alarm(NVRAM); 248 } 249 break; 250 case 0x1FF6: 251 /* interrupts */ 252 NVRAM->buffer[0x1FF6] = val; 253 break; 254 case 0x1FF7: 255 /* watchdog */ 256 NVRAM->buffer[0x1FF7] = val; 257 set_up_watchdog(NVRAM, val); 258 break; 259 case 0x1FF8: 260 case 0x07F8: 261 /* control */ 262 NVRAM->buffer[addr] = (val & ~0xA0) | 0x90; 263 break; 264 case 0x1FF9: 265 case 0x07F9: 266 /* seconds (BCD) */ 267 tmp = from_bcd(val & 0x7F); 268 if (tmp >= 0 && tmp <= 59) { 269 get_time(NVRAM, &tm); 270 tm.tm_sec = tmp; 271 set_time(NVRAM, &tm); 272 } 273 if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) { 274 if (val & 0x80) { 275 NVRAM->stop_time = time(NULL); 276 } else { 277 NVRAM->time_offset += NVRAM->stop_time - time(NULL); 278 NVRAM->stop_time = 0; 279 } 280 } 281 NVRAM->buffer[addr] = val & 0x80; 282 break; 283 case 0x1FFA: 284 case 0x07FA: 285 /* minutes (BCD) */ 286 tmp = from_bcd(val & 0x7F); 287 if (tmp >= 0 && tmp <= 59) { 288 get_time(NVRAM, &tm); 289 tm.tm_min = tmp; 290 set_time(NVRAM, &tm); 291 } 292 break; 293 case 0x1FFB: 294 case 0x07FB: 295 /* hours (BCD) */ 296 tmp = from_bcd(val & 0x3F); 297 if (tmp >= 0 && tmp <= 23) { 298 get_time(NVRAM, &tm); 299 tm.tm_hour = tmp; 300 set_time(NVRAM, &tm); 301 } 302 break; 303 case 0x1FFC: 304 case 0x07FC: 305 /* day of the week / century */ 306 tmp = from_bcd(val & 0x07); 307 get_time(NVRAM, &tm); 308 tm.tm_wday = tmp; 309 set_time(NVRAM, &tm); 310 NVRAM->buffer[addr] = val & 0x40; 311 break; 312 case 0x1FFD: 313 case 0x07FD: 314 /* date (BCD) */ 315 tmp = from_bcd(val & 0x3F); 316 if (tmp != 0) { 317 get_time(NVRAM, &tm); 318 tm.tm_mday = tmp; 319 set_time(NVRAM, &tm); 320 } 321 break; 322 case 0x1FFE: 323 case 0x07FE: 324 /* month */ 325 tmp = from_bcd(val & 0x1F); 326 if (tmp >= 1 && tmp <= 12) { 327 get_time(NVRAM, &tm); 328 tm.tm_mon = tmp - 1; 329 set_time(NVRAM, &tm); 330 } 331 break; 332 case 0x1FFF: 333 case 0x07FF: 334 /* year */ 335 tmp = from_bcd(val); 336 if (tmp >= 0 && tmp <= 99) { 337 get_time(NVRAM, &tm); 338 tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900; 339 set_time(NVRAM, &tm); 340 } 341 break; 342 default: 343 /* Check lock registers state */ 344 if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1)) 345 break; 346 if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2)) 347 break; 348 do_write: 349 if (addr < NVRAM->size) { 350 NVRAM->buffer[addr] = val & 0xFF; 351 } 352 break; 353 } 354 } 355 356 uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr) 357 { 358 struct tm tm; 359 uint32_t retval = 0xFF; 360 361 /* check for NVRAM access */ 362 if ((NVRAM->model == 2 && addr < 0x078f) || 363 (NVRAM->model == 8 && addr < 0x1ff8) || 364 (NVRAM->model == 59 && addr < 0x1ff0)) { 365 goto do_read; 366 } 367 368 /* TOD access */ 369 switch (addr) { 370 case 0x1FF0: 371 /* flags register */ 372 goto do_read; 373 case 0x1FF1: 374 /* unused */ 375 retval = 0; 376 break; 377 case 0x1FF2: 378 /* alarm seconds */ 379 goto do_read; 380 case 0x1FF3: 381 /* alarm minutes */ 382 goto do_read; 383 case 0x1FF4: 384 /* alarm hours */ 385 goto do_read; 386 case 0x1FF5: 387 /* alarm date */ 388 goto do_read; 389 case 0x1FF6: 390 /* interrupts */ 391 goto do_read; 392 case 0x1FF7: 393 /* A read resets the watchdog */ 394 set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]); 395 goto do_read; 396 case 0x1FF8: 397 case 0x07F8: 398 /* control */ 399 goto do_read; 400 case 0x1FF9: 401 case 0x07F9: 402 /* seconds (BCD) */ 403 get_time(NVRAM, &tm); 404 retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec); 405 break; 406 case 0x1FFA: 407 case 0x07FA: 408 /* minutes (BCD) */ 409 get_time(NVRAM, &tm); 410 retval = to_bcd(tm.tm_min); 411 break; 412 case 0x1FFB: 413 case 0x07FB: 414 /* hours (BCD) */ 415 get_time(NVRAM, &tm); 416 retval = to_bcd(tm.tm_hour); 417 break; 418 case 0x1FFC: 419 case 0x07FC: 420 /* day of the week / century */ 421 get_time(NVRAM, &tm); 422 retval = NVRAM->buffer[addr] | tm.tm_wday; 423 break; 424 case 0x1FFD: 425 case 0x07FD: 426 /* date */ 427 get_time(NVRAM, &tm); 428 retval = to_bcd(tm.tm_mday); 429 break; 430 case 0x1FFE: 431 case 0x07FE: 432 /* month */ 433 get_time(NVRAM, &tm); 434 retval = to_bcd(tm.tm_mon + 1); 435 break; 436 case 0x1FFF: 437 case 0x07FF: 438 /* year */ 439 get_time(NVRAM, &tm); 440 retval = to_bcd((tm.tm_year + 1900 - NVRAM->base_year) % 100); 441 break; 442 default: 443 /* Check lock registers state */ 444 if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1)) 445 break; 446 if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2)) 447 break; 448 do_read: 449 if (addr < NVRAM->size) { 450 retval = NVRAM->buffer[addr]; 451 } 452 break; 453 } 454 trace_m48txx_nvram_mem_read(addr, retval); 455 456 return retval; 457 } 458 459 /* IO access to NVRAM */ 460 static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val, 461 unsigned size) 462 { 463 M48t59State *NVRAM = opaque; 464 465 trace_m48txx_nvram_io_write(addr, val); 466 switch (addr) { 467 case 0: 468 NVRAM->addr &= ~0x00FF; 469 NVRAM->addr |= val; 470 break; 471 case 1: 472 NVRAM->addr &= ~0xFF00; 473 NVRAM->addr |= val << 8; 474 break; 475 case 3: 476 m48t59_write(NVRAM, NVRAM->addr, val); 477 NVRAM->addr = 0x0000; 478 break; 479 default: 480 break; 481 } 482 } 483 484 static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size) 485 { 486 M48t59State *NVRAM = opaque; 487 uint32_t retval; 488 489 switch (addr) { 490 case 3: 491 retval = m48t59_read(NVRAM, NVRAM->addr); 492 break; 493 default: 494 retval = -1; 495 break; 496 } 497 trace_m48txx_nvram_io_read(addr, retval); 498 499 return retval; 500 } 501 502 static uint64_t nvram_read(void *opaque, hwaddr addr, unsigned size) 503 { 504 M48t59State *NVRAM = opaque; 505 506 return m48t59_read(NVRAM, addr); 507 } 508 509 static void nvram_write(void *opaque, hwaddr addr, uint64_t value, 510 unsigned size) 511 { 512 M48t59State *NVRAM = opaque; 513 514 return m48t59_write(NVRAM, addr, value); 515 } 516 517 static const MemoryRegionOps nvram_ops = { 518 .read = nvram_read, 519 .write = nvram_write, 520 .impl.min_access_size = 1, 521 .impl.max_access_size = 1, 522 .valid.min_access_size = 1, 523 .valid.max_access_size = 4, 524 .endianness = DEVICE_BIG_ENDIAN, 525 }; 526 527 static const VMStateDescription vmstate_m48t59 = { 528 .name = "m48t59", 529 .version_id = 1, 530 .minimum_version_id = 1, 531 .fields = (VMStateField[]) { 532 VMSTATE_UINT8(lock, M48t59State), 533 VMSTATE_UINT16(addr, M48t59State), 534 VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, size), 535 VMSTATE_END_OF_LIST() 536 } 537 }; 538 539 void m48t59_reset_common(M48t59State *NVRAM) 540 { 541 NVRAM->addr = 0; 542 NVRAM->lock = 0; 543 if (NVRAM->alrm_timer != NULL) 544 timer_del(NVRAM->alrm_timer); 545 546 if (NVRAM->wd_timer != NULL) 547 timer_del(NVRAM->wd_timer); 548 } 549 550 static void m48t59_reset_sysbus(DeviceState *d) 551 { 552 M48txxSysBusState *sys = M48TXX_SYS_BUS(d); 553 M48t59State *NVRAM = &sys->state; 554 555 m48t59_reset_common(NVRAM); 556 } 557 558 const MemoryRegionOps m48t59_io_ops = { 559 .read = NVRAM_readb, 560 .write = NVRAM_writeb, 561 .impl = { 562 .min_access_size = 1, 563 .max_access_size = 1, 564 }, 565 .endianness = DEVICE_LITTLE_ENDIAN, 566 }; 567 568 /* Initialisation routine */ 569 Nvram *m48t59_init(qemu_irq IRQ, hwaddr mem_base, 570 uint32_t io_base, uint16_t size, int base_year, 571 int model) 572 { 573 DeviceState *dev; 574 SysBusDevice *s; 575 int i; 576 577 for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { 578 if (m48txx_sysbus_info[i].size != size || 579 m48txx_sysbus_info[i].model != model) { 580 continue; 581 } 582 583 dev = qdev_new(m48txx_sysbus_info[i].bus_name); 584 qdev_prop_set_int32(dev, "base-year", base_year); 585 s = SYS_BUS_DEVICE(dev); 586 sysbus_realize_and_unref(s, &error_fatal); 587 sysbus_connect_irq(s, 0, IRQ); 588 if (io_base != 0) { 589 memory_region_add_subregion(get_system_io(), io_base, 590 sysbus_mmio_get_region(s, 1)); 591 } 592 if (mem_base != 0) { 593 sysbus_mmio_map(s, 0, mem_base); 594 } 595 596 return NVRAM(s); 597 } 598 599 assert(false); 600 return NULL; 601 } 602 603 void m48t59_realize_common(M48t59State *s, Error **errp) 604 { 605 s->buffer = g_malloc0(s->size); 606 if (s->model == 59) { 607 s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s); 608 s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s); 609 } 610 qemu_get_timedate(&s->alarm, 0); 611 } 612 613 static void m48t59_init1(Object *obj) 614 { 615 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(obj); 616 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 617 SysBusDevice *dev = SYS_BUS_DEVICE(obj); 618 M48t59State *s = &d->state; 619 620 s->model = u->info.model; 621 s->size = u->info.size; 622 sysbus_init_irq(dev, &s->IRQ); 623 624 memory_region_init_io(&s->iomem, obj, &nvram_ops, s, "m48t59.nvram", 625 s->size); 626 memory_region_init_io(&d->io, obj, &m48t59_io_ops, s, "m48t59", 4); 627 } 628 629 static void m48t59_realize(DeviceState *dev, Error **errp) 630 { 631 M48txxSysBusState *d = M48TXX_SYS_BUS(dev); 632 M48t59State *s = &d->state; 633 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 634 635 sysbus_init_mmio(sbd, &s->iomem); 636 sysbus_init_mmio(sbd, &d->io); 637 m48t59_realize_common(s, errp); 638 } 639 640 static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr) 641 { 642 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 643 return m48t59_read(&d->state, addr); 644 } 645 646 static void m48txx_sysbus_write(Nvram *obj, uint32_t addr, uint32_t val) 647 { 648 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 649 m48t59_write(&d->state, addr, val); 650 } 651 652 static void m48txx_sysbus_toggle_lock(Nvram *obj, int lock) 653 { 654 M48txxSysBusState *d = M48TXX_SYS_BUS(obj); 655 m48t59_toggle_lock(&d->state, lock); 656 } 657 658 static Property m48t59_sysbus_properties[] = { 659 DEFINE_PROP_INT32("base-year", M48txxSysBusState, state.base_year, 0), 660 DEFINE_PROP_END_OF_LIST(), 661 }; 662 663 static void m48txx_sysbus_class_init(ObjectClass *klass, void *data) 664 { 665 DeviceClass *dc = DEVICE_CLASS(klass); 666 NvramClass *nc = NVRAM_CLASS(klass); 667 668 dc->realize = m48t59_realize; 669 dc->reset = m48t59_reset_sysbus; 670 device_class_set_props(dc, m48t59_sysbus_properties); 671 dc->vmsd = &vmstate_m48t59; 672 nc->read = m48txx_sysbus_read; 673 nc->write = m48txx_sysbus_write; 674 nc->toggle_lock = m48txx_sysbus_toggle_lock; 675 } 676 677 static void m48txx_sysbus_concrete_class_init(ObjectClass *klass, void *data) 678 { 679 M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_CLASS(klass); 680 M48txxInfo *info = data; 681 682 u->info = *info; 683 } 684 685 static const TypeInfo nvram_info = { 686 .name = TYPE_NVRAM, 687 .parent = TYPE_INTERFACE, 688 .class_size = sizeof(NvramClass), 689 }; 690 691 static const TypeInfo m48txx_sysbus_type_info = { 692 .name = TYPE_M48TXX_SYS_BUS, 693 .parent = TYPE_SYS_BUS_DEVICE, 694 .instance_size = sizeof(M48txxSysBusState), 695 .instance_init = m48t59_init1, 696 .abstract = true, 697 .class_init = m48txx_sysbus_class_init, 698 .interfaces = (InterfaceInfo[]) { 699 { TYPE_NVRAM }, 700 { } 701 } 702 }; 703 704 static void m48t59_register_types(void) 705 { 706 TypeInfo sysbus_type_info = { 707 .parent = TYPE_M48TXX_SYS_BUS, 708 .class_size = sizeof(M48txxSysBusDeviceClass), 709 .class_init = m48txx_sysbus_concrete_class_init, 710 }; 711 int i; 712 713 type_register_static(&nvram_info); 714 type_register_static(&m48txx_sysbus_type_info); 715 716 for (i = 0; i < ARRAY_SIZE(m48txx_sysbus_info); i++) { 717 sysbus_type_info.name = m48txx_sysbus_info[i].bus_name; 718 sysbus_type_info.class_data = &m48txx_sysbus_info[i]; 719 type_register(&sysbus_type_info); 720 } 721 } 722 723 type_init(m48t59_register_types) 724