qemu/hw/dma/xilinx_devcfg.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the Xilinx Devcfg Interface
   3 *
   4 * (C) 2011 PetaLogix Pty Ltd
   5 * (C) 2014 Xilinx Inc.
   6 * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
   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 "sysemu/sysemu.h"
  29#include "sysemu/dma.h"
  30#include "hw/sysbus.h"
  31#include "qemu/bitops.h"
  32#include "hw/register-dep.h"
  33#include "qapi/error.h"
  34#include "qemu/log.h"
  35#include "qemu/bitops.h"
  36
  37#define TYPE_XILINX_DEVCFG "xlnx.ps7-dev-cfg"
  38
  39#define XILINX_DEVCFG(obj) \
  40    OBJECT_CHECK(XilinxDevcfg, (obj), TYPE_XILINX_DEVCFG)
  41
  42/* FIXME: get rid of hardcoded nastiness */
  43
  44#define FREQ_HZ 900000000
  45
  46#define BTT_MAX 0x400 /* bytes to transfer per delay inteval */
  47
  48#ifndef XILINX_DEVCFG_ERR_DEBUG
  49#define XILINX_DEVCFG_ERR_DEBUG 0
  50#endif
  51#define DB_PRINT(...) do { \
  52    if (XILINX_DEVCFG_ERR_DEBUG) { \
  53        fprintf(stderr,  ": %s: ", __func__); \
  54        fprintf(stderr, ## __VA_ARGS__); \
  55    } \
  56} while (0);
  57
  58#define R_CTRL            (0x00/4)
  59    #define FORCE_RST            (1 << 31) /* Not supported, writes ignored */
  60    #define PCAP_PR              (1 << 27) /* Forced to 0 on bad unlock */
  61    #define PCAP_MODE            (1 << 26)
  62    #define MULTIBOOT_EN         (1 << 24)
  63    #define USER_MODE            (1 << 15)
  64    #define PCFG_AES_FUSE        (1 << 12) /* locked by AES_FUSE_LOCK */
  65    #define PCFG_AES_EN_SHIFT    9 /* locked by AES_EN_LOCK */
  66    #define PCFG_AES_EN_LEN      3 /* locked by AES_EN_LOCK */
  67    #define PCFG_AES_EN_MASK     (((1 << PCFG_AES_EN_LEN) - 1) \
  68                                    << PCFG_AES_EN_SHIFT)
  69    #define SEU_EN               (1 << 8) /* locked by SEU_LOCK */
  70    #define SEC_EN               (1 << 7) /* locked by SEC_LOCK */
  71    #define SPNIDEN              (1 << 6) /* locked by DBG_LOCK */
  72    #define SPIDEN               (1 << 5) /* locked by DBG_LOCK */
  73    #define NIDEN                (1 << 4) /* locked by DBG_LOCK */
  74    #define DBGEN                (1 << 3) /* locked by DBG_LOCK */
  75    #define DAP_EN               (7 << 0) /* locked by DBG_LOCK */
  76
  77#define R_LOCK          (0x04/4)
  78    #define AES_FUSE_LOCK        4
  79    #define AES_EN_LOCK          3
  80    #define SEU_LOCK             2
  81    #define SEC_LOCK             1
  82    #define DBG_LOCK             0
  83
  84/* mapping bits in R_LOCK to what they lock in R_CTRL */
  85static const uint32_t lock_ctrl_map[] = {
  86    [AES_FUSE_LOCK] = PCFG_AES_FUSE,
  87    [AES_EN_LOCK] = PCFG_AES_EN_MASK,
  88    [SEU_LOCK] = SEU_LOCK,
  89    [SEC_LOCK] = SEC_LOCK,
  90    [DBG_LOCK] =  SPNIDEN | SPIDEN | NIDEN | DBGEN | DAP_EN,
  91};
  92
  93#define R_CFG           (0x08/4)
  94    #define RFIFO_TH_SHIFT       10
  95    #define RFIFO_TH_LEN         2
  96    #define WFIFO_TH_SHIFT       8
  97    #define WFIFO_TH_LEN         2
  98    #define DISABLE_SRC_INC      (1 << 5)
  99    #define DISABLE_DST_INC      (1 << 4)
 100#define R_CFG_RO 0xFFFFF800
 101#define R_CFG_RESET 0x50B
 102
 103#define R_INT_STS       (0x0C/4)
 104    #define PSS_GTS_USR_B_INT    (1 << 31)
 105    #define PSS_FST_CFG_B_INT    (1 << 30)
 106    #define PSS_CFG_RESET_B_INT  (1 << 27)
 107    #define RX_FIFO_OV_INT       (1 << 18)
 108    #define WR_FIFO_LVL_INT      (1 << 17)
 109    #define RD_FIFO_LVL_INT      (1 << 16)
 110    #define DMA_CMD_ERR_INT      (1 << 15)
 111    #define DMA_Q_OV_INT         (1 << 14)
 112    #define DMA_DONE_INT         (1 << 13)
 113    #define DMA_P_DONE_INT       (1 << 12)
 114    #define P2D_LEN_ERR_INT      (1 << 11)
 115    #define PCFG_DONE_INT        (1 << 2)
 116    #define R_INT_STS_RSVD       ((0x7 << 24) | (0x1 << 19) | (0xF < 7))
 117
 118#define R_INT_MASK      (0x10/4)
 119
 120#define R_STATUS        (0x14/4)
 121    #define DMA_CMD_Q_F         (1 << 31)
 122    #define DMA_CMD_Q_E         (1 << 30)
 123    #define DMA_DONE_CNT_SHIFT  28
 124    #define DMA_DONE_CNT_LEN    2
 125    #define RX_FIFO_LVL_SHIFT   20
 126    #define RX_FIFO_LVL_LEN     5
 127    #define TX_FIFO_LVL_SHIFT   12
 128    #define TX_FIFO_LVL_LEN     7
 129    #define TX_FIFO_LVL         (0x7f << 12)
 130    #define PSS_GTS_USR_B       (1 << 11)
 131    #define PSS_FST_CFG_B       (1 << 10)
 132    #define PSS_CFG_RESET_B     (1 << 5)
 133
 134#define R_DMA_SRC_ADDR  (0x18/4)
 135#define R_DMA_DST_ADDR  (0x1C/4)
 136#define R_DMA_SRC_LEN   (0x20/4)
 137#define R_DMA_DST_LEN   (0x24/4)
 138#define R_ROM_SHADOW    (0x28/4)
 139#define R_SW_ID         (0x30/4)
 140#define R_UNLOCK        (0x34/4)
 141
 142#define R_UNLOCK_MAGIC 0x757BDF0D
 143
 144#define R_MCTRL         (0x80/4)
 145    #define PS_VERSION_SHIFT    28
 146    #define PS_VERSION_MASK     (0xf << PS_VERSION_SHIFT)
 147    #define PCFG_POR_B          (1 << 8)
 148    #define INT_PCAP_LPBK       (1 << 4)
 149    #define MCTRL_QEMU          (1 << 3)
 150
 151#define R_MAX (0x118/4+1)
 152
 153#define RX_FIFO_LEN 32
 154#define TX_FIFO_LEN 128
 155
 156#define DMA_COMMAND_FIFO_LEN 10
 157
 158typedef struct XilinxDevcfgDMACommand {
 159    uint32_t src_addr;
 160    uint32_t dest_addr;
 161    uint32_t src_len;
 162    uint32_t dest_len;
 163} XilinxDevcfgDMACommand;
 164
 165static const VMStateDescription vmstate_xilinx_devcfg_dma_command = {
 166    .name = "xilinx_devcfg_dma_command",
 167    .version_id = 1,
 168    .minimum_version_id = 1,
 169    .minimum_version_id_old = 1,
 170    .fields = (VMStateField[]) {
 171        VMSTATE_UINT32(src_addr, XilinxDevcfgDMACommand),
 172        VMSTATE_UINT32(dest_addr, XilinxDevcfgDMACommand),
 173        VMSTATE_UINT32(src_len, XilinxDevcfgDMACommand),
 174        VMSTATE_UINT32(dest_len, XilinxDevcfgDMACommand),
 175        VMSTATE_END_OF_LIST()
 176    }
 177};
 178
 179typedef struct XilinxDevcfg {
 180    SysBusDevice parent_obj;
 181
 182    MemoryRegion iomem;
 183    MemoryRegion *dma_mr;
 184    AddressSpace *dma_as;
 185    qemu_irq irq;
 186
 187    XilinxDevcfgDMACommand dma_command_fifo[DMA_COMMAND_FIFO_LEN];
 188    uint8_t dma_command_fifo_num;
 189
 190    uint32_t regs[R_MAX];
 191    DepRegisterInfo regs_info[R_MAX];
 192} XilinxDevcfg;
 193
 194static const VMStateDescription vmstate_xilinx_devcfg = {
 195    .name = "xilinx_devcfg",
 196    .version_id = 1,
 197    .minimum_version_id = 1,
 198    .minimum_version_id_old = 1,
 199    .fields = (VMStateField[]) {
 200        VMSTATE_STRUCT_ARRAY(dma_command_fifo, XilinxDevcfg,
 201                             DMA_COMMAND_FIFO_LEN, 0,
 202                             vmstate_xilinx_devcfg_dma_command,
 203                             XilinxDevcfgDMACommand),
 204        VMSTATE_UINT8(dma_command_fifo_num, XilinxDevcfg),
 205        VMSTATE_UINT32_ARRAY(regs, XilinxDevcfg, R_MAX),
 206        VMSTATE_END_OF_LIST()
 207    }
 208};
 209
 210static void xilinx_devcfg_update_ixr(XilinxDevcfg *s)
 211{
 212    qemu_set_irq(s->irq, !!(~s->regs[R_INT_MASK] & s->regs[R_INT_STS]));
 213}
 214
 215static void xilinx_devcfg_reset(DeviceState *dev)
 216{
 217    XilinxDevcfg *s = XILINX_DEVCFG(dev);
 218    int i;
 219
 220    for (i = 0; i < R_MAX; ++i) {
 221        dep_register_reset(&s->regs_info[i]);
 222    }
 223}
 224
 225static void xilinx_devcfg_dma_go(XilinxDevcfg *s)
 226{
 227    for (;;) {
 228        uint8_t buf[BTT_MAX];
 229        XilinxDevcfgDMACommand *dmah = s->dma_command_fifo;
 230        uint32_t btt = BTT_MAX;
 231
 232        btt = MIN(btt, dmah->src_len);
 233        if (s->regs[R_MCTRL] & INT_PCAP_LPBK) {
 234            btt = MIN(btt, dmah->dest_len);
 235        }
 236        DB_PRINT("reading %x bytes from %x\n", btt, dmah->src_addr);
 237        dma_memory_read(s->dma_as, dmah->src_addr, buf, btt);
 238        dmah->src_len -= btt;
 239        dmah->src_addr += btt;
 240        if (s->regs[R_MCTRL] & INT_PCAP_LPBK) {
 241            DB_PRINT("writing %x bytes from %x\n", btt, dmah->dest_addr);
 242            dma_memory_write(s->dma_as, dmah->dest_addr, buf, btt);
 243            dmah->dest_len -= btt;
 244            dmah->dest_addr += btt;
 245        }
 246        if (!dmah->src_len && !dmah->dest_len) {
 247            DB_PRINT("dma operation finished\n");
 248            s->regs[R_INT_STS] |= DMA_DONE_INT | DMA_P_DONE_INT;
 249            s->dma_command_fifo_num = s->dma_command_fifo_num - 1;
 250            memcpy(s->dma_command_fifo, &s->dma_command_fifo[1],
 251                   sizeof(*s->dma_command_fifo) * DMA_COMMAND_FIFO_LEN - 1);
 252        }
 253        xilinx_devcfg_update_ixr(s);
 254        if (!s->dma_command_fifo_num) { /* there is still work to do */
 255            return;
 256        }
 257    }
 258}
 259
 260static void r_ixr_post_write(DepRegisterInfo *reg, uint64_t val)
 261{
 262    XilinxDevcfg *s = XILINX_DEVCFG(reg->opaque);
 263
 264    xilinx_devcfg_update_ixr(s);
 265}
 266
 267static uint64_t r_ctrl_pre_write(DepRegisterInfo *reg, uint64_t val)
 268{
 269    XilinxDevcfg *s = XILINX_DEVCFG(reg->opaque);
 270    int i;
 271
 272    for (i = 0; i < ARRAY_SIZE(lock_ctrl_map); ++i) {
 273        if (s->regs[R_LOCK] & 1 << i) {
 274            val &= ~lock_ctrl_map[i];
 275            val |= lock_ctrl_map[i] & s->regs[R_CTRL];
 276        }
 277    }
 278    return val;
 279}
 280
 281static void r_ctrl_post_write(DepRegisterInfo *reg, uint64_t val)
 282{
 283    uint32_t aes_en = extract32(val, PCFG_AES_EN_SHIFT, PCFG_AES_EN_LEN);
 284
 285    if (aes_en != 0 && aes_en != 7) {
 286        qemu_log_mask(LOG_UNIMP, "%s: warning, aes-en bits inconsistent,"
 287                      "unimplemeneted security reset should happen!\n",
 288                      reg->prefix);
 289    }
 290}
 291
 292static void r_unlock_post_write(DepRegisterInfo *reg, uint64_t val)
 293{
 294    XilinxDevcfg *s = XILINX_DEVCFG(reg->opaque);
 295
 296    if (val == R_UNLOCK_MAGIC) {
 297        DB_PRINT("successful unlock\n");
 298    } else { /* bad unlock attempt */
 299        qemu_log_mask(LOG_GUEST_ERROR, "%s: failed unlock\n", reg->prefix);
 300        s->regs[R_CTRL] &= ~PCAP_PR;
 301        s->regs[R_CTRL] &= ~PCFG_AES_EN_MASK;
 302    }
 303}
 304
 305static uint64_t r_lock_pre_write(DepRegisterInfo *reg, uint64_t val)
 306{
 307    XilinxDevcfg *s = XILINX_DEVCFG(reg->opaque);
 308
 309    /* once bits are locked they stay locked */
 310    return s->regs[R_LOCK] | val;
 311}
 312
 313static void r_dma_dst_len_post_write(DepRegisterInfo *reg, uint64_t val)
 314{
 315    XilinxDevcfg *s = XILINX_DEVCFG(reg->opaque);
 316
 317    s->dma_command_fifo[s->dma_command_fifo_num] = (XilinxDevcfgDMACommand) {
 318            .src_addr = s->regs[R_DMA_SRC_ADDR] & ~0x3UL,
 319            .dest_addr = s->regs[R_DMA_DST_ADDR] & ~0x3UL,
 320            .src_len = s->regs[R_DMA_SRC_LEN] << 2,
 321            .dest_len = s->regs[R_DMA_DST_LEN] << 2,
 322    };
 323    s->dma_command_fifo_num++;
 324    DB_PRINT("dma transfer started; %d total transfers pending\n",
 325             s->dma_command_fifo_num);
 326    xilinx_devcfg_dma_go(s);
 327}
 328
 329static const DepRegisterAccessInfo xilinx_devcfg_regs_info[] = {
 330    {   .name = "CTRL",                 .decode.addr = R_CTRL * 4,
 331        .reset = PCAP_PR | PCAP_MODE | 0x3 << 13,
 332        .ro = 0x107f6000,
 333        .rsvd = 0x1 << 15 | 0x3 << 13,
 334        .ui1 = (DepRegisterAccessError[]) {
 335            { .mask = FORCE_RST, .reason = "PS reset not implemented" },
 336            { .mask = PCAP_MODE, .reason = "FPGA Fabric doesnt exist" },
 337            { .mask = PCFG_AES_EN_MASK, .reason = "AES not implmented" },
 338            {},
 339        },
 340        .pre_write = r_ctrl_pre_write,
 341        .post_write = r_ctrl_post_write,
 342    },
 343    {   .name = "LOCK",                 .decode.addr = R_LOCK * 4,
 344        .ro = ~ONES(5),
 345        .pre_write = r_lock_pre_write,
 346    },
 347    {   .name = "CFG",                  .decode.addr = R_CFG * 4,
 348        .reset = 1 << RFIFO_TH_SHIFT | 1 << WFIFO_TH_SHIFT | 0x8,
 349        .rsvd = 0xf,
 350        .ro = 0x00f | ~ONES(12),
 351    },
 352    {   .name = "INT_STS",              .decode.addr = R_INT_STS * 4,
 353        .w1c = ~R_INT_STS_RSVD,
 354        .reset = PSS_GTS_USR_B_INT | PSS_CFG_RESET_B_INT | WR_FIFO_LVL_INT,
 355        .ro = R_INT_STS_RSVD,
 356        .post_write = r_ixr_post_write,
 357    },
 358    {    .name = "INT_MASK",            .decode.addr = R_INT_MASK * 4,
 359        .reset = ~0,
 360        .ro = R_INT_STS_RSVD,
 361        .post_write = r_ixr_post_write,
 362    },
 363    {   .name = "STATUS",               .decode.addr = R_STATUS * 4,
 364        .reset = DMA_CMD_Q_E | PSS_GTS_USR_B | PSS_CFG_RESET_B,
 365        .ro = ~0,
 366    },
 367    {   .name = "DMA_SRC_ADDR",         .decode.addr = R_DMA_SRC_ADDR * 4, },
 368    {   .name = "DMA_DST_ADDR",         .decode.addr = R_DMA_DST_ADDR * 4, },
 369    {   .name = "DMA_SRC_LEN",          .decode.addr = R_DMA_SRC_LEN * 4,
 370        .ro = ~ONES(27) },
 371    {   .name = "DMA_DST_LEN",          .decode.addr = R_DMA_DST_LEN * 4,
 372        .ro = ~ONES(27),
 373        .post_write = r_dma_dst_len_post_write,
 374    },
 375    {   .name = "ROM_SHADOW",           .decode.addr = R_ROM_SHADOW * 4,
 376        .rsvd = ~0ull,
 377    },
 378    {   .name = "SW_ID",                .decode.addr = R_SW_ID * 4, },
 379    {   .name = "UNLOCK",               .decode.addr = R_UNLOCK * 4,
 380        .post_write = r_unlock_post_write,
 381    },
 382    {   .name = "MCTRL",                .decode.addr = R_MCTRL * 4,
 383       /* Silicon 3.0 for version field, and the mysterious reserved bit 23 */
 384       .reset = 0x2 << PS_VERSION_SHIFT | 1 << 23 | MCTRL_QEMU,
 385       /* some reserved bits are rw while others are ro */
 386       .ro = ~INT_PCAP_LPBK,
 387       .rsvd = 0x00f00303,
 388    },
 389};
 390
 391static const MemoryRegionOps devcfg_reg_ops = {
 392    .read = dep_register_read_memory_le,
 393    .write = dep_register_write_memory_le,
 394    .endianness = DEVICE_LITTLE_ENDIAN,
 395    .valid = {
 396        .min_access_size = 4,
 397        .max_access_size = 4,
 398    }
 399};
 400
 401static void xilinx_devcfg_realize(DeviceState *dev, Error **errp)
 402{
 403    XilinxDevcfg *s = XILINX_DEVCFG(dev);
 404    const char *prefix = object_get_canonical_path(OBJECT(dev));
 405    int i;
 406
 407    for (i = 0; i < ARRAY_SIZE(xilinx_devcfg_regs_info); ++i) {
 408        DepRegisterInfo *r = &s->regs_info[i];
 409
 410        *r = (DepRegisterInfo) {
 411            .data = &s->regs[
 412                    xilinx_devcfg_regs_info[i].decode.addr/4],
 413            .data_size = sizeof(uint32_t),
 414            .access = &xilinx_devcfg_regs_info[i],
 415            .debug = XILINX_DEVCFG_ERR_DEBUG,
 416            .prefix = prefix,
 417            .opaque = s,
 418        };
 419        memory_region_init_io(&r->mem, OBJECT(dev), &devcfg_reg_ops, r,
 420                              r->access->name, 4);
 421        memory_region_add_subregion(&s->iomem, r->access->decode.addr, &r->mem);
 422
 423        s->dma_as = s->dma_mr ? address_space_init_shareable(s->dma_mr, NULL)
 424                              : &address_space_memory;
 425    }
 426}
 427
 428static void xilinx_devcfg_init(Object *obj)
 429{
 430    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 431    XilinxDevcfg *s = XILINX_DEVCFG(obj);
 432
 433    sysbus_init_irq(sbd, &s->irq);
 434
 435    memory_region_init(&s->iomem, obj, "devcfg", R_MAX*4);
 436    sysbus_init_mmio(sbd, &s->iomem);
 437
 438    object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
 439                             (Object **)&s->dma_mr,
 440                             qdev_prop_allow_set_link_before_realize,
 441                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 442                             &error_abort);
 443}
 444
 445static void xilinx_devcfg_class_init(ObjectClass *klass, void *data)
 446{
 447    DeviceClass *dc = DEVICE_CLASS(klass);
 448
 449    dc->reset = xilinx_devcfg_reset;
 450    dc->vmsd = &vmstate_xilinx_devcfg;
 451    dc->realize = xilinx_devcfg_realize;
 452}
 453
 454static const TypeInfo xilinx_devcfg_info = {
 455    .name           = TYPE_XILINX_DEVCFG,
 456    .parent         = TYPE_SYS_BUS_DEVICE,
 457    .instance_size  = sizeof(XilinxDevcfg),
 458    .instance_init  = xilinx_devcfg_init,
 459    .class_init     = xilinx_devcfg_class_init,
 460};
 461
 462static void xilinx_devcfg_register_types(void)
 463{
 464    type_register_static(&xilinx_devcfg_info);
 465}
 466
 467type_init(xilinx_devcfg_register_types)
 468