Statistics
| Branch: | Revision:

root / hw / timer / m48t59.c @ efec3dd6

History | View | Annotate | Download (20.7 kB)

1
/*
2
 * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
3
 *
4
 * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw/hw.h"
25
#include "hw/timer/m48t59.h"
26
#include "qemu/timer.h"
27
#include "sysemu/sysemu.h"
28
#include "hw/sysbus.h"
29
#include "hw/isa/isa.h"
30
#include "exec/address-spaces.h"
31

    
32
//#define DEBUG_NVRAM
33

    
34
#if defined(DEBUG_NVRAM)
35
#define NVRAM_PRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
36
#else
37
#define NVRAM_PRINTF(fmt, ...) do { } while (0)
38
#endif
39

    
40
/*
41
 * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
42
 * alarm and a watchdog timer and related control registers. In the
43
 * PPC platform there is also a nvram lock function.
44
 */
45

    
46
/*
47
 * Chipset docs:
48
 * http://www.st.com/stonline/products/literature/ds/2410/m48t02.pdf
49
 * http://www.st.com/stonline/products/literature/ds/2411/m48t08.pdf
50
 * http://www.st.com/stonline/products/literature/od/7001/m48t59y.pdf
51
 */
52

    
53
struct M48t59State {
54
    /* Hardware parameters */
55
    qemu_irq IRQ;
56
    MemoryRegion iomem;
57
    uint32_t io_base;
58
    uint32_t size;
59
    /* RTC management */
60
    time_t   time_offset;
61
    time_t   stop_time;
62
    /* Alarm & watchdog */
63
    struct tm alarm;
64
    QEMUTimer *alrm_timer;
65
    QEMUTimer *wd_timer;
66
    /* NVRAM storage */
67
    uint8_t *buffer;
68
    /* Model parameters */
69
    uint32_t model; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */
70
    /* NVRAM storage */
71
    uint16_t addr;
72
    uint8_t  lock;
73
};
74

    
75
#define TYPE_ISA_M48T59 "m48t59_isa"
76
#define ISA_M48T59(obj) \
77
    OBJECT_CHECK(M48t59ISAState, (obj), TYPE_ISA_M48T59)
78

    
79
typedef struct M48t59ISAState {
80
    ISADevice parent_obj;
81

    
82
    M48t59State state;
83
    MemoryRegion io;
84
} M48t59ISAState;
85

    
86
#define SYSBUS_M48T59(obj) \
87
    OBJECT_CHECK(M48t59SysBusState, (obj), TYPE_SYSBUS_M48T59)
