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/module.h"
  13#include "qemu/error-report.h"
  14#include "hw/misc/aspeed_sdmc.h"
  15#include "hw/misc/aspeed_scu.h"
  16#include "hw/qdev-properties.h"
  17#include "migration/vmstate.h"
  18#include "qapi/error.h"
  19#include "trace.h"
  20
  21/* Protection Key Register */
  22#define R_PROT            (0x00 / 4)
  23#define   PROT_KEY_UNLOCK     0xFC600309
  24
  25/* Configuration Register */
  26#define R_CONF            (0x04 / 4)
  27
  28/* Control/Status Register #1 (ast2500) */
  29#define R_STATUS1         (0x60 / 4)
  30#define   PHY_BUSY_STATE      BIT(0)
  31#define   PHY_PLL_LOCK_STATUS BIT(4)
  32
  33#define R_ECC_TEST_CTRL   (0x70 / 4)
  34#define   ECC_TEST_FINISHED   BIT(12)
  35#define   ECC_TEST_FAIL       BIT(13)
  36
  37/*
  38 * Configuration register Ox4 (for Aspeed AST2400 SOC)
  39 *
  40 * These are for the record and future use. ASPEED_SDMC_DRAM_SIZE is
  41 * what we care about right now as it is checked by U-Boot to
  42 * determine the RAM size.
  43 */
  44
  45#define ASPEED_SDMC_RESERVED            0xFFFFF800 /* 31:11 reserved */
  46#define ASPEED_SDMC_AST2300_COMPAT      (1 << 10)
  47#define ASPEED_SDMC_SCRAMBLE_PATTERN    (1 << 9)
  48#define ASPEED_SDMC_DATA_SCRAMBLE       (1 << 8)
  49#define ASPEED_SDMC_ECC_ENABLE          (1 << 7)
  50#define ASPEED_SDMC_VGA_COMPAT          (1 << 6) /* readonly */
  51#define ASPEED_SDMC_DRAM_BANK           (1 << 5)
  52#define ASPEED_SDMC_DRAM_BURST          (1 << 4)
  53#define ASPEED_SDMC_VGA_APERTURE(x)     ((x & 0x3) << 2) /* readonly */
  54#define     ASPEED_SDMC_VGA_8MB             0x0
  55#define     ASPEED_SDMC_VGA_16MB            0x1
  56#define     ASPEED_SDMC_VGA_32MB            0x2
  57#define     ASPEED_SDMC_VGA_64MB            0x3
  58#define ASPEED_SDMC_DRAM_SIZE(x)        (x & 0x3)
  59#define     ASPEED_SDMC_DRAM_64MB           0x0
  60#define     ASPEED_SDMC_DRAM_128MB          0x1
  61#define     ASPEED_SDMC_DRAM_256MB          0x2
  62#define     ASPEED_SDMC_DRAM_512MB          0x3
  63
  64#define ASPEED_SDMC_READONLY_MASK                       \
  65    (ASPEED_SDMC_RESERVED | ASPEED_SDMC_VGA_COMPAT |    \
  66     ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
  67/*
  68 * Configuration register Ox4 (for Aspeed AST2500 SOC and higher)
  69 *
  70 * Incompatibilities are annotated in the list. ASPEED_SDMC_HW_VERSION
  71 * should be set to 1 for the AST2500 SOC.
  72 */
  73#define ASPEED_SDMC_HW_VERSION(x)       ((x & 0xf) << 28) /* readonly */
  74#define ASPEED_SDMC_SW_VERSION          ((x & 0xff) << 20)
  75#define ASPEED_SDMC_CACHE_INITIAL_DONE  (1 << 19)  /* readonly */
  76#define ASPEED_SDMC_AST2500_RESERVED    0x7C000 /* 18:14 reserved */
  77#define ASPEED_SDMC_CACHE_DDR4_CONF     (1 << 13)
  78#define ASPEED_SDMC_CACHE_INITIAL       (1 << 12)
  79#define ASPEED_SDMC_CACHE_RANGE_CTRL    (1 << 11)
  80#define ASPEED_SDMC_CACHE_ENABLE        (1 << 10) /* differs from AST2400 */
  81#define ASPEED_SDMC_DRAM_TYPE           (1 << 4)  /* differs from AST2400 */
  82
  83/* DRAM size definitions differs */
  84#define     ASPEED_SDMC_AST2500_128MB       0x0
  85#define     ASPEED_SDMC_AST2500_256MB       0x1
  86#define     ASPEED_SDMC_AST2500_512MB       0x2
  87#define     ASPEED_SDMC_AST2500_1024MB      0x3
  88
  89#define     ASPEED_SDMC_AST2600_256MB       0x0
  90#define     ASPEED_SDMC_AST2600_512MB       0x1
  91#define     ASPEED_SDMC_AST2600_1024MB      0x2
  92#define     ASPEED_SDMC_AST2600_2048MB      0x3
  93
  94#define ASPEED_SDMC_AST2500_READONLY_MASK                               \
  95    (ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE |     \
  96     ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT |            \
  97     ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB))
  98
  99static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
 100{
 101    AspeedSDMCState *s = ASPEED_SDMC(opaque);
 102
 103    addr >>= 2;
 104
 105    if (addr >= ARRAY_SIZE(s->regs)) {
 106        qemu_log_mask(LOG_GUEST_ERROR,
 107                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
 108                      __func__, addr);
 109        return 0;
 110    }
 111
 112    return s->regs[addr];
 113}
 114
 115static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
 116                             unsigned int size)
 117{
 118    AspeedSDMCState *s = ASPEED_SDMC(opaque);
 119    AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
 120
 121    addr >>= 2;
 122
 123    if (addr >= ARRAY_SIZE(s->regs)) {
 124        qemu_log_mask(LOG_GUEST_ERROR,
 125                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
 126                      __func__, addr);
 127        return;
 128    }
 129
 130    if (addr == R_PROT) {
 131        s->regs[addr] = (data == PROT_KEY_UNLOCK) ? 1 : 0;
 132        return;
 133    }
 134
 135    if (!s->regs[R_PROT]) {
 136        qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
 137        return;
 138    }
 139
 140    asc->write(s, addr, data);
 141}
 142
 143static const MemoryRegionOps aspeed_sdmc_ops = {
 144    .read = aspeed_sdmc_read,
 145    .write = aspeed_sdmc_write,
 146    .endianness = DEVICE_LITTLE_ENDIAN,
 147    .valid.min_access_size = 4,
 148    .valid.max_access_size = 4,
 149};
 150
 151static int ast2400_rambits(AspeedSDMCState *s)
 152{
 153    switch (s->ram_size >> 20) {
 154    case 64:
 155        return ASPEED_SDMC_DRAM_64MB;
 156    case 128:
 157        return ASPEED_SDMC_DRAM_128MB;
 158    case 256:
 159        return ASPEED_SDMC_DRAM_256MB;
 160    case 512:
 161        return ASPEED_SDMC_DRAM_512MB;
 162    default:
 163        break;
 164    }
 165
 166    /* use a common default */
 167    warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 256M",
 168                s->ram_size);
 169    s->ram_size = 256 << 20;
 170    return ASPEED_SDMC_DRAM_256MB;
 171}
 172
 173static int ast2500_rambits(AspeedSDMCState *s)
 174{
 175    switch (s->ram_size >> 20) {
 176    case 128:
 177        return ASPEED_SDMC_AST2500_128MB;
 178    case 256:
 179        return ASPEED_SDMC_AST2500_256MB;
 180    case 512:
 181        return ASPEED_SDMC_AST2500_512MB;
 182    case 1024:
 183        return ASPEED_SDMC_AST2500_1024MB;
 184    default:
 185        break;
 186    }
 187
 188    /* use a common default */
 189    warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 512M",
 190                s->ram_size);
 191    s->ram_size = 512 << 20;
 192    return ASPEED_SDMC_AST2500_512MB;
 193}
 194
 195static int ast2600_rambits(AspeedSDMCState *s)
 196{
 197    switch (s->ram_size >> 20) {
 198    case 256:
 199        return ASPEED_SDMC_AST2600_256MB;
 200    case 512:
 201        return ASPEED_SDMC_AST2600_512MB;
 202    case 1024:
 203        return ASPEED_SDMC_AST2600_1024MB;
 204    case 2048:
 205        return ASPEED_SDMC_AST2600_2048MB;
 206    default:
 207        break;
 208    }
 209
 210    /* use a common default */
 211    warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 512M",
 212                s->ram_size);
 213    s->ram_size = 512 << 20;
 214    return ASPEED_SDMC_AST2600_512MB;
 215}
 216
 217static void aspeed_sdmc_reset(DeviceState *dev)
 218{
 219    AspeedSDMCState *s = ASPEED_SDMC(dev);
 220    AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
 221
 222    memset(s->regs, 0, sizeof(s->regs));
 223
 224    /* Set ram size bit and defaults values */
 225    s->regs[R_CONF] = asc->compute_conf(s, 0);
 226}
 227
 228static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
 229{
 230    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 231    AspeedSDMCState *s = ASPEED_SDMC(dev);
 232    AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
 233
 234    s->max_ram_size = asc->max_ram_size;
 235
 236    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
 237                          TYPE_ASPEED_SDMC, 0x1000);
 238    sysbus_init_mmio(sbd, &s->iomem);
 239}
 240
 241static const VMStateDescription vmstate_aspeed_sdmc = {
 242    .name = "aspeed.sdmc",
 243    .version_id = 1,
 244    .minimum_version_id = 1,
 245    .fields = (VMStateField[]) {
 246        VMSTATE_UINT32_ARRAY(regs, AspeedSDMCState, ASPEED_SDMC_NR_REGS),
 247        VMSTATE_END_OF_LIST()
 248    }
 249};
 250
 251static Property aspeed_sdmc_properties[] = {
 252    DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
 253    DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0),
 254    DEFINE_PROP_END_OF_LIST(),
 255};
 256
 257static void aspeed_sdmc_class_init(ObjectClass *klass, void *data)
 258{
 259    DeviceClass *dc = DEVICE_CLASS(klass);
 260    dc->realize = aspeed_sdmc_realize;
 261    dc->reset = aspeed_sdmc_reset;
 262    dc->desc = "ASPEED SDRAM Memory Controller";
 263    dc->vmsd = &vmstate_aspeed_sdmc;
 264    dc->props = aspeed_sdmc_properties;
 265}
 266
 267static const TypeInfo aspeed_sdmc_info = {
 268    .name = TYPE_ASPEED_SDMC,
 269    .parent = TYPE_SYS_BUS_DEVICE,
 270    .instance_size = sizeof(AspeedSDMCState),
 271    .class_init = aspeed_sdmc_class_init,
 272    .class_size = sizeof(AspeedSDMCClass),
 273    .abstract   = true,
 274};
 275
 276static uint32_t aspeed_2400_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
 277{
 278    uint32_t fixed_conf = ASPEED_SDMC_VGA_COMPAT |
 279        ASPEED_SDMC_DRAM_SIZE(ast2400_rambits(s));
 280
 281    /* Make sure readonly bits are kept */
 282    data &= ~ASPEED_SDMC_READONLY_MASK;
 283
 284    return data | fixed_conf;
 285}
 286
 287static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
 288                                   uint32_t data)
 289{
 290    switch (reg) {
 291    case R_CONF:
 292        data = aspeed_2400_sdmc_compute_conf(s, data);
 293        break;
 294    default:
 295        break;
 296    }
 297
 298    s->regs[reg] = data;
 299}
 300
 301static void aspeed_2400_sdmc_class_init(ObjectClass *klass, void *data)
 302{
 303    DeviceClass *dc = DEVICE_CLASS(klass);
 304    AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
 305
 306    dc->desc = "ASPEED 2400 SDRAM Memory Controller";
 307    asc->max_ram_size = 512 << 20;
 308    asc->compute_conf = aspeed_2400_sdmc_compute_conf;
 309    asc->write = aspeed_2400_sdmc_write;
 310}
 311
 312static const TypeInfo aspeed_2400_sdmc_info = {
 313    .name = TYPE_ASPEED_2400_SDMC,
 314    .parent = TYPE_ASPEED_SDMC,
 315    .class_init = aspeed_2400_sdmc_class_init,
 316};
 317
 318static uint32_t aspeed_2500_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
 319{
 320    uint32_t fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
 321        ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
 322        ASPEED_SDMC_CACHE_INITIAL_DONE |
 323        ASPEED_SDMC_DRAM_SIZE(ast2500_rambits(s));
 324
 325    /* Make sure readonly bits are kept */
 326    data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
 327
 328    return data | fixed_conf;
 329}
 330
 331static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
 332                                   uint32_t data)
 333{
 334    switch (reg) {
 335    case R_CONF:
 336        data = aspeed_2500_sdmc_compute_conf(s, data);
 337        break;
 338    case R_STATUS1:
 339        /* Will never return 'busy' */
 340        data &= ~PHY_BUSY_STATE;
 341        break;
 342    case R_ECC_TEST_CTRL:
 343        /* Always done, always happy */
 344        data |= ECC_TEST_FINISHED;
 345        data &= ~ECC_TEST_FAIL;
 346        break;
 347    default:
 348        break;
 349    }
 350
 351    s->regs[reg] = data;
 352}
 353
 354static void aspeed_2500_sdmc_class_init(ObjectClass *klass, void *data)
 355{
 356    DeviceClass *dc = DEVICE_CLASS(klass);
 357    AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
 358
 359    dc->desc = "ASPEED 2500 SDRAM Memory Controller";
 360    asc->max_ram_size = 1024 << 20;
 361    asc->compute_conf = aspeed_2500_sdmc_compute_conf;
 362    asc->write = aspeed_2500_sdmc_write;
 363}
 364
 365static const TypeInfo aspeed_2500_sdmc_info = {
 366    .name = TYPE_ASPEED_2500_SDMC,
 367    .parent = TYPE_ASPEED_SDMC,
 368    .class_init = aspeed_2500_sdmc_class_init,
 369};
 370
 371static uint32_t aspeed_2600_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
 372{
 373    uint32_t fixed_conf = ASPEED_SDMC_HW_VERSION(3) |
 374        ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
 375        ASPEED_SDMC_DRAM_SIZE(ast2600_rambits(s));
 376
 377    /* Make sure readonly bits are kept (use ast2500 mask) */
 378    data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
 379
 380    return data | fixed_conf;
 381}
 382
 383static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
 384                                   uint32_t data)
 385{
 386    switch (reg) {
 387    case R_CONF:
 388        data = aspeed_2600_sdmc_compute_conf(s, data);
 389        break;
 390    case R_STATUS1:
 391        /* Will never return 'busy'. 'lock status' is always set */
 392        data &= ~PHY_BUSY_STATE;
 393        data |= PHY_PLL_LOCK_STATUS;
 394        break;
 395    case R_ECC_TEST_CTRL:
 396        /* Always done, always happy */
 397        data |= ECC_TEST_FINISHED;
 398        data &= ~ECC_TEST_FAIL;
 399        break;
 400    default:
 401        break;
 402    }
 403
 404    s->regs[reg] = data;
 405}
 406
 407static void aspeed_2600_sdmc_class_init(ObjectClass *klass, void *data)
 408{
 409    DeviceClass *dc = DEVICE_CLASS(klass);
 410    AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
 411
 412    dc->desc = "ASPEED 2600 SDRAM Memory Controller";
 413    asc->max_ram_size = 2048 << 20;
 414    asc->compute_conf = aspeed_2600_sdmc_compute_conf;
 415    asc->write = aspeed_2600_sdmc_write;
 416}
 417
 418static const TypeInfo aspeed_2600_sdmc_info = {
 419    .name = TYPE_ASPEED_2600_SDMC,
 420    .parent = TYPE_ASPEED_SDMC,
 421    .class_init = aspeed_2600_sdmc_class_init,
 422};
 423
 424static void aspeed_sdmc_register_types(void)
 425{
 426    type_register_static(&aspeed_sdmc_info);
 427    type_register_static(&aspeed_2400_sdmc_info);
 428    type_register_static(&aspeed_2500_sdmc_info);
 429    type_register_static(&aspeed_2600_sdmc_info);
 430}
 431
 432type_init(aspeed_sdmc_register_types);
 433