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