88

    
89
typedef struct M48t59SysBusState {
90
    SysBusDevice parent_obj;
91

    
92
    M48t59State state;
93
    MemoryRegion io;
94
} M48t59SysBusState;
95

    
96
/* Fake timer functions */
97

    
98
/* Alarm management */
99
static void alarm_cb (void *opaque)
100
{
101
    struct tm tm;
102
    uint64_t next_time;
103
    M48t59State *NVRAM = opaque;
104

    
105
    qemu_set_irq(NVRAM->IRQ, 1);
106
    if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
107
        (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
108
        (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
109
        (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
110
        /* Repeat once a month */
111
        qemu_get_timedate(&tm, NVRAM->time_offset);
112
        tm.tm_mon++;
113
        if (tm.tm_mon == 13) {
114
            tm.tm_mon = 1;
115
            tm.tm_year++;
116
        }
117
        next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
118
    } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
119
               (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
120
               (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
121
               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
122
        /* Repeat once a day */
123
        next_time = 24 * 60 * 60;
124
    } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
125
               (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
126
               (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
127
               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
128
        /* Repeat once an hour */
129
        next_time = 60 * 60;
130
    } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
131
               (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
132
               (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
133
               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
134
        /* Repeat once a minute */
135
        next_time = 60;
136
    } else {
137
        /* Repeat once a second */
138
        next_time = 1;
139
    }
140
    timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) +
141
                    next_time * 1000);
142
    qemu_set_irq(NVRAM->IRQ, 0);
143
}
144

    
145
static void set_alarm(M48t59State *NVRAM)
146
{
147
    int diff;
148
    if (NVRAM->alrm_timer != NULL) {
149
        timer_del(NVRAM->alrm_timer);
150
        diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
151
        if (diff > 0)
152
            timer_mod(NVRAM->alrm_timer, diff * 1000);
153
    }
154
}
155

    
156
/* RTC management helpers */
157
static inline void get_time(M48t59State *NVRAM, struct tm *tm)
158
{
159
    qemu_get_timedate(tm, NVRAM->time_offset);
160
}
161

    
162
static void set_time(M48t59State *NVRAM, struct tm *tm)
163
{
164
    NVRAM->time_offset = qemu_timedate_diff(tm);
165
    set_alarm(NVRAM);
166
}
167

    
168
/* Watchdog management */
169
static void watchdog_cb (void *opaque)
170
{
171
    M48t59State *NVRAM = opaque;
172

    
173
    NVRAM->buffer[0x1FF0] |= 0x80;
174
    if (NVRAM->buffer[0x1FF7] & 0x80) {
175
        NVRAM->buffer[0x1FF7] = 0x00;
176
        NVRAM->buffer[0x1FFC] &= ~0x40;
177
        /* May it be a hw CPU Reset instead ? */
178
        qemu_system_reset_request();
179
    } else {
180
        qemu_set_irq(NVRAM->IRQ, 1);
181
        qemu_set_irq(NVRAM->IRQ, 0);
182
    }
183
}
184

    
185
static void set_up_watchdog(M48t59State *NVRAM, uint8_t value)
186
{
187
    uint64_t interval; /* in 1/16 seconds */
188

    
189
    NVRAM->buffer[0x1FF0] &= ~0x80;
190
    if (NVRAM->wd_timer != NULL) {
191
        timer_del(NVRAM->wd_timer);
192
        if (value != 0) {
193
            interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
194
            timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
195
                           ((interval * 1000) >> 4));
196
        }
197
    }
198
}
199

    
200
/* Direct access to NVRAM */
201
void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
202
{
203
    M48t59State *NVRAM = opaque;
204
    struct tm tm;
205
    int tmp;
206

    
207
    if (addr > 0x1FF8 && addr < 0x2000)
208
        NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
209

    
210
    /* check for NVRAM access */
211
    if ((NVRAM->model == 2 && addr < 0x7f8) ||
212
        (NVRAM->model == 8 && addr < 0x1ff8) ||
213
        (NVRAM->model == 59 && addr < 0x1ff0)) {
214
        goto do_write;
215
    }
216

    
217
    /* TOD access */
218
    switch (addr) {
219
    case 0x1FF0:
220
        /* flags register : read-only */
221
        break;
222
    case 0x1FF1:
223
        /* unused */
224
        break;
225
    case 0x1FF2:
226
        /* alarm seconds */
227
        tmp = from_bcd(val & 0x7F);
228
        if (tmp >= 0 && tmp <= 59) {
229
            NVRAM->alarm.tm_sec = tmp;
230
            NVRAM->buffer[0x1FF2] = val;
231
            set_alarm(NVRAM);
232
        }
233
        break;
234
    case 0x1FF3:
235
        /* alarm minutes */
236
        tmp = from_bcd(val & 0x7F);
237
        if (tmp >= 0 && tmp <= 59) {
238
            NVRAM->alarm.tm_min = tmp;
239
            NVRAM->buffer[0x1FF3] = val;
240
            set_alarm(NVRAM);
241
        }
242
        break;
243
    case 0x1FF4:
244
        /* alarm hours */
245
        tmp = from_bcd(val & 0x3F);
246
        if (tmp >= 0 && tmp <= 23) {
247
            NVRAM->alarm.tm_hour = tmp;
248
            NVRAM->buffer[0x1FF4] = val;
249
            set_alarm(NVRAM);
250
        }
251
        break;
252
    case 0x1FF5:
253
        /* alarm date */
254
        tmp = from_bcd(val & 0x3F);
255
        if (tmp != 0) {
256
            NVRAM->alarm.tm_mday = tmp;
257
            NVRAM->buffer[0x1FF5] = val;
258
            set_alarm(NVRAM);
259
        }
260
        break;
261
    case 0x1FF6:
262
        /* interrupts */
263
        NVRAM->buffer[0x1FF6] = val;
264
        break;
265
    case 0x1FF7:
266
        /* watchdog */
267
        NVRAM->buffer[0x1FF7] = val;
268
        set_up_watchdog(NVRAM, val);
269
        break;
270
    case 0x1FF8:
271
    case 0x07F8:
272
        /* control */
273
       NVRAM->buffer[addr] = (val & ~0xA0) | 0x90;
274
        break;
275
    case 0x1FF9:
276
    case 0x07F9:
277
        /* seconds (BCD) */
278
        tmp = from_bcd(val & 0x7F);
279
        if (tmp >= 0 && tmp <= 59) {
280
            get_time(NVRAM, &tm);
281
            tm.tm_sec = tmp;
282
            set_time(NVRAM, &tm);
283
        }
284
        if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
285
            if (val & 0x80) {
286
                NVRAM->stop_time = time(NULL);
287
            } else {
288
                NVRAM->time_offset += NVRAM->stop_time - time(NULL);
289
                NVRAM->stop_time = 0;
290
            }
291
        }
292
        NVRAM->buffer[addr] = val & 0x80;
293
        break;
294
    case 0x1FFA:
295
    case 0x07FA:
296
        /* minutes (BCD) */
297
        tmp = from_bcd(val & 0x7F);
298
        if (tmp >= 0 && tmp <= 59) {
299
            get_time(NVRAM, &tm);
300
            tm.tm_min = tmp;
301
            set_time(NVRAM, &tm);
302
        }
303
        break;
304
    case 0x1FFB:
305
    case 0x07FB:
306
        /* hours (BCD) */
307
        tmp = from_bcd(val & 0x3F);
308
        if (tmp >= 0 && tmp <= 23) {
309
            get_time(NVRAM, &tm);
310
            tm.tm_hour = tmp;
311
            set_time(NVRAM, &tm);
312
        }
313
        break;
314
    case 0x1FFC:
315
    case 0x07FC:
316
        /* day of the week / century */
317
        tmp = from_bcd(val & 0x07);
318
        get_time(NVRAM, &tm);
319
        tm.tm_wday = tmp;
320
        set_time(NVRAM, &tm);
321
        NVRAM->buffer[addr] = val & 0x40;
322
        break;
323
    case 0x1FFD:
324
    case 0x07FD:
325
        /* date (BCD) */
326
       tmp = from_bcd(val & 0x3F);
327
        if (tmp != 0) {
328
            get_time(NVRAM, &tm);
329
            tm.tm_mday = tmp;
330
            set_time(NVRAM, &tm);
331
        }
332
        break;
333
    case 0x1FFE:
334
    case 0x07FE:
335
        /* month */
336
        tmp = from_bcd(val & 0x1F);
337
        if (tmp >= 1 && tmp <= 12) {
338
            get_time(NVRAM, &tm);
339
            tm.tm_mon = tmp - 1;
340
            set_time(NVRAM, &tm);
341
        }
342
        break;
343
    case 0x1FFF:
344
    case 0x07FF:
345
        /* year */
346
        tmp = from_bcd(val);
347
        if (tmp >= 0 && tmp <= 99) {
348
            get_time(NVRAM, &tm);
349
            if (NVRAM->model == 8) {
350
                tm.tm_year = from_bcd(val) + 68; // Base year is 1968
351
            } else {
352
                tm.tm_year = from_bcd(val);
353
            }
354
            set_time(NVRAM, &tm);
355
        }
356
        break;
357
    default:
358
        /* Check lock registers state */
359
        if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
360
            break;
361
        if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
362
            break;
363
    do_write:
364
        if (addr < NVRAM->size) {
365
            NVRAM->buffer[addr] = val & 0xFF;
366
        }
367
        break;
368
    }
369
}
370

    
371
uint32_t m48t59_read (void *opaque, uint32_t addr)
372
{
373
    M48t59State *NVRAM = opaque;
374
    struct tm tm;
375
    uint32_t retval = 0xFF;
376

    
377
    /* check for NVRAM access */
378
    if ((NVRAM->model == 2 && addr < 0x078f) ||
379
        (NVRAM->model == 8 && addr < 0x1ff8) ||
380
        (NVRAM->model == 59 && addr < 0x1ff0)) {
381
        goto do_read;
382
    }
383

    
384
    /* TOD access */
385
    switch (addr) {
386
    case 0x1FF0:
387
        /* flags register */
388
        goto do_read;
389
    case 0x1FF1:
390
        /* unused */
391
        retval = 0;
392
        break;
393
    case 0x1FF2:
394
        /* alarm seconds */
395
        goto do_read;
396
    case 0x1FF3:
397
        /* alarm minutes */
398
        goto do_read;
399
    case 0x1FF4:
400
        /* alarm hours */
401
        goto do_read;
402
    case 0x1FF5:
403
        /* alarm date */
404
        goto do_read;
405
    case 0x1FF6:
406
        /* interrupts */
407
        goto do_read;
408
    case 0x1FF7:
409
        /* A read resets the watchdog */
410
        set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
411
        goto do_read;
412
    case 0x1FF8:
413
    case 0x07F8:
414
        /* control */
415
        goto do_read;
416
    case 0x1FF9:
417
    case 0x07F9:
418
        /* seconds (BCD) */
419
        get_time(NVRAM, &tm);
420
        retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec);
421
        break;
422
    case 0x1FFA:
423
    case 0x07FA:
424
        /* minutes (BCD) */
425
        get_time(NVRAM, &tm);
426
        retval = to_bcd(tm.tm_min);
427
        break;
428
    case 0x1FFB:
429
    case 0x07FB:
430
        /* hours (BCD) */
431
        get_time(NVRAM, &tm);
432
        retval = to_bcd(tm.tm_hour);
433
        break;
434
    case 0x1FFC:
435
    case 0x07FC:
436
        /* day of the week / century */
437
        get_time(NVRAM, &tm);
438
        retval = NVRAM->buffer[addr] | tm.tm_wday;
439
        break;
440
    case 0x1FFD:
441
    case 0x07FD:
442
        /* date */
443
        get_time(NVRAM, &tm);
444
        retval = to_bcd(tm.tm_mday);
445
        break;
446
    case 0x1FFE:
447
    case 0x07FE:
448
        /* month */
449
        get_time(NVRAM, &tm);
450
        retval = to_bcd(tm.tm_mon + 1);
451
        break;
452
    case 0x1FFF:
453
    case 0x07FF:
454
        /* year */
455
        get_time(NVRAM, &tm);
456
        if (NVRAM->model == 8) {
457
            retval = to_bcd(tm.tm_year - 68); // Base year is 1968
458
        } else {
459
            retval = to_bcd(tm.tm_year);
460
        }
461
        break;
462
    default:
463
        /* Check lock registers state */
464
        if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
465
            break;
466
        if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
467
            break;
468
    do_read:
469
        if (addr < NVRAM->size) {
470
            retval = NVRAM->buffer[addr];
471
        }
472
        break;
473
    }
474
    if (addr > 0x1FF9 && addr < 0x2000)
475
       NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
476

    
477
    return retval;
478
}
479

    
480
void m48t59_toggle_lock (void *opaque, int lock)
481
{
482
    M48t59State *NVRAM = opaque;
483

    
484
    NVRAM->lock ^= 1 << lock;
485
}
486

    
487
/* IO access to NVRAM */
488
static void NVRAM_writeb(void *opaque, hwaddr addr, uint64_t val,
489
                         unsigned size)
