1369e5cb0SEdgar E. Iglesias /* 2369e5cb0SEdgar E. Iglesias * QEMU model of the Clock-Reset-LPD (CRL). 3369e5cb0SEdgar E. Iglesias * 4369e5cb0SEdgar E. Iglesias * Copyright (c) 2022 Advanced Micro Devices, Inc. 5369e5cb0SEdgar E. Iglesias * SPDX-License-Identifier: GPL-2.0-or-later 6369e5cb0SEdgar E. Iglesias * 7369e5cb0SEdgar E. Iglesias * Written by Edgar E. Iglesias <edgar.iglesias@amd.com> 8369e5cb0SEdgar E. Iglesias */ 9369e5cb0SEdgar E. Iglesias 10369e5cb0SEdgar E. Iglesias #include "qemu/osdep.h" 11369e5cb0SEdgar E. Iglesias #include "qapi/error.h" 12369e5cb0SEdgar E. Iglesias #include "qemu/log.h" 13369e5cb0SEdgar E. Iglesias #include "qemu/bitops.h" 14369e5cb0SEdgar E. Iglesias #include "migration/vmstate.h" 15369e5cb0SEdgar E. Iglesias #include "hw/qdev-properties.h" 16369e5cb0SEdgar E. Iglesias #include "hw/sysbus.h" 17369e5cb0SEdgar E. Iglesias #include "hw/irq.h" 18369e5cb0SEdgar E. Iglesias #include "hw/register.h" 19369e5cb0SEdgar E. Iglesias #include "hw/resettable.h" 20369e5cb0SEdgar E. Iglesias 21369e5cb0SEdgar E. Iglesias #include "target/arm/arm-powerctl.h" 22*e2d8cf9bSPhilippe Mathieu-Daudé #include "target/arm/multiprocessing.h" 23369e5cb0SEdgar E. Iglesias #include "hw/misc/xlnx-versal-crl.h" 24369e5cb0SEdgar E. Iglesias 25369e5cb0SEdgar E. Iglesias #ifndef XLNX_VERSAL_CRL_ERR_DEBUG 26369e5cb0SEdgar E. Iglesias #define XLNX_VERSAL_CRL_ERR_DEBUG 0 27369e5cb0SEdgar E. Iglesias #endif 28369e5cb0SEdgar E. Iglesias 29369e5cb0SEdgar E. Iglesias static void crl_update_irq(XlnxVersalCRL *s) 30369e5cb0SEdgar E. Iglesias { 31369e5cb0SEdgar E. Iglesias bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK]; 32369e5cb0SEdgar E. Iglesias qemu_set_irq(s->irq, pending); 33369e5cb0SEdgar E. Iglesias } 34369e5cb0SEdgar E. Iglesias 35369e5cb0SEdgar E. Iglesias static void crl_status_postw(RegisterInfo *reg, uint64_t val64) 36369e5cb0SEdgar E. Iglesias { 37369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 38369e5cb0SEdgar E. Iglesias crl_update_irq(s); 39369e5cb0SEdgar E. Iglesias } 40369e5cb0SEdgar E. Iglesias 41369e5cb0SEdgar E. Iglesias static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64) 42369e5cb0SEdgar E. Iglesias { 43369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 44369e5cb0SEdgar E. Iglesias uint32_t val = val64; 45369e5cb0SEdgar E. Iglesias 46369e5cb0SEdgar E. Iglesias s->regs[R_IR_MASK] &= ~val; 47369e5cb0SEdgar E. Iglesias crl_update_irq(s); 48369e5cb0SEdgar E. Iglesias return 0; 49369e5cb0SEdgar E. Iglesias } 50369e5cb0SEdgar E. Iglesias 51369e5cb0SEdgar E. Iglesias static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64) 52369e5cb0SEdgar E. Iglesias { 53369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 54369e5cb0SEdgar E. Iglesias uint32_t val = val64; 55369e5cb0SEdgar E. Iglesias 56369e5cb0SEdgar E. Iglesias s->regs[R_IR_MASK] |= val; 57369e5cb0SEdgar E. Iglesias crl_update_irq(s); 58369e5cb0SEdgar E. Iglesias return 0; 59369e5cb0SEdgar E. Iglesias } 60369e5cb0SEdgar E. Iglesias 61369e5cb0SEdgar E. Iglesias static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev, 62369e5cb0SEdgar E. Iglesias bool rst_old, bool rst_new) 63369e5cb0SEdgar E. Iglesias { 64369e5cb0SEdgar E. Iglesias device_cold_reset(dev); 65369e5cb0SEdgar E. Iglesias } 66369e5cb0SEdgar E. Iglesias 67369e5cb0SEdgar E. Iglesias static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu, 68369e5cb0SEdgar E. Iglesias bool rst_old, bool rst_new) 69369e5cb0SEdgar E. Iglesias { 70369e5cb0SEdgar E. Iglesias if (rst_new) { 71c4380f7bSRichard Henderson arm_set_cpu_off(arm_cpu_mp_affinity(armcpu)); 72369e5cb0SEdgar E. Iglesias } else { 73c4380f7bSRichard Henderson arm_set_cpu_on_and_reset(arm_cpu_mp_affinity(armcpu)); 74369e5cb0SEdgar E. Iglesias } 75369e5cb0SEdgar E. Iglesias } 76369e5cb0SEdgar E. Iglesias 77369e5cb0SEdgar E. Iglesias #define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \ 78369e5cb0SEdgar E. Iglesias bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \ 79369e5cb0SEdgar E. Iglesias bool new_f = FIELD_EX32(new_val, reg, f); \ 80369e5cb0SEdgar E. Iglesias \ 81369e5cb0SEdgar E. Iglesias /* Detect edges. */ \ 82369e5cb0SEdgar E. Iglesias if (dev && old_f != new_f) { \ 83369e5cb0SEdgar E. Iglesias crl_reset_ ## type(s, dev, old_f, new_f); \ 84369e5cb0SEdgar E. Iglesias } \ 85369e5cb0SEdgar E. Iglesias } 86369e5cb0SEdgar E. Iglesias 87369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64) 88369e5cb0SEdgar E. Iglesias { 89369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 90369e5cb0SEdgar E. Iglesias 91369e5cb0SEdgar E. Iglesias REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]); 92369e5cb0SEdgar E. Iglesias REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]); 93369e5cb0SEdgar E. Iglesias return val64; 94369e5cb0SEdgar E. Iglesias } 95369e5cb0SEdgar E. Iglesias 96369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64) 97369e5cb0SEdgar E. Iglesias { 98369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 99369e5cb0SEdgar E. Iglesias int i; 100369e5cb0SEdgar E. Iglesias 101369e5cb0SEdgar E. Iglesias /* A single register fans out to all ADMA reset inputs. */ 102369e5cb0SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) { 103369e5cb0SEdgar E. Iglesias REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]); 104369e5cb0SEdgar E. Iglesias } 105369e5cb0SEdgar E. Iglesias return val64; 106369e5cb0SEdgar E. Iglesias } 107369e5cb0SEdgar E. Iglesias 108369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64) 109369e5cb0SEdgar E. Iglesias { 110369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 111369e5cb0SEdgar E. Iglesias 112369e5cb0SEdgar E. Iglesias REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]); 113369e5cb0SEdgar E. Iglesias return val64; 114369e5cb0SEdgar E. Iglesias } 115369e5cb0SEdgar E. Iglesias 116369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64) 117369e5cb0SEdgar E. Iglesias { 118369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 119369e5cb0SEdgar E. Iglesias 120369e5cb0SEdgar E. Iglesias REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]); 121369e5cb0SEdgar E. Iglesias return val64; 122369e5cb0SEdgar E. Iglesias } 123369e5cb0SEdgar E. Iglesias 124369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64) 125369e5cb0SEdgar E. Iglesias { 126369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 127369e5cb0SEdgar E. Iglesias 128369e5cb0SEdgar E. Iglesias REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]); 129369e5cb0SEdgar E. Iglesias return val64; 130369e5cb0SEdgar E. Iglesias } 131369e5cb0SEdgar E. Iglesias 132369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64) 133369e5cb0SEdgar E. Iglesias { 134369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 135369e5cb0SEdgar E. Iglesias 136369e5cb0SEdgar E. Iglesias REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]); 137369e5cb0SEdgar E. Iglesias return val64; 138369e5cb0SEdgar E. Iglesias } 139369e5cb0SEdgar E. Iglesias 140369e5cb0SEdgar E. Iglesias static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64) 141369e5cb0SEdgar E. Iglesias { 142369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); 143369e5cb0SEdgar E. Iglesias 144369e5cb0SEdgar E. Iglesias REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb); 145369e5cb0SEdgar E. Iglesias return val64; 146369e5cb0SEdgar E. Iglesias } 147369e5cb0SEdgar E. Iglesias 148369e5cb0SEdgar E. Iglesias static const RegisterAccessInfo crl_regs_info[] = { 149369e5cb0SEdgar E. Iglesias { .name = "ERR_CTRL", .addr = A_ERR_CTRL, 150369e5cb0SEdgar E. Iglesias },{ .name = "IR_STATUS", .addr = A_IR_STATUS, 151369e5cb0SEdgar E. Iglesias .w1c = 0x1, 152369e5cb0SEdgar E. Iglesias .post_write = crl_status_postw, 153369e5cb0SEdgar E. Iglesias },{ .name = "IR_MASK", .addr = A_IR_MASK, 154369e5cb0SEdgar E. Iglesias .reset = 0x1, 155369e5cb0SEdgar E. Iglesias .ro = 0x1, 156369e5cb0SEdgar E. Iglesias },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE, 157369e5cb0SEdgar E. Iglesias .pre_write = crl_enable_prew, 158369e5cb0SEdgar E. Iglesias },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE, 159369e5cb0SEdgar E. Iglesias .pre_write = crl_disable_prew, 160369e5cb0SEdgar E. Iglesias },{ .name = "WPROT", .addr = A_WPROT, 161369e5cb0SEdgar E. Iglesias },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN, 162369e5cb0SEdgar E. Iglesias .reset = 0x1, 163369e5cb0SEdgar E. Iglesias .rsvd = 0xe, 164369e5cb0SEdgar E. Iglesias },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL, 165369e5cb0SEdgar E. Iglesias .reset = 0x24809, 166369e5cb0SEdgar E. Iglesias .rsvd = 0xf88c00f6, 167369e5cb0SEdgar E. Iglesias },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG, 168369e5cb0SEdgar E. Iglesias .reset = 0x2000000, 169369e5cb0SEdgar E. Iglesias .rsvd = 0x1801210, 170369e5cb0SEdgar E. Iglesias },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG, 171369e5cb0SEdgar E. Iglesias .rsvd = 0x7e330000, 172369e5cb0SEdgar E. Iglesias },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS, 173369e5cb0SEdgar E. Iglesias .reset = R_PLL_STATUS_RPLL_STABLE_MASK | 174369e5cb0SEdgar E. Iglesias R_PLL_STATUS_RPLL_LOCK_MASK, 175369e5cb0SEdgar E. Iglesias .rsvd = 0xfa, 176369e5cb0SEdgar E. Iglesias .ro = 0x5, 177369e5cb0SEdgar E. Iglesias },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL, 178369e5cb0SEdgar E. Iglesias .reset = 0x2000100, 179369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00ff, 180369e5cb0SEdgar E. Iglesias },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL, 181369e5cb0SEdgar E. Iglesias .reset = 0x6000300, 182369e5cb0SEdgar E. Iglesias .rsvd = 0xf9fc00f8, 183369e5cb0SEdgar E. Iglesias },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL, 184369e5cb0SEdgar E. Iglesias .reset = 0x2000800, 185369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 186369e5cb0SEdgar E. Iglesias },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL, 187369e5cb0SEdgar E. Iglesias .reset = 0xe000300, 188369e5cb0SEdgar E. Iglesias .rsvd = 0xe1fc00f8, 189369e5cb0SEdgar E. Iglesias },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL, 190369e5cb0SEdgar E. Iglesias .reset = 0x2000500, 191369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 192369e5cb0SEdgar E. Iglesias },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL, 193369e5cb0SEdgar E. Iglesias .reset = 0xe000a00, 194369e5cb0SEdgar E. Iglesias .rsvd = 0xf1fc00f8, 195369e5cb0SEdgar E. Iglesias },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL, 196369e5cb0SEdgar E. Iglesias .reset = 0xe000a00, 197369e5cb0SEdgar E. Iglesias .rsvd = 0xf1fc00f8, 198369e5cb0SEdgar E. Iglesias },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL, 199369e5cb0SEdgar E. Iglesias .reset = 0x300, 200369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 201369e5cb0SEdgar E. Iglesias },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL, 202369e5cb0SEdgar E. Iglesias .reset = 0x2001900, 203369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 204369e5cb0SEdgar E. Iglesias },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL, 205369e5cb0SEdgar E. Iglesias .reset = 0xc00, 206369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 207369e5cb0SEdgar E. Iglesias },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL, 208369e5cb0SEdgar E. Iglesias .reset = 0xc00, 209369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 210369e5cb0SEdgar E. Iglesias },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL, 211369e5cb0SEdgar E. Iglesias .reset = 0x600, 212369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 213369e5cb0SEdgar E. Iglesias },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL, 214369e5cb0SEdgar E. Iglesias .reset = 0x600, 215369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 216369e5cb0SEdgar E. Iglesias },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL, 217369e5cb0SEdgar E. Iglesias .reset = 0xc00, 218369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 219369e5cb0SEdgar E. Iglesias },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL, 220369e5cb0SEdgar E. Iglesias .reset = 0xc00, 221369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 222369e5cb0SEdgar E. Iglesias },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL, 223369e5cb0SEdgar E. Iglesias .reset = 0xc00, 224369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 225369e5cb0SEdgar E. Iglesias },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL, 226369e5cb0SEdgar E. Iglesias .reset = 0xc00, 227369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 228369e5cb0SEdgar E. Iglesias },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL, 229369e5cb0SEdgar E. Iglesias .reset = 0x300, 230369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 231369e5cb0SEdgar E. Iglesias },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL, 232369e5cb0SEdgar E. Iglesias .reset = 0x2000c00, 233369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 234369e5cb0SEdgar E. Iglesias },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK, 235369e5cb0SEdgar E. Iglesias },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL, 236369e5cb0SEdgar E. Iglesias .reset = 0xf04, 237369e5cb0SEdgar E. Iglesias .rsvd = 0xfffc00f8, 238369e5cb0SEdgar E. Iglesias },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL, 239369e5cb0SEdgar E. Iglesias .reset = 0x300, 240369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 241369e5cb0SEdgar E. Iglesias },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL, 242369e5cb0SEdgar E. Iglesias .reset = 0x300, 243369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 244369e5cb0SEdgar E. Iglesias },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL, 245369e5cb0SEdgar E. Iglesias .reset = 0x3c00, 246369e5cb0SEdgar E. Iglesias .rsvd = 0xfdfc00f8, 247369e5cb0SEdgar E. Iglesias },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5, 248369e5cb0SEdgar E. Iglesias .reset = 0x17, 249369e5cb0SEdgar E. Iglesias .rsvd = 0x8, 250369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_r5_prew, 251369e5cb0SEdgar E. Iglesias },{ .name = "RST_ADMA", .addr = A_RST_ADMA, 252369e5cb0SEdgar E. Iglesias .reset = 0x1, 253369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_adma_prew, 254369e5cb0SEdgar E. Iglesias },{ .name = "RST_GEM0", .addr = A_RST_GEM0, 255369e5cb0SEdgar E. Iglesias .reset = 0x1, 256369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_gem0_prew, 257369e5cb0SEdgar E. Iglesias },{ .name = "RST_GEM1", .addr = A_RST_GEM1, 258369e5cb0SEdgar E. Iglesias .reset = 0x1, 259369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_gem1_prew, 260369e5cb0SEdgar E. Iglesias },{ .name = "RST_SPARE", .addr = A_RST_SPARE, 261369e5cb0SEdgar E. Iglesias .reset = 0x1, 262369e5cb0SEdgar E. Iglesias },{ .name = "RST_USB0", .addr = A_RST_USB0, 263369e5cb0SEdgar E. Iglesias .reset = 0x1, 264369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_usb_prew, 265369e5cb0SEdgar E. Iglesias },{ .name = "RST_UART0", .addr = A_RST_UART0, 266369e5cb0SEdgar E. Iglesias .reset = 0x1, 267369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_uart0_prew, 268369e5cb0SEdgar E. Iglesias },{ .name = "RST_UART1", .addr = A_RST_UART1, 269369e5cb0SEdgar E. Iglesias .reset = 0x1, 270369e5cb0SEdgar E. Iglesias .pre_write = crl_rst_uart1_prew, 271369e5cb0SEdgar E. Iglesias },{ .name = "RST_SPI0", .addr = A_RST_SPI0, 272369e5cb0SEdgar E. Iglesias .reset = 0x1, 273369e5cb0SEdgar E. Iglesias },{ .name = "RST_SPI1", .addr = A_RST_SPI1, 274369e5cb0SEdgar E. Iglesias .reset = 0x1, 275369e5cb0SEdgar E. Iglesias },{ .name = "RST_CAN0", .addr = A_RST_CAN0, 276369e5cb0SEdgar E. Iglesias .reset = 0x1, 277369e5cb0SEdgar E. Iglesias },{ .name = "RST_CAN1", .addr = A_RST_CAN1, 278369e5cb0SEdgar E. Iglesias .reset = 0x1, 279369e5cb0SEdgar E. Iglesias },{ .name = "RST_I2C0", .addr = A_RST_I2C0, 280369e5cb0SEdgar E. Iglesias .reset = 0x1, 281369e5cb0SEdgar E. Iglesias },{ .name = "RST_I2C1", .addr = A_RST_I2C1, 282369e5cb0SEdgar E. Iglesias .reset = 0x1, 283369e5cb0SEdgar E. Iglesias },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD, 284369e5cb0SEdgar E. Iglesias .reset = 0x33, 285369e5cb0SEdgar E. Iglesias .rsvd = 0xcc, 286369e5cb0SEdgar E. Iglesias },{ .name = "RST_GPIO", .addr = A_RST_GPIO, 287369e5cb0SEdgar E. Iglesias .reset = 0x1, 288369e5cb0SEdgar E. Iglesias },{ .name = "RST_TTC", .addr = A_RST_TTC, 289369e5cb0SEdgar E. Iglesias .reset = 0xf, 290369e5cb0SEdgar E. Iglesias },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP, 291369e5cb0SEdgar E. Iglesias .reset = 0x1, 292369e5cb0SEdgar E. Iglesias },{ .name = "RST_SWDT", .addr = A_RST_SWDT, 293369e5cb0SEdgar E. Iglesias .reset = 0x1, 294369e5cb0SEdgar E. Iglesias },{ .name = "RST_OCM", .addr = A_RST_OCM, 295369e5cb0SEdgar E. Iglesias },{ .name = "RST_IPI", .addr = A_RST_IPI, 296369e5cb0SEdgar E. Iglesias },{ .name = "RST_FPD", .addr = A_RST_FPD, 297369e5cb0SEdgar E. Iglesias .reset = 0x3, 298369e5cb0SEdgar E. Iglesias },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE, 299369e5cb0SEdgar E. Iglesias .reset = 0x1, 300369e5cb0SEdgar E. Iglesias .rsvd = 0xf8, 301369e5cb0SEdgar E. Iglesias } 302369e5cb0SEdgar E. Iglesias }; 303369e5cb0SEdgar E. Iglesias 304369e5cb0SEdgar E. Iglesias static void crl_reset_enter(Object *obj, ResetType type) 305369e5cb0SEdgar E. Iglesias { 306369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); 307369e5cb0SEdgar E. Iglesias unsigned int i; 308369e5cb0SEdgar E. Iglesias 309369e5cb0SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { 310369e5cb0SEdgar E. Iglesias register_reset(&s->regs_info[i]); 311369e5cb0SEdgar E. Iglesias } 312369e5cb0SEdgar E. Iglesias } 313369e5cb0SEdgar E. Iglesias 314369e5cb0SEdgar E. Iglesias static void crl_reset_hold(Object *obj) 315369e5cb0SEdgar E. Iglesias { 316369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); 317369e5cb0SEdgar E. Iglesias 318369e5cb0SEdgar E. Iglesias crl_update_irq(s); 319369e5cb0SEdgar E. Iglesias } 320369e5cb0SEdgar E. Iglesias 321369e5cb0SEdgar E. Iglesias static const MemoryRegionOps crl_ops = { 322369e5cb0SEdgar E. Iglesias .read = register_read_memory, 323369e5cb0SEdgar E. Iglesias .write = register_write_memory, 324369e5cb0SEdgar E. Iglesias .endianness = DEVICE_LITTLE_ENDIAN, 325369e5cb0SEdgar E. Iglesias .valid = { 326369e5cb0SEdgar E. Iglesias .min_access_size = 4, 327369e5cb0SEdgar E. Iglesias .max_access_size = 4, 328369e5cb0SEdgar E. Iglesias }, 329369e5cb0SEdgar E. Iglesias }; 330369e5cb0SEdgar E. Iglesias 331369e5cb0SEdgar E. Iglesias static void crl_init(Object *obj) 332369e5cb0SEdgar E. Iglesias { 333369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); 334369e5cb0SEdgar E. Iglesias SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 335369e5cb0SEdgar E. Iglesias int i; 336369e5cb0SEdgar E. Iglesias 337369e5cb0SEdgar E. Iglesias s->reg_array = 338369e5cb0SEdgar E. Iglesias register_init_block32(DEVICE(obj), crl_regs_info, 339369e5cb0SEdgar E. Iglesias ARRAY_SIZE(crl_regs_info), 340369e5cb0SEdgar E. Iglesias s->regs_info, s->regs, 341369e5cb0SEdgar E. Iglesias &crl_ops, 342369e5cb0SEdgar E. Iglesias XLNX_VERSAL_CRL_ERR_DEBUG, 343369e5cb0SEdgar E. Iglesias CRL_R_MAX * 4); 344369e5cb0SEdgar E. Iglesias sysbus_init_mmio(sbd, &s->reg_array->mem); 345369e5cb0SEdgar E. Iglesias sysbus_init_irq(sbd, &s->irq); 346369e5cb0SEdgar E. Iglesias 347369e5cb0SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) { 348369e5cb0SEdgar E. Iglesias object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU, 349369e5cb0SEdgar E. Iglesias (Object **)&s->cfg.cpu_r5[i], 350369e5cb0SEdgar E. Iglesias qdev_prop_allow_set_link_before_realize, 351369e5cb0SEdgar E. Iglesias OBJ_PROP_LINK_STRONG); 352369e5cb0SEdgar E. Iglesias } 353369e5cb0SEdgar E. Iglesias 354369e5cb0SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) { 355369e5cb0SEdgar E. Iglesias object_property_add_link(obj, "adma[*]", TYPE_DEVICE, 356369e5cb0SEdgar E. Iglesias (Object **)&s->cfg.adma[i], 357369e5cb0SEdgar E. Iglesias qdev_prop_allow_set_link_before_realize, 358369e5cb0SEdgar E. Iglesias OBJ_PROP_LINK_STRONG); 359369e5cb0SEdgar E. Iglesias } 360369e5cb0SEdgar E. Iglesias 361369e5cb0SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) { 362369e5cb0SEdgar E. Iglesias object_property_add_link(obj, "uart[*]", TYPE_DEVICE, 363369e5cb0SEdgar E. Iglesias (Object **)&s->cfg.uart[i], 364369e5cb0SEdgar E. Iglesias qdev_prop_allow_set_link_before_realize, 365369e5cb0SEdgar E. Iglesias OBJ_PROP_LINK_STRONG); 366369e5cb0SEdgar E. Iglesias } 367369e5cb0SEdgar E. Iglesias 368369e5cb0SEdgar E. Iglesias for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) { 369369e5cb0SEdgar E. Iglesias object_property_add_link(obj, "gem[*]", TYPE_DEVICE, 370369e5cb0SEdgar E. Iglesias (Object **)&s->cfg.gem[i], 371369e5cb0SEdgar E. Iglesias qdev_prop_allow_set_link_before_realize, 372369e5cb0SEdgar E. Iglesias OBJ_PROP_LINK_STRONG); 373369e5cb0SEdgar E. Iglesias } 374369e5cb0SEdgar E. Iglesias 375369e5cb0SEdgar E. Iglesias object_property_add_link(obj, "usb", TYPE_DEVICE, 376369e5cb0SEdgar E. Iglesias (Object **)&s->cfg.gem[i], 377369e5cb0SEdgar E. Iglesias qdev_prop_allow_set_link_before_realize, 378369e5cb0SEdgar E. Iglesias OBJ_PROP_LINK_STRONG); 379369e5cb0SEdgar E. Iglesias } 380369e5cb0SEdgar E. Iglesias 381369e5cb0SEdgar E. Iglesias static void crl_finalize(Object *obj) 382369e5cb0SEdgar E. Iglesias { 383369e5cb0SEdgar E. Iglesias XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); 384369e5cb0SEdgar E. Iglesias register_finalize_block(s->reg_array); 385369e5cb0SEdgar E. Iglesias } 386369e5cb0SEdgar E. Iglesias 387369e5cb0SEdgar E. Iglesias static const VMStateDescription vmstate_crl = { 388369e5cb0SEdgar E. Iglesias .name = TYPE_XLNX_VERSAL_CRL, 389369e5cb0SEdgar E. Iglesias .version_id = 1, 390369e5cb0SEdgar E. Iglesias .minimum_version_id = 1, 391e4ea952fSRichard Henderson .fields = (const VMStateField[]) { 392369e5cb0SEdgar E. Iglesias VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX), 393369e5cb0SEdgar E. Iglesias VMSTATE_END_OF_LIST(), 394369e5cb0SEdgar E. Iglesias } 395369e5cb0SEdgar E. Iglesias }; 396369e5cb0SEdgar E. Iglesias 397369e5cb0SEdgar E. Iglesias static void crl_class_init(ObjectClass *klass, void *data) 398369e5cb0SEdgar E. Iglesias { 399369e5cb0SEdgar E. Iglesias ResettableClass *rc = RESETTABLE_CLASS(klass); 400369e5cb0SEdgar E. Iglesias DeviceClass *dc = DEVICE_CLASS(klass); 401369e5cb0SEdgar E. Iglesias 402369e5cb0SEdgar E. Iglesias dc->vmsd = &vmstate_crl; 403369e5cb0SEdgar E. Iglesias 404369e5cb0SEdgar E. Iglesias rc->phases.enter = crl_reset_enter; 405369e5cb0SEdgar E. Iglesias rc->phases.hold = crl_reset_hold; 406369e5cb0SEdgar E. Iglesias } 407369e5cb0SEdgar E. Iglesias 408369e5cb0SEdgar E. Iglesias static const TypeInfo crl_info = { 409369e5cb0SEdgar E. Iglesias .name = TYPE_XLNX_VERSAL_CRL, 410369e5cb0SEdgar E. Iglesias .parent = TYPE_SYS_BUS_DEVICE, 411369e5cb0SEdgar E. Iglesias .instance_size = sizeof(XlnxVersalCRL), 412369e5cb0SEdgar E. Iglesias .class_init = crl_class_init, 413369e5cb0SEdgar E. Iglesias .instance_init = crl_init, 414369e5cb0SEdgar E. Iglesias .instance_finalize = crl_finalize, 415369e5cb0SEdgar E. Iglesias }; 416369e5cb0SEdgar E. Iglesias 417369e5cb0SEdgar E. Iglesias static void crl_register_types(void) 418369e5cb0SEdgar E. Iglesias { 419369e5cb0SEdgar E. Iglesias type_register_static(&crl_info); 420369e5cb0SEdgar E. Iglesias } 421369e5cb0SEdgar E. Iglesias 422369e5cb0SEdgar E. Iglesias type_init(crl_register_types) 423