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