490
{
491
    M48t59State *NVRAM = opaque;
492

    
493
    NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
494
    switch (addr) {
495
    case 0:
496
        NVRAM->addr &= ~0x00FF;
497
        NVRAM->addr |= val;
498
        break;
499
    case 1:
500
        NVRAM->addr &= ~0xFF00;
501
        NVRAM->addr |= val << 8;
502
        break;
503
    case 3:
504
        m48t59_write(NVRAM, NVRAM->addr, val);
505
        NVRAM->addr = 0x0000;
506
        break;
507
    default:
508
        break;
509
    }
510
}
511

    
512
static uint64_t NVRAM_readb(void *opaque, hwaddr addr, unsigned size)
513
{
514
    M48t59State *NVRAM = opaque;
515
    uint32_t retval;
516

    
517
    switch (addr) {
518
    case 3:
519
        retval = m48t59_read(NVRAM, NVRAM->addr);
520
        break;
521
    default:
522
        retval = -1;
523
        break;
524
    }
525
    NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
526

    
527
    return retval;
528
}
529

    
530
static void nvram_writeb (void *opaque, hwaddr addr, uint32_t value)
531
{
532
    M48t59State *NVRAM = opaque;
533

    
534
    m48t59_write(NVRAM, addr, value & 0xff);
535
}
536

    
537
static void nvram_writew (void *opaque, hwaddr addr, uint32_t value)
538
{
539
    M48t59State *NVRAM = opaque;
540

    
541
    m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
542
    m48t59_write(NVRAM, addr + 1, value & 0xff);
543
}
544

    
545
static void nvram_writel (void *opaque, hwaddr addr, uint32_t value)
546
{
547
    M48t59State *NVRAM = opaque;
548

    
549
    m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
550
    m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
551
    m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
552
    m48t59_write(NVRAM, addr + 3, value & 0xff);
553
}
554

    
555
static uint32_t nvram_readb (void *opaque, hwaddr addr)
556
{
557
    M48t59State *NVRAM = opaque;
558
    uint32_t retval;
559

    
560
    retval = m48t59_read(NVRAM, addr);
561
    return retval;
562
}
563

    
564
static uint32_t nvram_readw (void *opaque, hwaddr addr)
565
{
566
    M48t59State *NVRAM = opaque;
567
    uint32_t retval;
568

    
569
    retval = m48t59_read(NVRAM, addr) << 8;
570
    retval |= m48t59_read(NVRAM, addr + 1);
571
    return retval;
572
}
573

    
574
static uint32_t nvram_readl (void *opaque, hwaddr addr)
575
{
576
    M48t59State *NVRAM = opaque;
577
    uint32_t retval;
578

    
579
    retval = m48t59_read(NVRAM, addr) << 24;
580
    retval |= m48t59_read(NVRAM, addr + 1) << 16;
581
    retval |= m48t59_read(NVRAM, addr + 2) << 8;
582
    retval |= m48t59_read(NVRAM, addr + 3);
583
    return retval;
584
}
585

    
586
static const MemoryRegionOps nvram_ops = {
587
    .old_mmio = {
588
        .read = { nvram_readb, nvram_readw, nvram_readl, },
589
        .write = { nvram_writeb, nvram_writew, nvram_writel, },
590
    },
591
    .endianness = DEVICE_NATIVE_ENDIAN,
592
};
593

    
594
static const VMStateDescription vmstate_m48t59 = {
595
    .name = "m48t59",
596
    .version_id = 1,
597
    .minimum_version_id = 1,
598
    .minimum_version_id_old = 1,
599
    .fields      = (VMStateField[]) {
600
        VMSTATE_UINT8(lock, M48t59State),
601
        VMSTATE_UINT16(addr, M48t59State),
602
        VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size),
603
        VMSTATE_END_OF_LIST()
604
    }
