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 PnvCore *pc = chiptod->slave_pc_target; 368 369 /* 370 * Moving TOD to TB will set the TB of all threads in a 371 * core, so skiboot only does this once per thread0, so 372 * that is where we keep the timebase state machine. 373 * 374 * It is likely possible for TBST to be driven from other 375 * threads in the core, but for now we only implement it for 376 * thread 0. 377 */ 378 379 if (pc->tod_state.tb_ready_for_tod) { 380 pc->tod_state.tod_sent_to_tb = 1; 381 } else { 382 qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: xscom write reg" 383 " TOD_MOVE_TOD_TO_TB_REG with TB not ready to" 384 " receive TOD\n"); 385 } 386 } 387 break; 388 case TOD_START_TOD_REG: 389 if (chiptod->tod_state != tod_stopped) { 390 qemu_log_mask(LOG_GUEST_ERROR, "pnv_chiptod: LOAD_TOG_REG in " 391 " state %d, should be in 1 (TOD_STOPPED)\n", 392 chiptod->tod_state); 393 } else { 394 chiptod->tod_state = tod_running; 395 } 396 break; 397 case TOD_TX_TTYPE_4_REG: 398 case TOD_TX_TTYPE_5_REG: 399 pctc->broadcast_ttype(chiptod, offset); 400 break; 401 default: 402 qemu_log_mask(LOG_UNIMP, "pnv_chiptod: unimplemented register: Ox%" 403 HWADDR_PRIx "\n", addr >> 3); 404 } 405 } 406 407 static const MemoryRegionOps pnv_chiptod_xscom_ops = { 408 .read = pnv_chiptod_xscom_read, 409 .write = pnv_chiptod_xscom_write, 410 .valid.min_access_size = 8, 411 .valid.max_access_size = 8, 412 .impl.min_access_size = 8, 413 .impl.max_access_size = 8, 414 .endianness = DEVICE_BIG_ENDIAN, 415 }; 416 417 static int pnv_chiptod_dt_xscom(PnvXScomInterface *dev, void *fdt, 418 int xscom_offset, 419 const char compat[], size_t compat_size) 420 { 421 PnvChipTOD *chiptod = PNV_CHIPTOD(dev); 422 g_autofree char *name = NULL; 423 int offset; 424 uint32_t chiptod_pcba = PNV9_XSCOM_CHIPTOD_BASE; 425 uint32_t reg[] = { 426 cpu_to_be32(chiptod_pcba), 427 cpu_to_be32(PNV9_XSCOM_CHIPTOD_SIZE) 428 }; 429 430 name = g_strdup_printf("chiptod@%x", chiptod_pcba); 431 offset = fdt_add_subnode(fdt, xscom_offset, name); 432 _FDT(offset); 433 434 if (chiptod->primary) { 435 _FDT((fdt_setprop(fdt, offset, "primary", NULL, 0))); 436 } else if (chiptod->secondary) { 437 _FDT((fdt_setprop(fdt, offset, "secondary", NULL, 0))); 438 } 439 440 _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)))); 441 _FDT((fdt_setprop(fdt, offset, "compatible", compat, compat_size))); 442 return 0; 443 } 444 445 static int pnv_chiptod_power9_dt_xscom(PnvXScomInterface *dev, void *fdt, 446 int xscom_offset) 447 { 448 const char compat[] = "ibm,power-chiptod\0ibm,power9-chiptod"; 449 450 return pnv_chiptod_dt_xscom(dev, fdt, xscom_offset, compat, sizeof(compat)); 451 } 452 453 static Property pnv_chiptod_properties[] = { 454 DEFINE_PROP_BOOL("primary", PnvChipTOD, primary, false), 455 DEFINE_PROP_BOOL("secondary", PnvChipTOD, secondary, false), 456 DEFINE_PROP_LINK("chip", PnvChipTOD , chip, TYPE_PNV_CHIP, PnvChip *), 457 DEFINE_PROP_END_OF_LIST(), 458 }; 459 460 static void pnv_chiptod_power9_class_init(ObjectClass *klass, void *data) 461 { 462 PnvChipTODClass *pctc = PNV_CHIPTOD_CLASS(klass); 463 DeviceClass *dc = DEVICE_CLASS(klass); 464 PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 465 466 dc->desc = "PowerNV ChipTOD Controller (POWER9)"; 467 device_class_set_props(dc, pnv_chiptod_properties); 468 469 xdc->dt_xscom = pnv_chiptod_power9_dt_xscom; 470 471 pctc->broadcast_ttype = chiptod_power9_broadcast_ttype; 472 pctc->tx_ttype_target = chiptod_power9_tx_ttype_target; 473 474 pctc->xscom_size = PNV_XSCOM_CHIPTOD_SIZE; 475 } 476 477 static const TypeInfo pnv_chiptod_power9_type_info = { 478 .name = TYPE_PNV9_CHIPTOD, 479 .parent = TYPE_PNV_CHIPTOD, 480 .instance_size = sizeof(PnvChipTOD), 481 .class_init = pnv_chiptod_power9_class_init, 482 .interfaces = (InterfaceInfo[]) { 483 { TYPE_PNV_XSCOM_INTERFACE }, 484 { } 485 } 486 }; 487 488 static int pnv_chiptod_power10_dt_xscom(PnvXScomInterface *dev, void *fdt, 489 int xscom_offset) 490 { 491 const char compat[] = "ibm,power-chiptod\0ibm,power10-chiptod"; 492 493 return pnv_chiptod_dt_xscom(dev, fdt, xscom_offset, compat, sizeof(compat)); 494 } 495 496 static void pnv_chiptod_power10_class_init(ObjectClass *klass, void *data) 497 { 498 PnvChipTODClass *pctc = PNV_CHIPTOD_CLASS(klass); 499 DeviceClass *dc = DEVICE_CLASS(klass); 500 PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 501 502 dc->desc = "PowerNV ChipTOD Controller (POWER10)"; 503 device_class_set_props(dc, pnv_chiptod_properties); 504 505 xdc->dt_xscom = pnv_chiptod_power10_dt_xscom; 506 507 pctc->broadcast_ttype = chiptod_power10_broadcast_ttype; 508 pctc->tx_ttype_target = chiptod_power10_tx_ttype_target; 509 510 pctc->xscom_size = PNV_XSCOM_CHIPTOD_SIZE; 511 } 512 513 static const TypeInfo pnv_chiptod_power10_type_info = { 514 .name = TYPE_PNV10_CHIPTOD, 515 .parent = TYPE_PNV_CHIPTOD, 516 .instance_size = sizeof(PnvChipTOD), 517 .class_init = pnv_chiptod_power10_class_init, 518 .interfaces = (InterfaceInfo[]) { 519 { TYPE_PNV_XSCOM_INTERFACE }, 520 { } 521 } 522 }; 523 524 static void pnv_chiptod_reset(void *dev) 525 { 526 PnvChipTOD *chiptod = PNV_CHIPTOD(dev); 527 528 chiptod->pss_mss_ctrl_reg = 0; 529 if (chiptod->primary) { 530 chiptod->pss_mss_ctrl_reg |= PPC_BIT(1); /* TOD is master */ 531 } 532 /* Drawer is master (we do not simulate multi-drawer) */ 533 chiptod->pss_mss_ctrl_reg |= PPC_BIT(2); 534 535 chiptod->tod_error = 0; 536 chiptod->tod_state = tod_error; 537 } 538 539 static void pnv_chiptod_realize(DeviceState *dev, Error **errp) 540 { 541 PnvChipTOD *chiptod = PNV_CHIPTOD(dev); 542 PnvChipTODClass *pctc = PNV_CHIPTOD_GET_CLASS(chiptod); 543 544 /* XScom regions for ChipTOD registers */ 545 pnv_xscom_region_init(&chiptod->xscom_regs, OBJECT(dev), 546 &pnv_chiptod_xscom_ops, chiptod, "xscom-chiptod", 547 pctc->xscom_size); 548 549 qemu_register_reset(pnv_chiptod_reset, chiptod); 550 } 551 552 static void pnv_chiptod_unrealize(DeviceState *dev) 553 { 554 PnvChipTOD *chiptod = PNV_CHIPTOD(dev); 555 556 qemu_unregister_reset(pnv_chiptod_reset, chiptod); 557 } 558 559 static void pnv_chiptod_class_init(ObjectClass *klass, void *data) 560 { 561 DeviceClass *dc = DEVICE_CLASS(klass); 562 563 dc->realize = pnv_chiptod_realize; 564 dc->unrealize = pnv_chiptod_unrealize; 565 dc->desc = "PowerNV ChipTOD Controller"; 566 dc->user_creatable = false; 567 } 568 569 static const TypeInfo pnv_chiptod_type_info = { 570 .name = TYPE_PNV_CHIPTOD, 571 .parent = TYPE_DEVICE, 572 .instance_size = sizeof(PnvChipTOD), 573 .class_init = pnv_chiptod_class_init, 574 .class_size = sizeof(PnvChipTODClass), 575 .abstract = true, 576 }; 577 578 static void pnv_chiptod_register_types(void) 579 { 580 type_register_static(&pnv_chiptod_type_info); 581 type_register_static(&pnv_chiptod_power9_type_info); 582 type_register_static(&pnv_chiptod_power10_type_info); 583 } 584 585 type_init(pnv_chiptod_register_types); 586