tests/tcg: Do not require FE_* exception bits
[qemu.git] / hw / rtc / m48t59.c
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)