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