qemu/hw/misc/xlnx-versal-rpu.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the RPU Realtime Processing Unit
   3 *
   4 * Copyright (c) 2019 Xilinx Inc.
   5 *
   6 * Autogenerated by xregqemu.py 2019-02-15.
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a copy
   9 * of this software and associated documentation files (the "Software"), to deal
  10 * in the Software without restriction, including without limitation the rights
  11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 * copies of the Software, and to permit persons to whom the Software is
  13 * furnished to do so, subject to the following conditions:
  14 *
  15 * The above copyright notice and this permission notice shall be included in
  16 * all copies or substantial portions of the Software.
  17 *
  18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24 * THE SOFTWARE.
  25 */
  26
  27#include "qemu/osdep.h"
  28#include "hw/sysbus.h"
  29#include "hw/register.h"
  30#include "qemu/bitops.h"
  31#include "qemu/log.h"
  32#include "qapi/error.h"
  33#include "migration/vmstate.h"
  34#include "hw/qdev-properties.h"
  35
  36#include "hw/fdt_generic_util.h"
  37
  38#ifndef XILINX_VERSAL_RPU_ERR_DEBUG
  39#define XILINX_VERSAL_RPU_ERR_DEBUG 0
  40#endif
  41
  42#define TYPE_XILINX_VERSAL_RPU "xlnx.versal-rpu"
  43
  44#define XILINX_VERSAL_RPU(obj) \
  45     OBJECT_CHECK(RPU, (obj), TYPE_XILINX_VERSAL_RPU)
  46
  47#define DPRINTF(...) do { \
  48        if (XILINX_VERSAL_RPU_ERR_DEBUG) { \
  49            qemu_log("%s: ", __func__); \
  50            qemu_log(__VA_ARGS__); \
  51        } \
  52    } while (0)
  53
  54REG32(RPU_GLBL_CNTL, 0x0)
  55    FIELD(RPU_GLBL_CNTL, GIC_AXPROT, 10, 1)
  56    FIELD(RPU_GLBL_CNTL, TCM_CLK_CNTL, 8, 1)
  57    FIELD(RPU_GLBL_CNTL, TCM_WAIT, 7, 1)
  58    FIELD(RPU_GLBL_CNTL, TCM_COMB, 6, 1)
  59    FIELD(RPU_GLBL_CNTL, TEINIT, 5, 1)
  60    FIELD(RPU_GLBL_CNTL, SLCLAMP, 4, 1)
  61    FIELD(RPU_GLBL_CNTL, SLSPLIT, 3, 1)
  62    FIELD(RPU_GLBL_CNTL, DBGNOCLKSTOP, 2, 1)
  63    FIELD(RPU_GLBL_CNTL, CFGIE, 1, 1)
  64    FIELD(RPU_GLBL_CNTL, CFGEE, 0, 1)
  65REG32(RPU_GLBL_STATUS, 0x4)
  66    FIELD(RPU_GLBL_STATUS, DBGNOPWRDWN, 0, 1)
  67REG32(RPU_ERR_CNTL, 0x8)
  68    FIELD(RPU_ERR_CNTL, APB_ERR_RES, 0, 1)
  69REG32(RPU_ERR_INJ, 0x20)
  70    FIELD(RPU_ERR_INJ, DCCMINP2, 8, 8)
  71    FIELD(RPU_ERR_INJ, DCCMINP, 0, 8)
  72REG32(RPU_CCF_MASK, 0x24)
  73    FIELD(RPU_CCF_MASK, TEST_MBIST_MODE, 7, 1)
  74    FIELD(RPU_CCF_MASK, TEST_SCAN_MODE_LP, 6, 1)
  75    FIELD(RPU_CCF_MASK, TEST_SCAN_MODE, 5, 1)
  76    FIELD(RPU_CCF_MASK, ISO, 4, 1)
  77    FIELD(RPU_CCF_MASK, PGE, 3, 1)
  78    FIELD(RPU_CCF_MASK, R50_DBG_RST, 2, 1)
  79    FIELD(RPU_CCF_MASK, R50_RST, 1, 1)
  80    FIELD(RPU_CCF_MASK, PGE_RST, 0, 1)
  81REG32(RPU_INTR_0, 0x28)
  82REG32(RPU_INTR_1, 0x2c)
  83REG32(RPU_INTR_2, 0x30)
  84REG32(RPU_INTR_3, 0x34)
  85REG32(RPU_INTR_4, 0x38)
  86REG32(RPU_INTR_MASK_0, 0x40)
  87REG32(RPU_INTR_MASK_1, 0x44)
  88REG32(RPU_INTR_MASK_2, 0x48)
  89REG32(RPU_INTR_MASK_3, 0x4c)
  90REG32(RPU_INTR_MASK_4, 0x50)
  91REG32(RPU_CCF_VAL, 0x54)
  92    FIELD(RPU_CCF_VAL, TEST_MBIST_MODE, 7, 1)
  93    FIELD(RPU_CCF_VAL, TEST_SCAN_MODE_LP, 6, 1)
  94    FIELD(RPU_CCF_VAL, TEST_SCAN_MODE, 5, 1)
  95    FIELD(RPU_CCF_VAL, ISO, 4, 1)
  96    FIELD(RPU_CCF_VAL, PGE, 3, 1)
  97    FIELD(RPU_CCF_VAL, R50_DBG_RST, 2, 1)
  98    FIELD(RPU_CCF_VAL, R50_RST, 1, 1)
  99    FIELD(RPU_CCF_VAL, PGE_RST, 0, 1)
 100REG32(RPU_SAFETY_CHK, 0xf0)
 101REG32(RPU_0_CFG, 0x100)
 102    FIELD(RPU_0_CFG, CFGNMFI0, 3, 1)
 103    FIELD(RPU_0_CFG, VINITHI, 2, 1)
 104    FIELD(RPU_0_CFG, COHERENT, 1, 1)
 105    FIELD(RPU_0_CFG, NCPUHALT, 0, 1)
 106REG32(RPU_0_STATUS, 0x104)
 107    FIELD(RPU_0_STATUS, NVALRESET, 5, 1)
 108    FIELD(RPU_0_STATUS, NVALIRQ, 4, 1)
 109    FIELD(RPU_0_STATUS, NVALFIQ, 3, 1)
 110    FIELD(RPU_0_STATUS, NWFIPIPESTOPPED, 2, 1)
 111    FIELD(RPU_0_STATUS, NWFEPIPESTOPPED, 1, 1)
 112    FIELD(RPU_0_STATUS, NCLKSTOPPED, 0, 1)
 113REG32(RPU_0_PWRDWN, 0x108)
 114    FIELD(RPU_0_PWRDWN, EN, 0, 1)
 115REG32(RPU_0_ISR, 0x114)
 116    FIELD(RPU_0_ISR, FPUFC, 24, 1)
 117    FIELD(RPU_0_ISR, FPOFC, 23, 1)
 118    FIELD(RPU_0_ISR, FPIXC, 22, 1)
 119    FIELD(RPU_0_ISR, FPIOC, 21, 1)
 120    FIELD(RPU_0_ISR, FPIDC, 20, 1)
 121    FIELD(RPU_0_ISR, FPDZC, 19, 1)
 122    FIELD(RPU_0_ISR, TCM_ASLV_CE, 18, 1)
 123    FIELD(RPU_0_ISR, TCM_ASLV_FAT, 17, 1)
 124    FIELD(RPU_0_ISR, TCM_LST_CE, 16, 1)
 125    FIELD(RPU_0_ISR, TCM_PREFETCH_CE, 15, 1)
 126    FIELD(RPU_0_ISR, B1TCM_CE, 14, 1)
 127    FIELD(RPU_0_ISR, B0TCM_CE, 13, 1)
 128    FIELD(RPU_0_ISR, ATCM_CE, 12, 1)
 129    FIELD(RPU_0_ISR, B1TCM_UE, 11, 1)
 130    FIELD(RPU_0_ISR, B0TCM_UE, 10, 1)
 131    FIELD(RPU_0_ISR, ATCM_UE, 9, 1)
 132    FIELD(RPU_0_ISR, DTAG_DIRTY_FAT, 8, 1)
 133    FIELD(RPU_0_ISR, DDATA_FAT, 7, 1)
 134    FIELD(RPU_0_ISR, TCM_LST_FAT, 6, 1)
 135    FIELD(RPU_0_ISR, TCM_PREFETCH_FAT, 5, 1)
 136    FIELD(RPU_0_ISR, DDATA_CE, 4, 1)
 137    FIELD(RPU_0_ISR, DTAG_DIRTY_CE, 3, 1)
 138    FIELD(RPU_0_ISR, IDATA_CE, 2, 1)
 139    FIELD(RPU_0_ISR, ITAG_CE, 1, 1)
 140    FIELD(RPU_0_ISR, APB_ERR, 0, 1)
 141REG32(RPU_0_IMR, 0x118)
 142    FIELD(RPU_0_IMR, FPUFC, 24, 1)
 143    FIELD(RPU_0_IMR, FPOFC, 23, 1)
 144    FIELD(RPU_0_IMR, FPIXC, 22, 1)
 145    FIELD(RPU_0_IMR, FPIOC, 21, 1)
 146    FIELD(RPU_0_IMR, FPIDC, 20, 1)
 147    FIELD(RPU_0_IMR, FPDZC, 19, 1)
 148    FIELD(RPU_0_IMR, TCM_ASLV_CE, 18, 1)
 149    FIELD(RPU_0_IMR, TCM_ASLV_FAT, 17, 1)
 150    FIELD(RPU_0_IMR, TCM_LST_CE, 16, 1)
 151    FIELD(RPU_0_IMR, TCM_PREFETCH_CE, 15, 1)
 152    FIELD(RPU_0_IMR, B1TCM_CE, 14, 1)
 153    FIELD(RPU_0_IMR, B0TCM_CE, 13, 1)
 154    FIELD(RPU_0_IMR, ATCM_CE, 12, 1)
 155    FIELD(RPU_0_IMR, B1TCM_UE, 11, 1)
 156    FIELD(RPU_0_IMR, B0TCM_UE, 10, 1)
 157    FIELD(RPU_0_IMR, ATCM_UE, 9, 1)
 158    FIELD(RPU_0_IMR, DTAG_DIRTY_FAT, 8, 1)
 159    FIELD(RPU_0_IMR, DDATA_FAT, 7, 1)
 160    FIELD(RPU_0_IMR, TCM_LST_FAT, 6, 1)
 161    FIELD(RPU_0_IMR, TCM_PREFETCH_FAT, 5, 1)
 162    FIELD(RPU_0_IMR, DDATA_CE, 4, 1)
 163    FIELD(RPU_0_IMR, DTAG_DIRTY_CE, 3, 1)
 164    FIELD(RPU_0_IMR, IDATA_CE, 2, 1)
 165    FIELD(RPU_0_IMR, ITAG_CE, 1, 1)
 166    FIELD(RPU_0_IMR, APB_ERR, 0, 1)
 167REG32(RPU_0_IEN, 0x11c)
 168    FIELD(RPU_0_IEN, FPUFC, 24, 1)
 169    FIELD(RPU_0_IEN, FPOFC, 23, 1)
 170    FIELD(RPU_0_IEN, FPIXC, 22, 1)
 171    FIELD(RPU_0_IEN, FPIOC, 21, 1)
 172    FIELD(RPU_0_IEN, FPIDC, 20, 1)
 173    FIELD(RPU_0_IEN, FPDZC, 19, 1)
 174    FIELD(RPU_0_IEN, TCM_ASLV_CE, 18, 1)
 175    FIELD(RPU_0_IEN, TCM_ASLV_FAT, 17, 1)
 176    FIELD(RPU_0_IEN, TCM_LST_CE, 16, 1)
 177    FIELD(RPU_0_IEN, TCM_PREFETCH_CE, 15, 1)
 178    FIELD(RPU_0_IEN, B1TCM_CE, 14, 1)
 179    FIELD(RPU_0_IEN, B0TCM_CE, 13, 1)
 180    FIELD(RPU_0_IEN, ATCM_CE, 12, 1)
 181    FIELD(RPU_0_IEN, B1TCM_UE, 11, 1)
 182    FIELD(RPU_0_IEN, B0TCM_UE, 10, 1)
 183    FIELD(RPU_0_IEN, ATCM_UE, 9, 1)
 184    FIELD(RPU_0_IEN, DTAG_DIRTY_FAT, 8, 1)
 185    FIELD(RPU_0_IEN, DDATA_FAT, 7, 1)
 186    FIELD(RPU_0_IEN, TCM_LST_FAT, 6, 1)
 187    FIELD(RPU_0_IEN, TCM_PREFETCH_FAT, 5, 1)
 188    FIELD(RPU_0_IEN, DDATA_CE, 4, 1)
 189    FIELD(RPU_0_IEN, DTAG_DIRTY_CE, 3, 1)
 190    FIELD(RPU_0_IEN, IDATA_CE, 2, 1)
 191    FIELD(RPU_0_IEN, ITAG_CE, 1, 1)
 192    FIELD(RPU_0_IEN, APB_ERR, 0, 1)
 193REG32(RPU_0_IDS, 0x120)
 194    FIELD(RPU_0_IDS, FPUFC, 24, 1)
 195    FIELD(RPU_0_IDS, FPOFC, 23, 1)
 196    FIELD(RPU_0_IDS, FPIXC, 22, 1)
 197    FIELD(RPU_0_IDS, FPIOC, 21, 1)
 198    FIELD(RPU_0_IDS, FPIDC, 20, 1)
 199    FIELD(RPU_0_IDS, FPDZC, 19, 1)
 200    FIELD(RPU_0_IDS, TCM_ASLV_CE, 18, 1)
 201    FIELD(RPU_0_IDS, TCM_ASLV_FAT, 17, 1)
 202    FIELD(RPU_0_IDS, TCM_LST_CE, 16, 1)
 203    FIELD(RPU_0_IDS, TCM_PREFETCH_CE, 15, 1)
 204    FIELD(RPU_0_IDS, B1TCM_CE, 14, 1)
 205    FIELD(RPU_0_IDS, B0TCM_CE, 13, 1)
 206    FIELD(RPU_0_IDS, ATCM_CE, 12, 1)
 207    FIELD(RPU_0_IDS, B1TCM_UE, 11, 1)
 208    FIELD(RPU_0_IDS, B0TCM_UE, 10, 1)
 209    FIELD(RPU_0_IDS, ATCM_UE, 9, 1)
 210    FIELD(RPU_0_IDS, DTAG_DIRTY_FAT, 8, 1)
 211    FIELD(RPU_0_IDS, DDATA_FAT, 7, 1)
 212    FIELD(RPU_0_IDS, TCM_LST_FAT, 6, 1)
 213    FIELD(RPU_0_IDS, TCM_PREFETCH_FAT, 5, 1)
 214    FIELD(RPU_0_IDS, DDATA_CE, 4, 1)
 215    FIELD(RPU_0_IDS, DTAG_DIRTY_CE, 3, 1)
 216    FIELD(RPU_0_IDS, IDATA_CE, 2, 1)
 217    FIELD(RPU_0_IDS, ITAG_CE, 1, 1)
 218    FIELD(RPU_0_IDS, APB_ERR, 0, 1)
 219REG32(RPU_0_SLV_BASE, 0x124)
 220    FIELD(RPU_0_SLV_BASE, ADDR, 0, 8)
 221REG32(RPU_0_AXI_OVER, 0x128)
 222    FIELD(RPU_0_AXI_OVER, AWCACHE, 6, 4)
 223    FIELD(RPU_0_AXI_OVER, ARCACHE, 2, 4)
 224    FIELD(RPU_0_AXI_OVER, AWCACHE_EN, 1, 1)
 225    FIELD(RPU_0_AXI_OVER, ARCACHE_EN, 0, 1)
 226REG32(RPU_1_CFG, 0x200)
 227    FIELD(RPU_1_CFG, CFGNMFI1, 3, 1)
 228    FIELD(RPU_1_CFG, VINITHI, 2, 1)
 229    FIELD(RPU_1_CFG, COHERENT, 1, 1)
 230    FIELD(RPU_1_CFG, NCPUHALT, 0, 1)
 231REG32(RPU_1_STATUS, 0x204)
 232    FIELD(RPU_1_STATUS, NVALRESET, 5, 1)
 233    FIELD(RPU_1_STATUS, NVALIRQ, 4, 1)
 234    FIELD(RPU_1_STATUS, NVALFIQ, 3, 1)
 235    FIELD(RPU_1_STATUS, NWFIPIPESTOPPED, 2, 1)
 236    FIELD(RPU_1_STATUS, NWFEPIPESTOPPED, 1, 1)
 237    FIELD(RPU_1_STATUS, NCLKSTOPPED, 0, 1)
 238REG32(RPU_1_PWRDWN, 0x208)
 239    FIELD(RPU_1_PWRDWN, EN, 0, 1)
 240REG32(RPU_1_ISR, 0x214)
 241    FIELD(RPU_1_ISR, FPUFC, 24, 1)
 242    FIELD(RPU_1_ISR, FPOFC, 23, 1)
 243    FIELD(RPU_1_ISR, FPIXC, 22, 1)
 244    FIELD(RPU_1_ISR, FPIOC, 21, 1)
 245    FIELD(RPU_1_ISR, FPIDC, 20, 1)
 246    FIELD(RPU_1_ISR, FPDZC, 19, 1)
 247    FIELD(RPU_1_ISR, TCM_ASLV_CE, 18, 1)
 248    FIELD(RPU_1_ISR, TCM_ASLV_FAT, 17, 1)
 249    FIELD(RPU_1_ISR, TCM_LST_CE, 16, 1)
 250    FIELD(RPU_1_ISR, TCM_PREFETCH_CE, 15, 1)
 251    FIELD(RPU_1_ISR, B1TCM_CE, 14, 1)
 252    FIELD(RPU_1_ISR, B0TCM_CE, 13, 1)
 253    FIELD(RPU_1_ISR, ATCM_CE, 12, 1)
 254    FIELD(RPU_1_ISR, B1TCM_UE, 11, 1)
 255    FIELD(RPU_1_ISR, B0TCM_UE, 10, 1)
 256    FIELD(RPU_1_ISR, ATCM_UE, 9, 1)
 257    FIELD(RPU_1_ISR, DTAG_DIRTY_FAT, 8, 1)
 258    FIELD(RPU_1_ISR, DDATA_FAT, 7, 1)
 259    FIELD(RPU_1_ISR, TCM_LST_FAT, 6, 1)
 260    FIELD(RPU_1_ISR, TCM_PREFETCH_FAT, 5, 1)
 261    FIELD(RPU_1_ISR, DDATA_CE, 4, 1)
 262    FIELD(RPU_1_ISR, DTAG_DIRTY_CE, 3, 1)
 263    FIELD(RPU_1_ISR, IDATA_CE, 2, 1)
 264    FIELD(RPU_1_ISR, ITAG_CE, 1, 1)
 265    FIELD(RPU_1_ISR, APB_ERR, 0, 1)
 266REG32(RPU_1_IMR, 0x218)
 267    FIELD(RPU_1_IMR, FPUFC, 24, 1)
 268    FIELD(RPU_1_IMR, FPOFC, 23, 1)
 269    FIELD(RPU_1_IMR, FPIXC, 22, 1)
 270    FIELD(RPU_1_IMR, FPIOC, 21, 1)
 271    FIELD(RPU_1_IMR, FPIDC, 20, 1)
 272    FIELD(RPU_1_IMR, FPDZC, 19, 1)
 273    FIELD(RPU_1_IMR, TCM_ASLV_CE, 18, 1)
 274    FIELD(RPU_1_IMR, TCM_ASLV_FAT, 17, 1)
 275    FIELD(RPU_1_IMR, TCM_LST_CE, 16, 1)
 276    FIELD(RPU_1_IMR, TCM_PREFETCH_CE, 15, 1)
 277    FIELD(RPU_1_IMR, B1TCM_CE, 14, 1)
 278    FIELD(RPU_1_IMR, B0TCM_CE, 13, 1)
 279    FIELD(RPU_1_IMR, ATCM_CE, 12, 1)
 280    FIELD(RPU_1_IMR, B1TCM_UE, 11, 1)
 281    FIELD(RPU_1_IMR, B0TCM_UE, 10, 1)
 282    FIELD(RPU_1_IMR, ATCM_UE, 9, 1)
 283    FIELD(RPU_1_IMR, DTAG_DIRTY_FAT, 8, 1)
 284    FIELD(RPU_1_IMR, DDATA_FAT, 7, 1)
 285    FIELD(RPU_1_IMR, TCM_LST_FAT, 6, 1)
 286    FIELD(RPU_1_IMR, TCM_PREFETCH_FAT, 5, 1)
 287    FIELD(RPU_1_IMR, DDATA_CE, 4, 1)
 288    FIELD(RPU_1_IMR, DTAG_DIRTY_CE, 3, 1)
 289    FIELD(RPU_1_IMR, IDATA_CE, 2, 1)
 290    FIELD(RPU_1_IMR, ITAG_CE, 1, 1)
 291    FIELD(RPU_1_IMR, APB_ERR, 0, 1)
 292REG32(RPU_1_IEN, 0x21c)
 293    FIELD(RPU_1_IEN, FPUFC, 24, 1)
 294    FIELD(RPU_1_IEN, FPOFC, 23, 1)
 295    FIELD(RPU_1_IEN, FPIXC, 22, 1)
 296    FIELD(RPU_1_IEN, FPIOC, 21, 1)
 297    FIELD(RPU_1_IEN, FPIDC, 20, 1)
 298    FIELD(RPU_1_IEN, FPDZC, 19, 1)
 299    FIELD(RPU_1_IEN, TCM_ASLV_CE, 18, 1)
 300    FIELD(RPU_1_IEN, TCM_ASLV_FAT, 17, 1)
 301    FIELD(RPU_1_IEN, TCM_LST_CE, 16, 1)
 302    FIELD(RPU_1_IEN, TCM_PREFETCH_CE, 15, 1)
 303    FIELD(RPU_1_IEN, B1TCM_CE, 14, 1)
 304    FIELD(RPU_1_IEN, B0TCM_CE, 13, 1)
 305    FIELD(RPU_1_IEN, ATCM_CE, 12, 1)
 306    FIELD(RPU_1_IEN, B1TCM_UE, 11, 1)
 307    FIELD(RPU_1_IEN, B0TCM_UE, 10, 1)
 308    FIELD(RPU_1_IEN, ATCM_UE, 9, 1)
 309    FIELD(RPU_1_IEN, DTAG_DIRTY_FAT, 8, 1)
 310    FIELD(RPU_1_IEN, DDATA_FAT, 7, 1)
 311    FIELD(RPU_1_IEN, TCM_LST_FAT, 6, 1)
 312    FIELD(RPU_1_IEN, TCM_PREFETCH_FAT, 5, 1)
 313    FIELD(RPU_1_IEN, DDATA_CE, 4, 1)
 314    FIELD(RPU_1_IEN, DTAG_DIRTY_CE, 3, 1)
 315    FIELD(RPU_1_IEN, IDATA_CE, 2, 1)
 316    FIELD(RPU_1_IEN, ITAG_CE, 1, 1)
 317    FIELD(RPU_1_IEN, APB_ERR, 0, 1)
 318REG32(RPU_1_IDS, 0x220)
 319    FIELD(RPU_1_IDS, FPUFC, 24, 1)
 320    FIELD(RPU_1_IDS, FPOFC, 23, 1)
 321    FIELD(RPU_1_IDS, FPIXC, 22, 1)
 322    FIELD(RPU_1_IDS, FPIOC, 21, 1)
 323    FIELD(RPU_1_IDS, FPIDC, 20, 1)
 324    FIELD(RPU_1_IDS, FPDZC, 19, 1)
 325    FIELD(RPU_1_IDS, TCM_ASLV_CE, 18, 1)
 326    FIELD(RPU_1_IDS, TCM_ASLV_FAT, 17, 1)
 327    FIELD(RPU_1_IDS, TCM_LST_CE, 16, 1)
 328    FIELD(RPU_1_IDS, TCM_PREFETCH_CE, 15, 1)
 329    FIELD(RPU_1_IDS, B1TCM_CE, 14, 1)
 330    FIELD(RPU_1_IDS, B0TCM_CE, 13, 1)
 331    FIELD(RPU_1_IDS, ATCM_CE, 12, 1)
 332    FIELD(RPU_1_IDS, B1TCM_UE, 11, 1)
 333    FIELD(RPU_1_IDS, B0TCM_UE, 10, 1)
 334    FIELD(RPU_1_IDS, ATCM_UE, 9, 1)
 335    FIELD(RPU_1_IDS, DTAG_DIRTY_FAT, 8, 1)
 336    FIELD(RPU_1_IDS, DDATA_FAT, 7, 1)
 337    FIELD(RPU_1_IDS, TCM_LST_FAT, 6, 1)
 338    FIELD(RPU_1_IDS, TCM_PREFETCH_FAT, 5, 1)
 339    FIELD(RPU_1_IDS, DDATA_CE, 4, 1)
 340    FIELD(RPU_1_IDS, DTAG_DIRTY_CE, 3, 1)
 341    FIELD(RPU_1_IDS, IDATA_CE, 2, 1)
 342    FIELD(RPU_1_IDS, ITAG_CE, 1, 1)
 343    FIELD(RPU_1_IDS, APB_ERR, 0, 1)
 344REG32(RPU_1_SLV_BASE, 0x224)
 345    FIELD(RPU_1_SLV_BASE, ADDR, 0, 8)
 346REG32(RPU_1_AXI_OVER, 0x228)
 347    FIELD(RPU_1_AXI_OVER, AWCACHE, 6, 4)
 348    FIELD(RPU_1_AXI_OVER, ARCACHE, 2, 4)
 349    FIELD(RPU_1_AXI_OVER, AWCACHE_EN, 1, 1)
 350    FIELD(RPU_1_AXI_OVER, ARCACHE_EN, 0, 1)
 351
 352#define RPU_R_MAX (R_RPU_1_AXI_OVER + 1)
 353
 354#define MAX_RPU 2
 355
 356typedef struct RPU {
 357    SysBusDevice parent_obj;
 358    MemoryRegion iomem;
 359    MemoryRegion mr_R5[2];
 360    MemoryRegion mr_R5_alias[2];
 361    MemoryRegion tcm_A[2];
 362    MemoryRegion tcm_B[2];
 363    MemoryRegion tcm_A1_alias[2];
 364    MemoryRegion tcm_B1_alias[2];
 365
 366    MemoryRegion icache[2];
 367    MemoryRegion dcache[2];
 368
 369    qemu_irq irq_rpu_1_imr;
 370    qemu_irq irq_rpu_0_imr;
 371    qemu_irq rpu_pwrdw[MAX_RPU];
 372    qemu_irq rpu_sleep[MAX_RPU];
 373
 374    bool r5_rst[2];
 375    qemu_irq halt[2];
 376    qemu_irq vinithi[2];
 377
 378    struct {
 379        uint32_t tcm_size;
 380        uint32_t icache_size;
 381        uint32_t dcache_size;
 382    } cfg;
 383
 384    DeviceState *rpu_cpu[MAX_RPU];
 385    uint32_t regs[RPU_R_MAX];
 386    RegisterInfo regs_info[RPU_R_MAX];
 387} RPU;
 388
 389static void rpu_1_imr_update_irq(RPU *s)
 390{
 391    bool pending = s->regs[R_RPU_1_ISR] & ~s->regs[R_RPU_1_IMR];
 392    qemu_set_irq(s->irq_rpu_1_imr, pending);
 393}
 394
 395static void rpu_1_isr_postw(RegisterInfo *reg, uint64_t val64)
 396{
 397    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 398    rpu_1_imr_update_irq(s);
 399}
 400
 401static uint64_t rpu_1_ien_prew(RegisterInfo *reg, uint64_t val64)
 402{
 403    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 404    uint32_t val = val64;
 405
 406    s->regs[R_RPU_1_IMR] &= ~val;
 407    rpu_1_imr_update_irq(s);
 408    return 0;
 409}
 410
 411static uint64_t rpu_1_ids_prew(RegisterInfo *reg, uint64_t val64)
 412{
 413    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 414    uint32_t val = val64;
 415
 416    s->regs[R_RPU_1_IMR] |= val;
 417    rpu_1_imr_update_irq(s);
 418    return 0;
 419}
 420
 421static void rpu_0_imr_update_irq(RPU *s)
 422{
 423    bool pending = s->regs[R_RPU_0_ISR] & ~s->regs[R_RPU_0_IMR];
 424    qemu_set_irq(s->irq_rpu_0_imr, pending);
 425}
 426
 427static void rpu_0_isr_postw(RegisterInfo *reg, uint64_t val64)
 428{
 429    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 430    rpu_0_imr_update_irq(s);
 431}
 432
 433static uint64_t rpu_0_ien_prew(RegisterInfo *reg, uint64_t val64)
 434{
 435    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 436    uint32_t val = val64;
 437
 438    s->regs[R_RPU_0_IMR] &= ~val;
 439    rpu_0_imr_update_irq(s);
 440    return 0;
 441}
 442
 443static uint64_t rpu_0_ids_prew(RegisterInfo *reg, uint64_t val64)
 444{
 445    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 446    uint32_t val = val64;
 447
 448    s->regs[R_RPU_0_IMR] |= val;
 449    rpu_0_imr_update_irq(s);
 450    return 0;
 451}
 452
 453static void rpu_setup_tcm(RPU *s)
 454{
 455    bool sl_clamp;
 456    bool sl_split;
 457    bool tcm_combine;
 458
 459    /* See page 26 of the DID.  */
 460    sl_clamp = ARRAY_FIELD_EX32(s->regs, RPU_GLBL_CNTL, SLCLAMP);
 461    sl_split = ARRAY_FIELD_EX32(s->regs, RPU_GLBL_CNTL, SLSPLIT);
 462    tcm_combine = ARRAY_FIELD_EX32(s->regs, RPU_GLBL_CNTL, TCM_COMB);
 463
 464    DPRINTF("%s: sl_clamp=%d sl_split=%d tcm_combine=%d\n",
 465             __func__, sl_clamp, sl_split, tcm_combine);
 466
 467    if (tcm_combine) {
 468        memory_region_set_enabled(&s->tcm_A1_alias[0], true);
 469        memory_region_set_enabled(&s->tcm_A1_alias[1], false);
 470        memory_region_set_enabled(&s->tcm_B1_alias[0], true);
 471        memory_region_set_enabled(&s->tcm_B1_alias[1], false);
 472    } else {
 473        memory_region_set_enabled(&s->tcm_A1_alias[0], false);
 474        memory_region_set_enabled(&s->tcm_A1_alias[1], true);
 475        memory_region_set_enabled(&s->tcm_B1_alias[0], false);
 476        memory_region_set_enabled(&s->tcm_B1_alias[1], true);
 477    }
 478
 479    /* Catch a few invalid combinations.  */
 480    if (sl_split) {
 481        if (sl_clamp) {
 482            qemu_log_mask(LOG_GUEST_ERROR, "slclamp set in split mode!\n");
 483        }
 484    } else {
 485        if (!sl_clamp) {
 486            qemu_log_mask(LOG_GUEST_ERROR,
 487                          "slclamp not set in lock-step mode!\n");
 488        }
 489    }
 490}
 491
 492#define PROPAGATE_GPIO(reg, f, irq) {             \
 493    bool val = ARRAY_FIELD_EX32(s->regs, reg, f); \
 494    qemu_set_irq(irq, val);                       \
 495}
 496
 497static void rpu_update_gpios(RPU *s)
 498{
 499    bool sl_split;
 500    bool ncpuhalt[2];
 501    int i;
 502
 503    sl_split = ARRAY_FIELD_EX32(s->regs, RPU_GLBL_CNTL, SLSPLIT);
 504
 505    ncpuhalt[0] = ARRAY_FIELD_EX32(s->regs, RPU_0_CFG, NCPUHALT);
 506    ncpuhalt[1] = ARRAY_FIELD_EX32(s->regs, RPU_1_CFG, NCPUHALT);
 507
 508    for (i = 0; i < ARRAY_SIZE(ncpuhalt); i++) {
 509        bool halt;
 510
 511        /* Sleep if halted or in reset.  */
 512        halt = !ncpuhalt[i];
 513        halt |= s->r5_rst[i];
 514
 515        if (i == 1 && !sl_split) {
 516            /* In lockstep mode we only run core0.  */
 517            halt = true;
 518        }
 519
 520        qemu_log_mask(CPU_LOG_RESET,
 521                      "r5 halt[%d]=%d rst=%d ncpuhalt=%d sl_split=%d\n",
 522                      i, halt, s->r5_rst[i], ncpuhalt[i], sl_split);
 523        qemu_set_irq(s->halt[i], halt);
 524    }
 525
 526    PROPAGATE_GPIO(RPU_0_CFG, VINITHI, s->vinithi[0]);
 527    PROPAGATE_GPIO(RPU_1_CFG, VINITHI, s->vinithi[1]);
 528
 529    /*
 530     * Send power down signal
 531     */
 532    if (s->regs[R_RPU_0_PWRDWN] &
 533         (!ARRAY_FIELD_EX32(s->regs, RPU_0_STATUS, NWFIPIPESTOPPED))) {
 534        qemu_irq_pulse(s->rpu_sleep[0]);
 535    }
 536    if (s->regs[R_RPU_1_PWRDWN] &
 537         (!ARRAY_FIELD_EX32(s->regs, RPU_1_STATUS, NWFIPIPESTOPPED))) {
 538        qemu_irq_pulse(s->rpu_sleep[1]);
 539    }
 540}
 541
 542static void rpu_update_gpios_pw(RegisterInfo *reg, uint64_t val64)
 543{
 544    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 545    rpu_update_gpios(s);
 546}
 547
 548static void rpu_pwrdwn_postw(RegisterInfo *reg, uint64_t val64)
 549{
 550    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 551    uint32_t r;
 552
 553    switch (reg->access->addr) {
 554    case A_RPU_0_PWRDWN:
 555        r = s->regs[R_RPU_0_PWRDWN];
 556        if (!!r) {
 557            qemu_set_irq(s->rpu_pwrdw[0], true);
 558        }
 559        break;
 560    case A_RPU_1_PWRDWN:
 561        r = s->regs[R_RPU_1_PWRDWN];
 562        if (!!r) {
 563            qemu_set_irq(s->rpu_pwrdw[1], true);
 564        }
 565        break;
 566    default:
 567        g_assert_not_reached();
 568    }
 569}
 570
 571static void rpu_update_gic_axprot(RPU *s, bool secure)
 572{
 573    unsigned int i;
 574    for (i = 0; i < MAX_RPU; i++) {
 575        if (s->rpu_cpu[i]) {
 576            qdev_prop_set_bit(s->rpu_cpu[i], "memattr-secure", secure);
 577        }
 578    }
 579}
 580
 581static void rpu_glbl_cntl_pw(RegisterInfo *reg, uint64_t val64)
 582{
 583    RPU *s = XILINX_VERSAL_RPU(reg->opaque);
 584
 585    rpu_update_gic_axprot(s, val64 & R_RPU_GLBL_CNTL_GIC_AXPROT_MASK ? false :
 586                          true);
 587    rpu_setup_tcm(s);
 588    rpu_update_gpios(s);
 589}
 590
 591static const RegisterAccessInfo rpu_regs_info[] = {
 592    {   .name = "RPU_GLBL_CNTL",  .addr = A_RPU_GLBL_CNTL,
 593        .reset = 0x50,
 594        .rsvd = 0xfffffa00,
 595        .post_write = rpu_glbl_cntl_pw,
 596    },{ .name = "RPU_GLBL_STATUS",  .addr = A_RPU_GLBL_STATUS,
 597        .rsvd = 0xfffffffe,
 598        .ro = 0x1,
 599    },{ .name = "RPU_ERR_CNTL",  .addr = A_RPU_ERR_CNTL,
 600        .rsvd = 0xfffffffe,
 601    },{ .name = "RPU_ERR_INJ",  .addr = A_RPU_ERR_INJ,
 602        .rsvd = 0xffff0000,
 603    },{ .name = "RPU_CCF_MASK",  .addr = A_RPU_CCF_MASK,
 604        .rsvd = 0xffffff00,
 605    },{ .name = "RPU_INTR_0",  .addr = A_RPU_INTR_0,
 606    },{ .name = "RPU_INTR_1",  .addr = A_RPU_INTR_1,
 607    },{ .name = "RPU_INTR_2",  .addr = A_RPU_INTR_2,
 608    },{ .name = "RPU_INTR_3",  .addr = A_RPU_INTR_3,
 609    },{ .name = "RPU_INTR_4",  .addr = A_RPU_INTR_4,
 610    },{ .name = "RPU_INTR_MASK_0",  .addr = A_RPU_INTR_MASK_0,
 611    },{ .name = "RPU_INTR_MASK_1",  .addr = A_RPU_INTR_MASK_1,
 612    },{ .name = "RPU_INTR_MASK_2",  .addr = A_RPU_INTR_MASK_2,
 613    },{ .name = "RPU_INTR_MASK_3",  .addr = A_RPU_INTR_MASK_3,
 614    },{ .name = "RPU_INTR_MASK_4",  .addr = A_RPU_INTR_MASK_4,
 615    },{ .name = "RPU_CCF_VAL",  .addr = A_RPU_CCF_VAL,
 616        .reset = 0x7,
 617        .rsvd = 0xffffff00,
 618    },{ .name = "RPU_SAFETY_CHK",  .addr = A_RPU_SAFETY_CHK,
 619    },{ .name = "RPU_0_CFG",  .addr = A_RPU_0_CFG,
 620        .reset = 0x5,
 621        .rsvd = 0xfffffff0,
 622        .post_write = rpu_update_gpios_pw,
 623    },{ .name = "RPU_0_STATUS",  .addr = A_RPU_0_STATUS,
 624        .reset = 0x3f,
 625        .rsvd = 0xffffffc0,
 626        .ro = 0x3f,
 627    },{ .name = "RPU_0_PWRDWN",  .addr = A_RPU_0_PWRDWN,
 628        .rsvd = 0xfffffffe,
 629        .post_write = rpu_pwrdwn_postw,
 630    },{ .name = "RPU_0_ISR",  .addr = A_RPU_0_ISR,
 631        .rsvd = 0xfe000000,
 632        .w1c = 0x1ffffff,
 633        .post_write = rpu_0_isr_postw,
 634    },{ .name = "RPU_0_IMR",  .addr = A_RPU_0_IMR,
 635        .reset = 0x1ffffff,
 636        .rsvd = 0xfe000000,
 637        .ro = 0x1ffffff,
 638    },{ .name = "RPU_0_IEN",  .addr = A_RPU_0_IEN,
 639        .rsvd = 0xfe000000,
 640        .pre_write = rpu_0_ien_prew,
 641    },{ .name = "RPU_0_IDS",  .addr = A_RPU_0_IDS,
 642        .rsvd = 0xfe000000,
 643        .pre_write = rpu_0_ids_prew,
 644    },{ .name = "RPU_0_SLV_BASE",  .addr = A_RPU_0_SLV_BASE,
 645        .rsvd = 0xffffff00,
 646    },{ .name = "RPU_0_AXI_OVER",  .addr = A_RPU_0_AXI_OVER,
 647        .rsvd = 0xfffffc00,
 648    },{ .name = "RPU_1_CFG",  .addr = A_RPU_1_CFG,
 649        .reset = 0x5,
 650        .rsvd = 0xfffffff0,
 651        .post_write = rpu_update_gpios_pw,
 652    },{ .name = "RPU_1_STATUS",  .addr = A_RPU_1_STATUS,
 653        .reset = 0x3f,
 654        .rsvd = 0xffffffc0,
 655        .ro = 0x3f,
 656    },{ .name = "RPU_1_PWRDWN",  .addr = A_RPU_1_PWRDWN,
 657        .rsvd = 0xfffffffe,
 658        .post_write = rpu_pwrdwn_postw,
 659    },{ .name = "RPU_1_ISR",  .addr = A_RPU_1_ISR,
 660        .rsvd = 0xfe000000,
 661        .w1c = 0x1ffffff,
 662        .post_write = rpu_1_isr_postw,
 663    },{ .name = "RPU_1_IMR",  .addr = A_RPU_1_IMR,
 664        .reset = 0x1ffffff,
 665        .rsvd = 0xfe000000,
 666        .ro = 0x1ffffff,
 667    },{ .name = "RPU_1_IEN",  .addr = A_RPU_1_IEN,
 668        .rsvd = 0xfe000000,
 669        .pre_write = rpu_1_ien_prew,
 670    },{ .name = "RPU_1_IDS",  .addr = A_RPU_1_IDS,
 671        .rsvd = 0xfe000000,
 672        .pre_write = rpu_1_ids_prew,
 673    },{ .name = "RPU_1_SLV_BASE",  .addr = A_RPU_1_SLV_BASE,
 674        .rsvd = 0xffffff00,
 675    },{ .name = "RPU_1_AXI_OVER",  .addr = A_RPU_1_AXI_OVER,
 676        .rsvd = 0xfffffc00,
 677    }
 678};
 679
 680static void rpu_reset(DeviceState *dev)
 681{
 682    RPU *s = XILINX_VERSAL_RPU(dev);
 683    unsigned int i;
 684
 685    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 686        register_reset(&s->regs_info[i]);
 687    }
 688
 689    rpu_1_imr_update_irq(s);
 690    rpu_0_imr_update_irq(s);
 691
 692    rpu_update_gic_axprot(s, true);
 693    rpu_update_gpios(s);
 694}
 695
 696static void rpu_rst_h(void *opaque, int irq, int level)
 697{
 698    RPU *s = XILINX_VERSAL_RPU(opaque);
 699
 700    s->r5_rst[irq] = level;
 701    rpu_update_gpios(s);
 702}
 703
 704static void rpu_wfi_h(void *opaque, int irq, int level)
 705{
 706    RPU *s = XILINX_VERSAL_RPU(opaque);
 707
 708    switch (irq) {
 709    case 0:
 710        ARRAY_FIELD_DP32(s->regs, RPU_0_STATUS, NWFIPIPESTOPPED, !level);
 711        break;
 712    case 1:
 713        ARRAY_FIELD_DP32(s->regs, RPU_1_STATUS, NWFIPIPESTOPPED, !level);
 714        break;
 715    default:
 716        g_assert_not_reached();
 717    }
 718    rpu_update_gpios(s);
 719}
 720
 721static void rpu_pwr_status_h(void *opaque, int irq, int level)
 722{
 723    RPU *s = XILINX_VERSAL_RPU(opaque);
 724
 725    if (!!level) {
 726        qemu_set_irq(s->rpu_pwrdw[irq], false);
 727    }
 728}
 729
 730static const MemoryRegionOps rpu_ops = {
 731    .read = register_read_memory,
 732    .write = register_write_memory,
 733    .endianness = DEVICE_LITTLE_ENDIAN,
 734    .valid = {
 735        .min_access_size = 4,
 736        .max_access_size = 4,
 737    },
 738};
 739
 740static void rpu_realize(DeviceState *dev, Error **errp)
 741{
 742    RPU *s = XILINX_VERSAL_RPU(dev);
 743    char *name;
 744    int i;
 745
 746    /* There's two R5 views we need to construct here.
 747     * R5_0 and R5_1.
 748     *
 749     * Each R5 has two TCM's, A and B. When TCM combine
 750     * is off, they both see their own respective A
 751     * and B TCM's with a hole in between. When combined
 752     * the full 256KB is accessible to R5_0 contigously.
 753     *
 754     * R5_0 (non-combined):
 755     * 0x00000 - 0x10000  ATCM0
 756     * 0x10000 - 0x20000  N/A
 757     * 0x20000 - 0x30000  BTCM0
 758     * 0x30000 - 0x50000  N/A
 759     *
 760     * R5_1 (non-combined):
 761     * 0x00000 - 0x10000  ATCM1
 762     * 0x10000 - 0x20000  N/A
 763     * 0x20000 - 0x30000  BTCM1
 764     * 0x30000 - 0x50000  N/A
 765     *
 766     * R5_0 (combined):
 767     * 0x00000 - 0x10000  ATCM0
 768     * 0x10000 - 0x20000  ATCM1
 769     * 0x20000 - 0x30000  BTCM0
 770     * 0x30000 - 0x40000  BTCM1
 771     *
 772     * R5_1 (combined):
 773     * 0x00000 - 0x10000  N/A
 774     * 0x10000 - 0x20000  N/A
 775     * 0x20000 - 0x30000  N/A
 776     * 0x30000 - 0x40000  N/A
 777     *
 778     */
 779
 780
 781    for (i = 0; i < ARRAY_SIZE(s->tcm_A); i++) {
 782        name = g_strdup_printf("mr-R5_%d", i);
 783        memory_region_init(&s->mr_R5[i], OBJECT(dev),
 784                           name,
 785                           s->cfg.tcm_size * 6);
 786        g_free(name);
 787
 788        name = g_strdup_printf("tcm_A%d", i);
 789        memory_region_init_ram(&s->tcm_A[i], OBJECT(dev),
 790                               name, s->cfg.tcm_size, &error_fatal);
 791        g_free(name);
 792
 793        name = g_strdup_printf("tcm_B%d", i);
 794        memory_region_init_ram(&s->tcm_B[i], OBJECT(dev),
 795                               name, s->cfg.tcm_size, &error_fatal);
 796        g_free(name);
 797
 798        name = g_strdup_printf("icache%d", i);
 799        memory_region_init_ram(&s->icache[i], OBJECT(dev),
 800                               name, s->cfg.icache_size, &error_fatal);
 801        g_free(name);
 802
 803        name = g_strdup_printf("dcache%d", i);
 804        memory_region_init_ram(&s->dcache[i], OBJECT(dev),
 805                               name, s->cfg.dcache_size, &error_fatal);
 806        g_free(name);
 807
 808        name = g_strdup_printf("mr-R5_%d-alias", i);
 809        memory_region_init_alias(&s->mr_R5_alias[i], OBJECT(dev),
 810                                 name, &s->mr_R5[i], 0x0, s->cfg.tcm_size * 6);
 811        g_free(name);
 812
 813        sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr_R5[i]);
 814        sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr_R5_alias[i]);
 815    }
 816
 817    for (i = 0; i < ARRAY_SIZE(s->tcm_A1_alias); i++) {
 818        name = g_strdup_printf("tcm_A1-%d-alias", i);
 819        memory_region_init_alias(&s->tcm_A1_alias[i], OBJECT(dev),
 820                                 name, &s->tcm_A[1], 0x0, s->cfg.tcm_size);
 821        g_free(name);
 822
 823        name = g_strdup_printf("tcm_B1-%d-alias", i);
 824        memory_region_init_alias(&s->tcm_B1_alias[i], OBJECT(dev),
 825                                 name, &s->tcm_B[1], 0x0, s->cfg.tcm_size);
 826        g_free(name);
 827    }
 828
 829    /* See page 28 of the DID.  */
 830    memory_region_add_subregion_overlap(&s->mr_R5[0], 0x0,
 831                                        &s->tcm_A[0], 0);
 832    memory_region_add_subregion_overlap(&s->mr_R5[0], s->cfg.tcm_size * 1,
 833                                        &s->tcm_A1_alias[0], 0);
 834    memory_region_add_subregion_overlap(&s->mr_R5[0], s->cfg.tcm_size * 2,
 835                                        &s->tcm_B[0], 0);
 836    memory_region_add_subregion_overlap(&s->mr_R5[0], s->cfg.tcm_size * 3,
 837                                        &s->tcm_B1_alias[0], 0);
 838    memory_region_add_subregion_overlap(&s->mr_R5[0], s->cfg.tcm_size * 4,
 839                                        &s->icache[0], 0);
 840    memory_region_add_subregion_overlap(&s->mr_R5[0], s->cfg.tcm_size * 5,
 841                                        &s->dcache[0], 0);
 842
 843    memory_region_add_subregion_overlap(&s->mr_R5[1], 0x0,
 844                                        &s->tcm_A1_alias[1], 0);
 845    memory_region_add_subregion_overlap(&s->mr_R5[1], s->cfg.tcm_size * 2,
 846                                        &s->tcm_B1_alias[1], 0);
 847    memory_region_add_subregion_overlap(&s->mr_R5[1], s->cfg.tcm_size * 4,
 848                                        &s->icache[1], 0);
 849    memory_region_add_subregion_overlap(&s->mr_R5[1], s->cfg.tcm_size * 5,
 850                                        &s->dcache[1], 0);
 851}
 852
 853static void rpu_init(Object *obj)
 854{
 855    RPU *s = XILINX_VERSAL_RPU(obj);
 856    DeviceState *dev = DEVICE(obj);
 857    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 858    RegisterInfoArray *reg_array;
 859    unsigned int i;
 860    char *name;
 861
 862    memory_region_init(&s->iomem, obj, TYPE_XILINX_VERSAL_RPU, RPU_R_MAX * 4);
 863    reg_array =
 864        register_init_block32(DEVICE(obj), rpu_regs_info,
 865                              ARRAY_SIZE(rpu_regs_info),
 866                              s->regs_info, s->regs,
 867                              &rpu_ops,
 868                              XILINX_VERSAL_RPU_ERR_DEBUG,
 869                              RPU_R_MAX * 4);
 870    memory_region_add_subregion(&s->iomem,
 871                                0x0,
 872                                &reg_array->mem);
 873    sysbus_init_mmio(sbd, &s->iomem);
 874
 875    sysbus_init_irq(sbd, &s->irq_rpu_1_imr);
 876    sysbus_init_irq(sbd, &s->irq_rpu_0_imr);
 877
 878    qdev_init_gpio_out_named(dev, s->halt, "halt", 2);
 879    qdev_init_gpio_out_named(dev, s->vinithi, "vinithi", 2);
 880    qdev_init_gpio_in_named(dev, rpu_rst_h, "rpu-rst", 2);
 881    qdev_init_gpio_in_named(dev, rpu_wfi_h, "rpu-wfi", 2);
 882    qdev_init_gpio_in_named(dev, rpu_pwr_status_h, "rpu-pwr-status", MAX_RPU);
 883    qdev_init_gpio_out_named(dev, s->rpu_pwrdw, "rpu-pwrdw", MAX_RPU);
 884    qdev_init_gpio_out_named(dev, s->rpu_sleep, "rpu-sleep", MAX_RPU);
 885
 886    for (i = 0; i < MAX_RPU; i++) {
 887        name = g_strdup_printf("rpu%d", i);
 888        object_property_add_link(obj, name, TYPE_DEVICE,
 889                             (Object **)&s->rpu_cpu[i],
 890                             qdev_prop_allow_set_link_before_realize,
 891                             OBJ_PROP_LINK_STRONG);
 892        g_free(name);
 893    }
 894}
 895
 896static const VMStateDescription vmstate_rpu = {
 897    .name = TYPE_XILINX_VERSAL_RPU,
 898    .version_id = 1,
 899    .minimum_version_id = 1,
 900    .fields = (VMStateField[]) {
 901        VMSTATE_UINT32_ARRAY(regs, RPU, RPU_R_MAX),
 902        VMSTATE_END_OF_LIST(),
 903    }
 904};
 905
 906static const FDTGenericGPIOSet crl_gpios[] = {
 907    {
 908      .names = &fdt_generic_gpio_name_set_gpio,
 909      .gpios = (FDTGenericGPIOConnection[]) {
 910        { .name = "halt", .fdt_index = 0, .range = 2 },
 911        { .name = "rpu-wfi", .fdt_index = 2, .range = 2},
 912        { .name = "vinithi", .fdt_index = 4, .range = 2 },
 913        { .name = "rpu-pwrdw", .fdt_index = 6, .range = MAX_RPU },
 914        { .name = "rpu-sleep", .fdt_index = (6 + MAX_RPU), .range = MAX_RPU },
 915        { },
 916      },
 917    },
 918    { },
 919};
 920
 921static const FDTGenericGPIOSet rpu_client_gpios[] = {
 922    {
 923      .names = &fdt_generic_gpio_name_set_gpio,
 924      .gpios = (FDTGenericGPIOConnection[]) {
 925        { .name = "rpu-rst", .fdt_index = 0, .range = 2 },
 926        { .name = "rpu-pwr-status", .fdt_index = 2, .range = MAX_RPU },
 927        { },
 928      },
 929    },
 930    { },
 931};
 932
 933static Property rpu_properties[] = {
 934    DEFINE_PROP_UINT32("tcm-size", RPU, cfg.tcm_size, 64 * 1024),
 935    DEFINE_PROP_UINT32("icache-size", RPU, cfg.icache_size, 64 * 1024),
 936    DEFINE_PROP_UINT32("dcache-size", RPU, cfg.dcache_size, 64 * 1024),
 937    DEFINE_PROP_END_OF_LIST(),
 938};
 939
 940static void rpu_class_init(ObjectClass *klass, void *data)
 941{
 942    DeviceClass *dc = DEVICE_CLASS(klass);
 943    FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
 944
 945    dc->reset = rpu_reset;
 946    dc->realize = rpu_realize;
 947    dc->vmsd = &vmstate_rpu;
 948    device_class_set_props(dc, rpu_properties);
 949    fggc->controller_gpios = crl_gpios;
 950    fggc->client_gpios = rpu_client_gpios;
 951}
 952
 953static const TypeInfo rpu_info = {
 954    .name          = TYPE_XILINX_VERSAL_RPU,
 955    .parent        = TYPE_SYS_BUS_DEVICE,
 956    .instance_size = sizeof(RPU),
 957    .class_init    = rpu_class_init,
 958    .instance_init = rpu_init,
 959    .interfaces = (InterfaceInfo[]) {
 960        { TYPE_FDT_GENERIC_GPIO },
 961        { }
 962    },
 963};
 964
 965static void rpu_register_types(void)
 966{
 967    type_register_static(&rpu_info);
 968}
 969
 970type_init(rpu_register_types)
 971