qemu/hw/misc/aspeed_sdmc.c
<<
>>
Prefs
   1/*
   2 * ASPEED SDRAM Memory Controller
   3 *
   4 * Copyright (C) 2016 IBM Corp.
   5 *
   6 * This code is licensed under the GPL version 2 or later.  See
   7 * the COPYING file in the top-level directory.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "qemu/log.h"
  12#include "qemu/error-report.h"
  13#include "hw/misc/aspeed_sdmc.h"
  14#include "hw/misc/aspeed_scu.h"
  15#include "hw/qdev-properties.h"
  16#include "qapi/error.h"
  17#include "trace.h"
  18
  19/* Protection Key Register */
  20#define R_PROT            (0x00 / 4)
  21#define   PROT_KEY_UNLOCK     0xFC600309
  22
  23/* Configuration Register */
  24#define R_CONF            (0x04 / 4)
  25
  26/*
  27 * Configuration register Ox4 (for Aspeed AST2400 SOC)
  28 *
  29 * These are for the record and future use. ASPEED_SDMC_DRAM_SIZE is
  30 * what we care about right now as it is checked by U-Boot to
  31 * determine the RAM size.
  32 */
  33
  34#define ASPEED_SDMC_RESERVED            0xFFFFF800 /* 31:11 reserved */
  35#define ASPEED_SDMC_AST2300_COMPAT      (1 << 10)
  36#define ASPEED_SDMC_SCRAMBLE_PATTERN    (1 << 9)
  37#define ASPEED_SDMC_DATA_SCRAMBLE       (1 << 8)
  38#define ASPEED_SDMC_ECC_ENABLE          (1 << 7)
  39#define ASPEED_SDMC_VGA_COMPAT          (1 << 6) /* readonly */
  40#define ASPEED_SDMC_DRAM_BANK           (1 << 5)
  41#define ASPEED_SDMC_DRAM_BURST          (1 << 4)
  42#define ASPEED_SDMC_VGA_APERTURE(x)     ((x & 0x3) << 2) /* readonly */
  43#define     ASPEED_SDMC_VGA_8MB             0x0
  44#define     ASPEED_SDMC_VGA_16MB            0x1
  45#define     ASPEED_SDMC_VGA_32MB            0x2
  46#define     ASPEED_SDMC_VGA_64MB            0x3
  47#define ASPEED_SDMC_DRAM_SIZE(x)        (x & 0x3)
  48#define     ASPEED_SDMC_DRAM_64MB           0x0
  49#define     ASPEED_SDMC_DRAM_128MB          0x1
  50#define     ASPEED_SDMC_DRAM_256MB          0x2
  51#define     ASPEED_SDMC_DRAM_512MB          0x3
  52
  53#define ASPEED_SDMC_READONLY_MASK                       \
  54    (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT |    \
  55     ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
  56/*
  57 * Configuration register Ox4 (for Aspeed AST2500 SOC and higher)
  58 *
  59 * Incompatibilities are annotated in the list. ASPEED_SDMC_HW_VERSION
  60 * should be set to 1 for the AST2500 SOC.
  61 */
  62#define ASPEED_SDMC_HW_VERSION(x)       ((x & 0xf) << 28) /* readonly */
  63#define ASPEED_SDMC_SW_VERSION          ((x & 0xff) << 20)
  64#define ASPEED_SDMC_CACHE_INITIAL_DONE  (1 << 19)  /* readonly */
  65#define ASPEED_SDMC_AST2500_RESERVED    0x7C000 /* 18:14 reserved */
  66#define ASPEED_SDMC_CACHE_DDR4_CONF     (1 << 13)
  67#define ASPEED_SDMC_CACHE_INITIAL       (1 << 12)
  68#define ASPEED_SDMC_CACHE_RANGE_CTRL    (1 << 11)
  69#define ASPEED_SDMC_CACHE_ENABLE        (1 << 10) /* differs from AST2400 */
  70#define ASPEED_SDMC_DRAM_TYPE           (1 << 4)  /* differs from AST2400 */
  71
  72/* DRAM size definitions differs */
  73#define     ASPEED_SDMC_AST2500_128MB       0x0
  74#define     ASPEED_SDMC_AST2500_256MB       0x1
  75#define     ASPEED_SDMC_AST2500_512MB       0x2
  76#define     ASPEED_SDMC_AST2500_1024MB      0x3
  77
  78#define ASPEED_SDMC_AST2500_READONLY_MASK                               \
  79    (ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE |     \
  80     ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT |            \
  81     ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
  82
  83static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
  84{
  85    AspeedSDMCState *s = ASPEED_SDMC(opaque);
  86
  87    addr >>= 2;
  88
  89    if (addr >= ARRAY_SIZE(s->regs)) {
  90        qemu_log_mask(LOG_GUEST_ERROR,
  91                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
  92                      __func__, addr);
  93        return 0;
  94    }
  95
  96    return s->regs[addr];
  97}
  98
  99static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
 100                             unsigned int size)
 101{
 102    AspeedSDMCState *s = ASPEED_SDMC(opaque);
 103
 104    addr >>= 2;
 105
 106    if (addr >= ARRAY_SIZE(s->regs)) {
 107        qemu_log_mask(LOG_GUEST_ERROR,
 108                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
 109                      __func__, addr);
 110        return;
 111    }
 112
 113    if (addr == R_PROT) {
 114        s->regs[addr] = (data == PROT_KEY_UNLOCK) ? 1 : 0;
 115        return;
 116    }
 117
 118    if (!s->regs[R_PROT]) {
 119        qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
 120        return;
 121    }
 122
 123    if (addr == R_CONF) {
 124        /* Make sure readonly bits are kept */
 125        switch (s->silicon_rev) {
 126        case AST2400_A0_SILICON_REV:
 127        case AST2400_A1_SILICON_REV:
 128            data &= ~ASPEED_SDMC_READONLY_MASK;
 129            break;
 130        case AST2500_A0_SILICON_REV:
 131        case AST2500_A1_SILICON_REV:
 132            data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
 133            break;
 134        default:
 135            g_assert_not_reached();
 136        }
 137    }
 138
 139    s->regs[addr] = data;
 140}
 141
 142static const MemoryRegionOps aspeed_sdmc_ops = {
 143    .read = aspeed_sdmc_read,
 144    .write = aspeed_sdmc_write,
 145    .endianness = DEVICE_LITTLE_ENDIAN,
 146    .valid.min_access_size = 4,
 147    .valid.max_access_size = 4,
 148};
 149
 150static int ast2400_rambits(AspeedSDMCState *s)
 151{
 152    switch (s->ram_size >> 20) {
 153    case 64:
 154        return ASPEED_SDMC_DRAM_64MB;
 155    case 128:
 156        return ASPEED_SDMC_DRAM_128MB;
 157    case 256:
 158        return ASPEED_SDMC_DRAM_256MB;
 159    case 512:
 160        return ASPEED_SDMC_DRAM_512MB;
 161    default:
 162        break;
 163    }
 164
 165    /* use a common default */
 166    warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 256M",
 167                s->ram_size);
 168    s->ram_size = 256 << 20;
 169    return ASPEED_SDMC_DRAM_256MB;
 170}
 171
 172static int ast2500_rambits(AspeedSDMCState *s)
 173{
 174    switch (s->ram_size >> 20) {
 175    case 128:
 176        return ASPEED_SDMC_AST2500_128MB;
 177    case 256:
 178        return ASPEED_SDMC_AST2500_256MB;
 179    case 512:
 180        return ASPEED_SDMC_AST2500_512MB;
 181    case 1024:
 182        return ASPEED_SDMC_AST2500_1024MB;
 183    default:
 184        break;
 185    }
 186
 187    /* use a common default */
 188    warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 512M",
 189                s->ram_size);
 190    s->ram_size = 512 << 20;
 191    return ASPEED_SDMC_AST2500_512MB;
 192}
 193
 194static void aspeed_sdmc_reset(DeviceState *dev)
 195{
 196    AspeedSDMCState *s = ASPEED_SDMC(dev);
 197
 198    memset(s->regs, 0, sizeof(s->regs));
 199
 200    /* Set ram size bit and defaults values */
 201    switch (s->silicon_rev) {
 202    case AST2400_A0_SILICON_REV:
 203    case AST2400_A1_SILICON_REV:
 204        s->regs[R_CONF] |=
 205            ASPEED_SDMC_VGA_COMPAT |
 206            ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
 207        break;
 208
 209    case AST2500_A0_SILICON_REV:
 210    case AST2500_A1_SILICON_REV:
 211        s->regs[R_CONF] |=
 212            ASPEED_SDMC_HW_VERSION(1) |
 213            ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
 214            ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
 215        break;
 216
 217    default:
 218        g_assert_not_reached();
 219    }
 220}
 221
 222static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
 223{
 224    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 225    AspeedSDMCState *s = ASPEED_SDMC(dev);
 226
 227    if (!is_supported_silicon_rev(s->silicon_rev)) {
 228        error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
 229                s->silicon_rev);
 230        return;
 231    }
 232
 233    switch (s->silicon_rev) {
 234    case AST2400_A0_SILICON_REV:
 235    case AST2400_A1_SILICON_REV:
 236        s->ram_bits = ast2400_rambits(s);
 237        break;
 238    case AST2500_A0_SILICON_REV:
 239    case AST2500_A1_SILICON_REV:
 240        s->ram_bits = ast2500_rambits(s);
 241        break;
 242    default:
 243        g_assert_not_reached();
 244    }
 245
 246    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
 247                          TYPE_ASPEED_SDMC, 0x1000);
 248    sysbus_init_mmio(sbd, &s->iomem);
 249}
 250
 251static const VMStateDescription vmstate_aspeed_sdmc = {
 252    .name = "aspeed.sdmc",
 253    .version_id = 1,
 254    .minimum_version_id = 1,
 255    .fields = (VMStateField[]) {
 256        VMSTATE_UINT32_ARRAY(regs, AspeedSDMCState, ASPEED_SDMC_NR_REGS),
 257        VMSTATE_END_OF_LIST()
 258    }
 259};
 260
 261static Property aspeed_sdmc_properties[] = {
 262    DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
 263    DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
 264    DEFINE_PROP_END_OF_LIST(),
 265};
 266
 267static void aspeed_sdmc_class_init(ObjectClass *klass, void *data)
 268{
 269    DeviceClass *dc = DEVICE_CLASS(klass);
 270    dc->realize = aspeed_sdmc_realize;
 271    dc->reset = aspeed_sdmc_reset;
 272    dc->desc = "ASPEED SDRAM Memory Controller";
 273    dc->vmsd = &vmstate_aspeed_sdmc;
 274    dc->props = aspeed_sdmc_properties;
 275}
 276
 277static const TypeInfo aspeed_sdmc_info = {
 278    .name = TYPE_ASPEED_SDMC,
 279    .parent = TYPE_SYS_BUS_DEVICE,
 280    .instance_size = sizeof(AspeedSDMCState),
 281    .class_init = aspeed_sdmc_class_init,
 282};
 283
 284static void aspeed_sdmc_register_types(void)
 285{
 286    type_register_static(&aspeed_sdmc_info);
 287}
 288
 289type_init(aspeed_sdmc_register_types);
 290