605
};
606

    
607
static void m48t59_reset_common(M48t59State *NVRAM)
608
{
609
    NVRAM->addr = 0;
610
    NVRAM->lock = 0;
611
    if (NVRAM->alrm_timer != NULL)
612
        timer_del(NVRAM->alrm_timer);
613

    
614
    if (NVRAM->wd_timer != NULL)
615
        timer_del(NVRAM->wd_timer);
616
}
617

    
618
static void m48t59_reset_isa(DeviceState *d)
619
{
620
    M48t59ISAState *isa = ISA_M48T59(d);
621
    M48t59State *NVRAM = &isa->state;
622

    
623
    m48t59_reset_common(NVRAM);
624
}
625

    
626
static void m48t59_reset_sysbus(DeviceState *d)
627
{
628
    M48t59SysBusState *sys = SYSBUS_M48T59(d);
629
    M48t59State *NVRAM = &sys->state;
630

    
631
    m48t59_reset_common(NVRAM);
632
}
633

    
634
static const MemoryRegionOps m48t59_io_ops = {
635
    .read = NVRAM_readb,
636
    .write = NVRAM_writeb,
637
    .impl = {
638
        .min_access_size = 1,
639
        .max_access_size = 1,
640
    },
641
    .endianness = DEVICE_LITTLE_ENDIAN,
642
};
643

    
644
/* Initialisation routine */
645
M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
646
                         uint32_t io_base, uint16_t size, int model)
