xref: /openbmc/qemu/hw/ppc/pnv_chiptod.c (revision cde2ba34)
1 /*
2  * QEMU PowerPC PowerNV Emulation of some ChipTOD behaviour
3  *
4  * Copyright (c) 2022-2023, IBM Corporation.
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  *
8  * ChipTOD (aka TOD) is a facility implemented in the nest / pervasive. The
9  * purpose is to keep time-of-day across chips and cores.
10  *
11  * There is a master chip TOD, which sends signals to slave chip TODs to
12  * keep them synchronized. There are two sets of configuration registers
13  * called primary and secondary, which can be used fail over.
14  *
15  * The chip TOD also distributes synchronisation signals to the timebase
16  * facility in each of the cores on the chip. In particular there is a
17  * feature that can move the TOD value in the ChipTOD to and from the TB.
18  *
19  * Initialisation typically brings all ChipTOD into sync (see tod_state),
20  * and then brings each core TB into sync with the ChipTODs (see timebase
21  * state and TFMR). This model is a very basic simulation of the init sequence
22  * performed by skiboot.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "sysemu/reset.h"
27 #include "target/ppc/cpu.h"
28 #include "qapi/error.h"
29 #include "qemu/log.h"
30 #include "qemu/module.h"
31 #include "hw/irq.h"
32 #include "hw/qdev-properties.h"
33 #include "hw/ppc/fdt.h"
34 #include "hw/ppc/ppc.h"
35 #include "hw/ppc/pnv.h"
36 #include "hw/ppc/pnv_chip.h"
37 #include "hw/ppc/pnv_core.h"
38 #include "hw/ppc/pnv_xscom.h"
39 #include "hw/ppc/pnv_chiptod.h"
40 #include "trace.h"
41 
42 #include <libfdt.h>
43 
44 /* TOD chip XSCOM addresses */
45 #define TOD_M_PATH_CTRL_REG             0x00000000 /* Master Path ctrl reg */
46 #define TOD_PRI_PORT_0_CTRL_REG         0x00000001 /* Primary port0 ctrl reg */
47 #define TOD_PRI_PORT_1_CTRL_REG         0x00000002 /* Primary port1 ctrl reg */
48 #define TOD_SEC_PORT_0_CTRL_REG         0x00000003 /* Secondary p0 ctrl reg */
49 #define TOD_SEC_PORT_1_CTRL_REG         0x00000004 /* Secondary p1 ctrl reg */
50 #define TOD_S_PATH_CTRL_REG             0x00000005 /* Slave Path ctrl reg */
51 #define TOD_I_PATH_CTRL_REG             0x00000006 /* Internal Path ctrl reg */
52 
53 /* -- TOD primary/secondary master/slave control register -- */
54 #define TOD_PSS_MSS_CTRL_REG            0x00000007
55 
56 /* -- TOD primary/secondary master/slave status register -- */
57 #define TOD_PSS_MSS_STATUS_REG          0x00000008
58 
59 /* TOD chip XSCOM addresses */
60 #define TOD_CHIP_CTRL_REG               0x00000010 /* Chip control reg */
61 
62 #define TOD_TX_TTYPE_0_REG              0x00000011
63 #define TOD_TX_TTYPE_1_REG              0x00000012 /* PSS switch reg */
64 #define TOD_TX_TTYPE_2_REG              0x00000013 /* Enable step checkers */
65 #define TOD_TX_TTYPE_3_REG              0x00000014 /* Request TOD reg */
66 #define TOD_TX_TTYPE_4_REG              0x00000015 /* Send TOD reg */
67 #define TOD_TX_TTYPE_5_REG              0x00000016 /* Invalidate TOD reg */
68 
69 #define TOD_MOVE_TOD_TO_TB_REG          0x00000017
70 #define TOD_LOAD_TOD_MOD_REG            0x00000018
71 #define TOD_LOAD_TOD_REG                0x00000021
72 #define TOD_START_TOD_REG               0x00000022
73 #define TOD_FSM_REG                     0x00000024
74 
75 #define TOD_TX_TTYPE_CTRL_REG           0x00000027 /* TX TTYPE Control reg */
76 #define   TOD_TX_TTYPE_PIB_SLAVE_ADDR      PPC_BITMASK(26, 31)
77 
78 /* -- TOD Error interrupt register -- */
79 #define TOD_ERROR_REG                   0x00000030
80 
81 /* PC unit PIB address which recieves the timebase transfer from TOD */
82 #define   PC_TOD                        0x4A3
83 
84 /*
85  * The TOD FSM:
86  * - The reset state is 0 error.
87  * - A hardware error detected will transition to state 0 from any state.
88  * - LOAD_TOD_MOD and TTYPE5 will transition to state 7 from any state.
89  *
90  * | state      | action                       | new |
91  * |------------+------------------------------+-----|
92  * | 0 error    | LOAD_TOD_MOD                 |  7  |
93  * | 0 error    | Recv TTYPE5 (invalidate TOD) |  7  |
94  * | 7 not_set  | LOAD_TOD (bit-63 = 0)        |  2  |
95  * | 7 not_set  | LOAD_TOD (bit-63 = 1)        |  1  |
96  * | 7 not_set  | Recv TTYPE4 (send TOD)       |  2  |
97  * | 2 running  |                              |     |
98  * | 1 stopped  | START_TOD                    |  2  |
99  *
100  * Note the hardware has additional states but they relate to the sending
101  * and receiving and waiting on synchronisation signals between chips and
102  * are not described or modeled here.
103  */
104 
105 static uint64_t pnv_chiptod_xscom_read(void *opaque, hwaddr addr,
106                                           unsigned size)
107 {
108     PnvChipTOD *chiptod = PNV_CHIPTOD(opaque);
109     uint32_t offset = addr >> 3;
110     uint64_t val = 0;
111 
112     switch (offset) {
113     case TOD_PSS_MSS_STATUS_REG:
114         /*
115          * ChipTOD does not support configurations other than primary
116          * master, does not support errors, etc.
117          */
118         val |= PPC_BITMASK(6, 10); /* STEP checker validity */
119         val |= PPC_BIT(12); /* Primary config master path select */
120         if (chiptod->tod_state == tod_running) {
121             val |= PPC_BIT(20); /* Is running */
122         }
123         val |= PPC_BIT(21); /* Is using primary config */
124         val |= PPC_BIT(26); /* Is using master path select */
125 
126         if (chiptod->primary) {
127             val |= PPC_BIT(23); /* Is active master */
128         } else if (chiptod->secondary) {
129             val |= PPC_BIT(24); /* Is backup master */
130         } else {
131             val |= PPC_BIT(25); /* Is slave (should backup master set this?) */
132         }
133         break;
134     case TOD_PSS_MSS_CTRL_REG:
135         val = chiptod->pss_mss_ctrl_reg;
136         break;
137     case TOD_TX_TTYPE_CTRL_REG:
138         val = 0;
139         break;
140     case TOD_ERROR_REG:
141         val = chiptod->tod_error;
142         break;
143     case TOD_FSM_REG:
144         if (chiptod->tod_state == tod_running) {
145             val |= PPC_BIT(4);
146         }
147         break;
148     default:
149         qemu_log_mask(LOG_UNIMP, "pnv_chiptod: unimplemented register: Ox%"
150                       HWADDR_PRIx "\n", addr >> 3);
151     }
152 
153     trace_pnv_chiptod_xscom_read(addr >> 3, val);
154 
155     return val;
156 }
157 
158 static void chiptod_receive_ttype(PnvChipTOD *chiptod, uint32_t trigger)
159 {
160     switch (trigger) {
161     case TOD_TX_TTYPE_4_REG:
162         if (chiptod->tod_state != tod_not_set) {
163             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: received TTYPE4 in "
164                           " state %d, should be in 7 (TOD_NOT_SET)\n",
165                           chiptod->tod_state);
166         } else {
167             chiptod->tod_state = tod_running;
168         }
169         break;
170     case TOD_TX_TTYPE_5_REG:
171         /* Works from any state */
172         chiptod->tod_state = tod_not_set;
173         break;
174     default:
175         qemu_log_mask(LOG_UNIMP, "pnv_chiptod: received unimplemented "
176                       " TTYPE %u\n", trigger);
177         break;
178     }
179 }
180 
181 static void chiptod_power9_broadcast_ttype(PnvChipTOD *sender,
182                                             uint32_t trigger)
183 {
184     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
185     int i;
186 
187     for (i = 0; i < pnv->num_chips; i++) {
188         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
189         PnvChipTOD *chiptod = &chip9->chiptod;
190 
191         if (chiptod != sender) {
192             chiptod_receive_ttype(chiptod, trigger);
193         }
194     }
195 }
196 
197 static void chiptod_power10_broadcast_ttype(PnvChipTOD *sender,
198                                             uint32_t trigger)
199 {
200     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
201     int i;
202 
203     for (i = 0; i < pnv->num_chips; i++) {
204         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
205         PnvChipTOD *chiptod = &chip10->chiptod;
206 
207         if (chiptod != sender) {
208             chiptod_receive_ttype(chiptod, trigger);
209         }
210     }
211 }
212 
213 static PnvCore *pnv_chip_get_core_by_xscom_base(PnvChip *chip,
214                                                 uint32_t xscom_base)
215 {
216     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
217     int i;
218 
219     for (i = 0; i < chip->nr_cores; i++) {
220         PnvCore *pc = chip->cores[i];
221         CPUCore *cc = CPU_CORE(pc);
222         int core_hwid = cc->core_id;
223 
224         if (pcc->xscom_core_base(chip, core_hwid) == xscom_base) {
225             return pc;
226         }
227     }
228     return NULL;
229 }
230 
231 static PnvCore *chiptod_power9_tx_ttype_target(PnvChipTOD *chiptod,
232                                                uint64_t val)
233 {
234     /*
235      * skiboot uses Core ID for P9, though SCOM should work too.
236      */
237     if (val & PPC_BIT(35)) { /* SCOM addressing */
238         uint32_t addr = val >> 32;
239         uint32_t reg = addr & 0xfff;
240 
241         if (reg != PC_TOD) {
242             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: SCOM addressing: "
243                           "unimplemented slave register 0x%" PRIx32 "\n", reg);
244             return NULL;
245         }
246 
247         return pnv_chip_get_core_by_xscom_base(chiptod->chip, addr & ~0xfff);
248 
249     } else { /* Core ID addressing */
250         uint32_t core_id = GETFIELD(TOD_TX_TTYPE_PIB_SLAVE_ADDR, val) & 0x1f;
251         return pnv_chip_find_core(chiptod->chip, core_id);
252     }
253 }
254 
255 static PnvCore *chiptod_power10_tx_ttype_target(PnvChipTOD *chiptod,
256                                                uint64_t val)
257 {
258     /*
259      * skiboot uses SCOM for P10 because Core ID was unable to be made to
260      * work correctly. For this reason only SCOM addressing is implemented.
261      */
262     if (val & PPC_BIT(35)) { /* SCOM addressing */
263         uint32_t addr = val >> 32;
264         uint32_t reg = addr & 0xfff;
265 
266         if (reg != PC_TOD) {
267             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: SCOM addressing: "
268                           "unimplemented slave register 0x%" PRIx32 "\n", reg);
269             return NULL;
270         }
271 
272         /*
273          * This may not deal with P10 big-core addressing at the moment.
274          * The big-core code in skiboot syncs small cores, but it targets
275          * the even PIR (first small-core) when syncing second small-core.
276          */
277         return pnv_chip_get_core_by_xscom_base(chiptod->chip, addr & ~0xfff);
278 
279     } else { /* Core ID addressing */
280         qemu_log_mask(LOG_UNIMP, "pnv_chiptod: TX TTYPE Core ID "
281                       "addressing is not implemented for POWER10\n");
282         return NULL;
283     }
284 }
285 
286 static void pnv_chiptod_xscom_write(void *opaque, hwaddr addr,
287                                     uint64_t val, unsigned size)
288 {
289     PnvChipTOD *chiptod = PNV_CHIPTOD(opaque);
290     PnvChipTODClass *pctc = PNV_CHIPTOD_GET_CLASS(chiptod);
291     uint32_t offset = addr >> 3;
292 
293     trace_pnv_chiptod_xscom_write(addr >> 3, val);
294 
295     switch (offset) {
296     case TOD_PSS_MSS_CTRL_REG:
297         /* Is this correct? */
298         if (chiptod->primary) {
299             val |= PPC_BIT(1); /* TOD is master */
300         } else {
301             val &= ~PPC_BIT(1);
302         }
303         val |= PPC_BIT(2); /* Drawer is master (don't simulate multi-drawer) */
304         chiptod->pss_mss_ctrl_reg = val & PPC_BITMASK(0, 31);
305         break;
306 
307     case TOD_TX_TTYPE_CTRL_REG:
308         /*
309          * This register sets the target of the TOD value transfer initiated
310          * by TOD_MOVE_TOD_TO_TB. The TOD is able to send the address to
311          * any target register, though in practice only the PC TOD register
312          * should be used. ChipTOD has a "SCOM addressing" mode which fully
313          * specifies the SCOM address, and a core-ID mode which uses the
314          * core ID to target the PC TOD for a given core.
315          */
316         chiptod->slave_pc_target = pctc->tx_ttype_target(chiptod, val);
317         if (!chiptod->slave_pc_target) {
318             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
319                           " TOD_TX_TTYPE_CTRL_REG val 0x%" PRIx64
320                           " invalid slave address\n", val);
321         }
322         break;
323     case TOD_ERROR_REG:
324         chiptod->tod_error &= ~val;
325         break;
326     case TOD_LOAD_TOD_MOD_REG:
327         if (!(val & PPC_BIT(0))) {
328             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
329                           " TOD_LOAD_TOD_MOD_REG with bad val 0x%" PRIx64"\n",
330                           val);
331         } else {
332             chiptod->tod_state = tod_not_set;
333         }
334         break;
335     case TOD_LOAD_TOD_REG:
336         if (chiptod->tod_state != tod_not_set) {
337             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: LOAD_TOG_REG in "
338                           " state %d, should be in 7 (TOD_NOT_SET)\n",
339                           chiptod->tod_state);
340         } else {
341             if (val & PPC_BIT(63)) {
342                 chiptod->tod_state = tod_stopped;
343             } else {
344                 chiptod->tod_state = tod_running;
345             }
346         }
347         break;
348 
349     case TOD_MOVE_TOD_TO_TB_REG:
350         /*
351          * XXX: it should be a cleaner model to have this drive a SCOM
352          * transaction to the target address, and implement the state machine
353          * in the PnvCore. For now, this hack makes things work.
354          */
355         if (chiptod->tod_state != tod_running) {
356             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
357                           " TOD_MOVE_TOD_TO_TB_REG in bad state %d\n",
358                           chiptod->tod_state);
359         } else if (!(val & PPC_BIT(0))) {
360             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
361                           " TOD_MOVE_TOD_TO_TB_REG with bad val 0x%" PRIx64"\n",
362                           val);
363         } else if (chiptod->slave_pc_target == NULL) {
364             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
365                           " TOD_MOVE_TOD_TO_TB_REG with no slave target\n");
366         } else {
367             PowerPCCPU *cpu = chiptod->slave_pc_target->threads[0];
368             CPUPPCState *env = &cpu->env;
369 
370             /*
371              * Moving TOD to TB will set the TB of all threads in a
372              * core, so skiboot only does this once per thread0, so
373              * that is where we keep the timebase state machine.
374              *
375              * It is likely possible for TBST to be driven from other
376              * threads in the core, but for now we only implement it for
377              * thread 0.
378              */
379 
380             if (env->pnv_tod_tbst.tb_ready_for_tod) {
381                 env->pnv_tod_tbst.tod_sent_to_tb = 1;
382             } else {
383                 qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg"
384                               " TOD_MOVE_TOD_TO_TB_REG with TB not ready to"
385                               " receive TOD\n");
386             }
387         }
388         break;
389     case TOD_START_TOD_REG:
390         if (chiptod->tod_state != tod_stopped) {
391             qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: LOAD_TOG_REG in "
392                           " state %d, should be in 1 (TOD_STOPPED)\n",
393                           chiptod->tod_state);
394         } else {
395             chiptod->tod_state = tod_running;
396         }
397         break;
398     case TOD_TX_TTYPE_4_REG:
399     case TOD_TX_TTYPE_5_REG:
400         pctc->broadcast_ttype(chiptod, offset);
401         break;
402     default:
403         qemu_log_mask(LOG_UNIMP, "pnv_chiptod: unimplemented register: Ox%"
404                       HWADDR_PRIx "\n", addr >> 3);
405     }
406 }
407 
408 static const MemoryRegionOps pnv_chiptod_xscom_ops = {
409     .read = pnv_chiptod_xscom_read,
410     .write = pnv_chiptod_xscom_write,
411     .valid.min_access_size = 8,
412     .valid.max_access_size = 8,
413     .impl.min_access_size = 8,
414     .impl.max_access_size = 8,
415     .endianness = DEVICE_BIG_ENDIAN,
416 };
417 
418 static int pnv_chiptod_dt_xscom(PnvXScomInterface *dev, void *fdt,
419                                 int xscom_offset,
420                                 const char compat[], size_t compat_size)
421 {
422     PnvChipTOD *chiptod = PNV_CHIPTOD(dev);
423     g_autofree char *name = NULL;
424     int offset;
425     uint32_t chiptod_pcba = PNV9_XSCOM_CHIPTOD_BASE;
426     uint32_t reg[] = {
427         cpu_to_be32(chiptod_pcba),
428         cpu_to_be32(PNV9_XSCOM_CHIPTOD_SIZE)
429     };
430 
431     name = g_strdup_printf("chiptod@%x", chiptod_pcba);
432     offset = fdt_add_subnode(fdt, xscom_offset, name);
433     _FDT(offset);
434 
435     if (chiptod->primary) {
436         _FDT((fdt_setprop(fdt, offset, "primary", NULL, 0)));
437     } else if (chiptod->secondary) {
438         _FDT((fdt_setprop(fdt, offset, "secondary", NULL, 0)));
439     }
440 
441     _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg))));
442     _FDT((fdt_setprop(fdt, offset, "compatible", compat, compat_size)));
443     return 0;
444 }
445 
446 static int pnv_chiptod_power9_dt_xscom(PnvXScomInterface *dev, void *fdt,
447                              int xscom_offset)
448 {
449     const char compat[] = "ibm,power-chiptod\0ibm,power9-chiptod";
450 
451     return pnv_chiptod_dt_xscom(dev, fdt, xscom_offset, compat, sizeof(compat));
452 }
453 
454 static Property pnv_chiptod_properties[] = {
455     DEFINE_PROP_BOOL("primary", PnvChipTOD, primary, false),
456     DEFINE_PROP_BOOL("secondary", PnvChipTOD, secondary, false),
457     DEFINE_PROP_LINK("chip", PnvChipTOD , chip, TYPE_PNV_CHIP, PnvChip *),
458     DEFINE_PROP_END_OF_LIST(),
459 };
460 
461 static void pnv_chiptod_power9_class_init(ObjectClass *klass, void *data)
462 {
463     PnvChipTODClass *pctc = PNV_CHIPTOD_CLASS(klass);
464     DeviceClass *dc = DEVICE_CLASS(klass);
465     PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
466 
467     dc->desc = "PowerNV ChipTOD Controller (POWER9)";
468     device_class_set_props(dc, pnv_chiptod_properties);
469 
470     xdc->dt_xscom = pnv_chiptod_power9_dt_xscom;
471 
472     pctc->broadcast_ttype = chiptod_power9_broadcast_ttype;
473     pctc->tx_ttype_target = chiptod_power9_tx_ttype_target;
474 
475     pctc->xscom_size = PNV_XSCOM_CHIPTOD_SIZE;
476 }
477 
478 static const TypeInfo pnv_chiptod_power9_type_info = {
479     .name          = TYPE_PNV9_CHIPTOD,
480     .parent        = TYPE_PNV_CHIPTOD,
481     .instance_size = sizeof(PnvChipTOD),
482     .class_init    = pnv_chiptod_power9_class_init,
483     .interfaces    = (InterfaceInfo[]) {
484         { TYPE_PNV_XSCOM_INTERFACE },
485         { }
486     }
487 };
488 
489 static int pnv_chiptod_power10_dt_xscom(PnvXScomInterface *dev, void *fdt,
490                              int xscom_offset)
491 {
492     const char compat[] = "ibm,power-chiptod\0ibm,power10-chiptod";
493 
494     return pnv_chiptod_dt_xscom(dev, fdt, xscom_offset, compat, sizeof(compat));
495 }
496 
497 static void pnv_chiptod_power10_class_init(ObjectClass *klass, void *data)
498 {
499     PnvChipTODClass *pctc = PNV_CHIPTOD_CLASS(klass);
500     DeviceClass *dc = DEVICE_CLASS(klass);
501     PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass);
502 
503     dc->desc = "PowerNV ChipTOD Controller (POWER10)";
504     device_class_set_props(dc, pnv_chiptod_properties);
505 
506     xdc->dt_xscom = pnv_chiptod_power10_dt_xscom;
507 
508     pctc->broadcast_ttype = chiptod_power10_broadcast_ttype;
509     pctc->tx_ttype_target = chiptod_power10_tx_ttype_target;
510 
511     pctc->xscom_size = PNV_XSCOM_CHIPTOD_SIZE;
512 }
513 
514 static const TypeInfo pnv_chiptod_power10_type_info = {
515     .name          = TYPE_PNV10_CHIPTOD,
516     .parent        = TYPE_PNV_CHIPTOD,
517     .instance_size = sizeof(PnvChipTOD),
518     .class_init    = pnv_chiptod_power10_class_init,
519     .interfaces    = (InterfaceInfo[]) {
520         { TYPE_PNV_XSCOM_INTERFACE },
521         { }
522     }
523 };
524 
525 static void pnv_chiptod_reset(void *dev)
526 {
527     PnvChipTOD *chiptod = PNV_CHIPTOD(dev);
528 
529     chiptod->pss_mss_ctrl_reg = 0;
530     if (chiptod->primary) {
531         chiptod->pss_mss_ctrl_reg |= PPC_BIT(1); /* TOD is master */
532     }
533     /* Drawer is master (we do not simulate multi-drawer) */
534     chiptod->pss_mss_ctrl_reg |= PPC_BIT(2);
535 
536     chiptod->tod_error = 0;
537     chiptod->tod_state = tod_error;
538 }
539 
540 static void pnv_chiptod_realize(DeviceState *dev, Error **errp)
541 {
542     PnvChipTOD *chiptod = PNV_CHIPTOD(dev);
543     PnvChipTODClass *pctc = PNV_CHIPTOD_GET_CLASS(chiptod);
544 
545     /* XScom regions for ChipTOD registers */
546     pnv_xscom_region_init(&chiptod->xscom_regs, OBJECT(dev),
547                           &pnv_chiptod_xscom_ops, chiptod, "xscom-chiptod",
548                           pctc->xscom_size);
549 
550     qemu_register_reset(pnv_chiptod_reset, chiptod);
551 }
552 
553 static void pnv_chiptod_unrealize(DeviceState *dev)
554 {
555     PnvChipTOD *chiptod = PNV_CHIPTOD(dev);
556 
557     qemu_unregister_reset(pnv_chiptod_reset, chiptod);
558 }
559 
560 static void pnv_chiptod_class_init(ObjectClass *klass, void *data)
561 {
562     DeviceClass *dc = DEVICE_CLASS(klass);
563 
564     dc->realize = pnv_chiptod_realize;
565     dc->unrealize = pnv_chiptod_unrealize;
566     dc->desc = "PowerNV ChipTOD Controller";
567     dc->user_creatable = false;
568 }
569 
570 static const TypeInfo pnv_chiptod_type_info = {
571     .name          = TYPE_PNV_CHIPTOD,
572     .parent        = TYPE_DEVICE,
573     .instance_size = sizeof(PnvChipTOD),
574     .class_init    = pnv_chiptod_class_init,
575     .class_size    = sizeof(PnvChipTODClass),
576     .abstract      = true,
577 };
578 
579 static void pnv_chiptod_register_types(void)
580 {
581     type_register_static(&pnv_chiptod_type_info);
582     type_register_static(&pnv_chiptod_power9_type_info);
583     type_register_static(&pnv_chiptod_power10_type_info);
584 }
585 
586 type_init(pnv_chiptod_register_types);
587