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