647
{
648
    DeviceState *dev;
649
    SysBusDevice *s;
650
    M48t59SysBusState *d;
651
    M48t59State *state;
652

    
653
    dev = qdev_create(NULL, TYPE_SYSBUS_M48T59);
654
    qdev_prop_set_uint32(dev, "model", model);
655
    qdev_prop_set_uint32(dev, "size", size);
656
    qdev_prop_set_uint32(dev, "io_base", io_base);
657
    qdev_init_nofail(dev);
658
    s = SYS_BUS_DEVICE(dev);
659
    d = SYSBUS_M48T59(dev);
660
    state = &d->state;
661
    sysbus_connect_irq(s, 0, IRQ);
662
    memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, state,
663
                          "m48t59", 4);
664
    if (io_base != 0) {
665
        memory_region_add_subregion(get_system_io(), io_base, &d->io);
666
    }
667
    if (mem_base != 0) {
668
        sysbus_mmio_map(s, 0, mem_base);
669
    }
670

    
671
    return state;
672
}
673

    
674
M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size,
675
                             int model)
676
{
677
    M48t59ISAState *d;
678
    ISADevice *isadev;
679
    DeviceState *dev;
680
    M48t59State *s;
681

    
682
    isadev = isa_create(bus, TYPE_ISA_M48T59);
683
    dev = DEVICE(isadev);
684
    qdev_prop_set_uint32(dev, "model", model);
685
    qdev_prop_set_uint32(dev, "size", size);
686
    qdev_prop_set_uint32(dev, "io_base", io_base);
687
    qdev_init_nofail(dev);
688
    d = ISA_M48T59(isadev);
689
    s = &d->state;
690

    
691
    memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, s, "m48t59", 4);
