qemu/hw/misc/mips_cmgcr.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
   7 * Authors: Sanjay Lal <sanjayl@kymasys.com>
   8 *
   9 * Copyright (C) 2015 Imagination Technologies
  10 */
  11
  12#include "qemu/osdep.h"
  13#include "qapi/error.h"
  14#include "hw/hw.h"
  15#include "hw/sysbus.h"
  16#include "sysemu/sysemu.h"
  17#include "hw/misc/mips_cmgcr.h"
  18#include "hw/misc/mips_cpc.h"
  19
  20static inline bool is_cpc_connected(MIPSGCRState *s)
  21{
  22    return s->cpc_mr != NULL;
  23}
  24
  25static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val)
  26{
  27    if (is_cpc_connected(gcr)) {
  28        gcr->cpc_base = val & GCR_CPC_BASE_MSK;
  29        memory_region_transaction_begin();
  30        memory_region_set_address(gcr->cpc_mr,
  31                                  gcr->cpc_base & GCR_CPC_BASE_CPCBASE_MSK);
  32        memory_region_set_enabled(gcr->cpc_mr,
  33                                  gcr->cpc_base & GCR_CPC_BASE_CPCEN_MSK);
  34        memory_region_transaction_commit();
  35    }
  36}
  37
  38/* Read GCR registers */
  39static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
  40{
  41    MIPSGCRState *gcr = (MIPSGCRState *) opaque;
  42
  43    switch (addr) {
  44    /* Global Control Block Register */
  45    case GCR_CONFIG_OFS:
  46        /* Set PCORES to 0 */
  47        return 0;
  48    case GCR_BASE_OFS:
  49        return gcr->gcr_base;
  50    case GCR_REV_OFS:
  51        return gcr->gcr_rev;
  52    case GCR_CPC_BASE_OFS:
  53        return gcr->cpc_base;
  54    case GCR_CPC_STATUS_OFS:
  55        return is_cpc_connected(gcr);
  56    case GCR_L2_CONFIG_OFS:
  57        /* L2 BYPASS */
  58        return GCR_L2_CONFIG_BYPASS_MSK;
  59        /* Core-Local and Core-Other Control Blocks */
  60    case MIPS_CLCB_OFS + GCR_CL_CONFIG_OFS:
  61    case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS:
  62        /* Set PVP to # of VPs - 1 */
  63        return gcr->num_vps - 1;
  64    case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
  65        return 0;
  66    default:
  67        qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx
  68                      "\n", size, addr);
  69        return 0;
  70    }
  71    return 0;
  72}
  73
  74/* Write GCR registers */
  75static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
  76{
  77    MIPSGCRState *gcr = (MIPSGCRState *)opaque;
  78
  79    switch (addr) {
  80    case GCR_CPC_BASE_OFS:
  81        update_cpc_base(gcr, data);
  82        break;
  83    default:
  84        qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx
  85                      " 0x%" PRIx64 "\n", size, addr, data);
  86        break;
  87    }
  88}
  89
  90static const MemoryRegionOps gcr_ops = {
  91    .read = gcr_read,
  92    .write = gcr_write,
  93    .endianness = DEVICE_NATIVE_ENDIAN,
  94    .impl = {
  95        .max_access_size = 8,
  96    },
  97};
  98
  99static void mips_gcr_init(Object *obj)
 100{
 101    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 102    MIPSGCRState *s = MIPS_GCR(obj);
 103
 104    object_property_add_link(obj, "cpc", TYPE_MEMORY_REGION,
 105                             (Object **)&s->cpc_mr,
 106                             qdev_prop_allow_set_link_before_realize,
 107                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 108                             &error_abort);
 109
 110    memory_region_init_io(&s->iomem, OBJECT(s), &gcr_ops, s,
 111                          "mips-gcr", GCR_ADDRSPACE_SZ);
 112    sysbus_init_mmio(sbd, &s->iomem);
 113}
 114
 115static void mips_gcr_reset(DeviceState *dev)
 116{
 117    MIPSGCRState *s = MIPS_GCR(dev);
 118
 119    update_cpc_base(s, 0);
 120}
 121
 122static const VMStateDescription vmstate_mips_gcr = {
 123    .name = "mips-gcr",
 124    .version_id = 0,
 125    .minimum_version_id = 0,
 126    .fields = (VMStateField[]) {
 127        VMSTATE_UINT64(cpc_base, MIPSGCRState),
 128        VMSTATE_END_OF_LIST()
 129    },
 130};
 131
 132static Property mips_gcr_properties[] = {
 133    DEFINE_PROP_INT32("num-vp", MIPSGCRState, num_vps, 1),
 134    DEFINE_PROP_INT32("gcr-rev", MIPSGCRState, gcr_rev, 0x800),
 135    DEFINE_PROP_UINT64("gcr-base", MIPSGCRState, gcr_base, GCR_BASE_ADDR),
 136    DEFINE_PROP_END_OF_LIST(),
 137};
 138
 139static void mips_gcr_class_init(ObjectClass *klass, void *data)
 140{
 141    DeviceClass *dc = DEVICE_CLASS(klass);
 142    dc->props = mips_gcr_properties;
 143    dc->vmsd = &vmstate_mips_gcr;
 144    dc->reset = mips_gcr_reset;
 145}
 146
 147static const TypeInfo mips_gcr_info = {
 148    .name          = TYPE_MIPS_GCR,
 149    .parent        = TYPE_SYS_BUS_DEVICE,
 150    .instance_size = sizeof(MIPSGCRState),
 151    .instance_init = mips_gcr_init,
 152    .class_init    = mips_gcr_class_init,
 153};
 154
 155static void mips_gcr_register_types(void)
 156{
 157    type_register_static(&mips_gcr_info);
 158}
 159
 160type_init(mips_gcr_register_types)
 161