692
    if (io_base != 0) {
693
        isa_register_ioport(isadev, &d->io, io_base);
694
    }
695

    
696
    return s;
697
}
698

    
699
static void m48t59_realize_common(M48t59State *s, Error **errp)
700
{
701
    s->buffer = g_malloc0(s->size);
702
    if (s->model == 59) {
703
        s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s);
704
        s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s);
705
    }
706
    qemu_get_timedate(&s->alarm, 0);
707

    
708
    vmstate_register(NULL, -1, &vmstate_m48t59, s);
709
}
710

    
711
static void m48t59_isa_realize(DeviceState *dev, Error **errp)
712
{
713
    ISADevice *isadev = ISA_DEVICE(dev);
714
    M48t59ISAState *d = ISA_M48T59(dev);
715
    M48t59State *s = &d->state;
716

    
717
    isa_init_irq(isadev, &s->IRQ, 8);
718
    m48t59_realize_common(s, errp);
719
}
720

    
721
static int m48t59_init1(SysBusDevice *dev)
722
{
723
    M48t59SysBusState *d = SYSBUS_M48T59(dev);
724
    M48t59State *s = &d->state;
725
    Error *err = NULL;
726

    
727
    sysbus_init_irq(dev, &s->IRQ);
728

    
729
    memory_region_init_io(&s->iomem, OBJECT(d), &nvram_ops, s,
730
                          "m48t59.nvram", s->size);
731
    sysbus_init_mmio(dev, &s->iomem);
732
    m48t59_realize_common(s, &err);
733
    if (err != NULL) {
734
        error_free(err);
735
        return -1;
736
    }
737

    
738
    return 0;
739
}
740

    
741
static Property m48t59_isa_properties[] = {
742
    DEFINE_PROP_UINT32("size",    M48t59ISAState, state.size,    -1),
743
    DEFINE_PROP_UINT32("model",   M48t59ISAState, state.model,   -1),
744
    DEFINE_PROP_HEX32( "io_base", M48t59ISAState, state.io_base,  0),
745
    DEFINE_PROP_END_OF_LIST(),
746
};
747

    
748
static void m48t59_isa_class_init(ObjectClass *klass, void *data)
749
{
750
    DeviceClass *dc = DEVICE_CLASS(klass);
751

    
752
    dc->realize = m48t59_isa_realize;
753
    dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */
754
    dc->reset = m48t59_reset_isa;
755
    dc->props = m48t59_isa_properties;
756
}
757

    
758
static const TypeInfo m48t59_isa_info = {
759
    .name          = TYPE_ISA_M48T59,
760
    .parent        = TYPE_ISA_DEVICE,
761
    .instance_size = sizeof(M48t59ISAState),
762
    .class_init    = m48t59_isa_class_init,
763
};
764

    
765
static Property m48t59_properties[] = {
766
    DEFINE_PROP_UINT32("size",    M48t59SysBusState, state.size,    -1),
767
    DEFINE_PROP_UINT32("model",   M48t59SysBusState, state.model,   -1),
768
    DEFINE_PROP_HEX32( "io_base", M48t59SysBusState, state.io_base,  0),
769
    DEFINE_PROP_END_OF_LIST(),
770
};
771

    
772
static void m48t59_class_init(ObjectClass *klass, void *data)
773
{
774
    DeviceClass *dc = DEVICE_CLASS(klass);
775
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
776

    
777
    k->init = m48t59_init1;
778
    dc->reset = m48t59_reset_sysbus;
779
    dc->props = m48t59_properties;
780
}
781

    
782
static const TypeInfo m48t59_info = {
783
    .name          = TYPE_SYSBUS_M48T59,
784
    .parent        = TYPE_SYS_BUS_DEVICE,
785
    .instance_size = sizeof(M48t59SysBusState),
786
    .class_init    = m48t59_class_init,
787
};
788

    
789
static void m48t59_register_types(void)
790
{
791
    type_register_static(&m48t59_info);
792
    type_register_static(&m48t59_isa_info);
793
}
794

    
795
type_init(m48t59_register_types)