qemu/hw/arm/aspeed_soc.c
<<
>>
Prefs
   1/*
   2 * ASPEED SoC family
   3 *
   4 * Andrew Jeffery <andrew@aj.id.au>
   5 * Jeremy Kerr <jk@ozlabs.org>
   6 *
   7 * Copyright 2016 IBM Corp.
   8 *
   9 * This code is licensed under the GPL version 2 or later.  See
  10 * the COPYING file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "qapi/error.h"
  15#include "qemu-common.h"
  16#include "cpu.h"
  17#include "exec/address-spaces.h"
  18#include "hw/arm/aspeed_soc.h"
  19#include "hw/char/serial.h"
  20#include "qemu/log.h"
  21#include "hw/i2c/aspeed_i2c.h"
  22
  23#define ASPEED_SOC_UART_5_BASE      0x00184000
  24#define ASPEED_SOC_IOMEM_SIZE       0x00200000
  25#define ASPEED_SOC_IOMEM_BASE       0x1E600000
  26#define ASPEED_SOC_FMC_BASE         0x1E620000
  27#define ASPEED_SOC_SPI_BASE         0x1E630000
  28#define ASPEED_SOC_SPI2_BASE        0x1E631000
  29#define ASPEED_SOC_VIC_BASE         0x1E6C0000
  30#define ASPEED_SOC_SDMC_BASE        0x1E6E0000
  31#define ASPEED_SOC_SCU_BASE         0x1E6E2000
  32#define ASPEED_SOC_SRAM_BASE        0x1E720000
  33#define ASPEED_SOC_TIMER_BASE       0x1E782000
  34#define ASPEED_SOC_WDT_BASE         0x1E785000
  35#define ASPEED_SOC_I2C_BASE         0x1E78A000
  36
  37static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
  38static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
  39
  40#define AST2400_SDRAM_BASE       0x40000000
  41#define AST2500_SDRAM_BASE       0x80000000
  42
  43static const hwaddr aspeed_soc_ast2400_spi_bases[] = { ASPEED_SOC_SPI_BASE };
  44static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" };
  45
  46static const hwaddr aspeed_soc_ast2500_spi_bases[] = { ASPEED_SOC_SPI_BASE,
  47                                                       ASPEED_SOC_SPI2_BASE};
  48static const char *aspeed_soc_ast2500_typenames[] = {
  49    "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
  50
  51static const AspeedSoCInfo aspeed_socs[] = {
  52    {
  53        .name         = "ast2400-a0",
  54        .cpu_model    = "arm926",
  55        .silicon_rev  = AST2400_A0_SILICON_REV,
  56        .sdram_base   = AST2400_SDRAM_BASE,
  57        .sram_size    = 0x8000,
  58        .spis_num     = 1,
  59        .spi_bases    = aspeed_soc_ast2400_spi_bases,
  60        .fmc_typename = "aspeed.smc.fmc",
  61        .spi_typename = aspeed_soc_ast2400_typenames,
  62    }, {
  63        .name         = "ast2400-a1",
  64        .cpu_model    = "arm926",
  65        .silicon_rev  = AST2400_A1_SILICON_REV,
  66        .sdram_base   = AST2400_SDRAM_BASE,
  67        .sram_size    = 0x8000,
  68        .spis_num     = 1,
  69        .spi_bases    = aspeed_soc_ast2400_spi_bases,
  70        .fmc_typename = "aspeed.smc.fmc",
  71        .spi_typename = aspeed_soc_ast2400_typenames,
  72    }, {
  73        .name         = "ast2400",
  74        .cpu_model    = "arm926",
  75        .silicon_rev  = AST2400_A0_SILICON_REV,
  76        .sdram_base   = AST2400_SDRAM_BASE,
  77        .sram_size    = 0x8000,
  78        .spis_num     = 1,
  79        .spi_bases    = aspeed_soc_ast2400_spi_bases,
  80        .fmc_typename = "aspeed.smc.fmc",
  81        .spi_typename = aspeed_soc_ast2400_typenames,
  82    }, {
  83        .name         = "ast2500-a1",
  84        .cpu_model    = "arm1176",
  85        .silicon_rev  = AST2500_A1_SILICON_REV,
  86        .sdram_base   = AST2500_SDRAM_BASE,
  87        .sram_size    = 0x9000,
  88        .spis_num     = 2,
  89        .spi_bases    = aspeed_soc_ast2500_spi_bases,
  90        .fmc_typename = "aspeed.smc.ast2500-fmc",
  91        .spi_typename = aspeed_soc_ast2500_typenames,
  92    },
  93};
  94
  95/*
  96 * IO handlers: simply catch any reads/writes to IO addresses that aren't
  97 * handled by a device mapping.
  98 */
  99
 100static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
 101{
 102    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
 103                  __func__, offset, size);
 104    return 0;
 105}
 106
 107static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
 108                unsigned size)
 109{
 110    qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
 111                  __func__, offset, value, size);
 112}
 113
 114static const MemoryRegionOps aspeed_soc_io_ops = {
 115    .read = aspeed_soc_io_read,
 116    .write = aspeed_soc_io_write,
 117    .endianness = DEVICE_LITTLE_ENDIAN,
 118};
 119
 120static void aspeed_soc_init(Object *obj)
 121{
 122    AspeedSoCState *s = ASPEED_SOC(obj);
 123    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 124    char *cpu_typename;
 125    int i;
 126
 127    cpu_typename = g_strdup_printf("%s-" TYPE_ARM_CPU, sc->info->cpu_model);
 128    object_initialize(&s->cpu, sizeof(s->cpu), cpu_typename);
 129    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
 130    g_free(cpu_typename);
 131
 132    object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
 133    object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
 134    qdev_set_parent_bus(DEVICE(&s->vic), sysbus_get_default());
 135
 136    object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
 137    object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
 138    qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
 139
 140    object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
 141    object_property_add_child(obj, "i2c", OBJECT(&s->i2c), NULL);
 142    qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default());
 143
 144    object_initialize(&s->scu, sizeof(s->scu), TYPE_ASPEED_SCU);
 145    object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
 146    qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
 147    qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
 148                         sc->info->silicon_rev);
 149    object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
 150                              "hw-strap1", &error_abort);
 151    object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
 152                              "hw-strap2", &error_abort);
 153
 154    object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
 155    object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
 156    qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default());
 157    object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
 158                              &error_abort);
 159
 160    for (i = 0; i < sc->info->spis_num; i++) {
 161        object_initialize(&s->spi[i], sizeof(s->spi[i]),
 162                          sc->info->spi_typename[i]);
 163        object_property_add_child(obj, "spi[*]", OBJECT(&s->spi[i]), NULL);
 164        qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
 165    }
 166
 167    object_initialize(&s->sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC);
 168    object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
 169    qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default());
 170    qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
 171                         sc->info->silicon_rev);
 172    object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
 173                              "ram-size", &error_abort);
 174
 175    object_initialize(&s->wdt, sizeof(s->wdt), TYPE_ASPEED_WDT);
 176    object_property_add_child(obj, "wdt", OBJECT(&s->wdt), NULL);
 177    qdev_set_parent_bus(DEVICE(&s->wdt), sysbus_get_default());
 178}
 179
 180static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 181{
 182    int i;
 183    AspeedSoCState *s = ASPEED_SOC(dev);
 184    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 185    Error *err = NULL, *local_err = NULL;
 186
 187    /* IO space */
 188    memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
 189            "aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
 190    memory_region_add_subregion_overlap(get_system_memory(),
 191                                        ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
 192
 193    /* CPU */
 194    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
 195    if (err) {
 196        error_propagate(errp, err);
 197        return;
 198    }
 199
 200    /* SRAM */
 201    memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
 202                           sc->info->sram_size, &err);
 203    if (err) {
 204        error_propagate(errp, err);
 205        return;
 206    }
 207    vmstate_register_ram_global(&s->sram);
 208    memory_region_add_subregion(get_system_memory(), ASPEED_SOC_SRAM_BASE,
 209                                &s->sram);
 210
 211    /* VIC */
 212    object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
 213    if (err) {
 214        error_propagate(errp, err);
 215        return;
 216    }
 217    sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
 218    sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
 219                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
 220    sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
 221                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
 222
 223    /* Timer */
 224    object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
 225    if (err) {
 226        error_propagate(errp, err);
 227        return;
 228    }
 229    sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, ASPEED_SOC_TIMER_BASE);
 230    for (i = 0; i < ARRAY_SIZE(timer_irqs); i++) {
 231        qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->vic), timer_irqs[i]);
 232        sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
 233    }
 234
 235    /* SCU */
 236    object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
 237    if (err) {
 238        error_propagate(errp, err);
 239        return;
 240    }
 241    sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
 242
 243    /* UART - attach an 8250 to the IO space as our UART5 */
 244    if (serial_hds[0]) {
 245        qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
 246        serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
 247                       uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
 248    }
 249
 250    /* I2C */
 251    object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err);
 252    if (err) {
 253        error_propagate(errp, err);
 254        return;
 255    }
 256    sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, ASPEED_SOC_I2C_BASE);
 257    sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
 258                       qdev_get_gpio_in(DEVICE(&s->vic), 12));
 259
 260    /* FMC, The number of CS is set at the board level */
 261    object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err);
 262    if (err) {
 263        error_propagate(errp, err);
 264        return;
 265    }
 266    sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, ASPEED_SOC_FMC_BASE);
 267    sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1,
 268                    s->fmc.ctrl->flash_window_base);
 269    sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
 270                       qdev_get_gpio_in(DEVICE(&s->vic), 19));
 271
 272    /* SPI */
 273    for (i = 0; i < sc->info->spis_num; i++) {
 274        object_property_set_int(OBJECT(&s->spi[i]), 1, "num-cs", &err);
 275        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
 276                                 &local_err);
 277        error_propagate(&err, local_err);
 278        if (err) {
 279            error_propagate(errp, err);
 280            return;
 281        }
 282        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, sc->info->spi_bases[i]);
 283        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1,
 284                        s->spi[i].ctrl->flash_window_base);
 285    }
 286
 287    /* SDMC - SDRAM Memory Controller */
 288    object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
 289    if (err) {
 290        error_propagate(errp, err);
 291        return;
 292    }
 293    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
 294
 295    /* Watch dog */
 296    object_property_set_bool(OBJECT(&s->wdt), true, "realized", &err);
 297    if (err) {
 298        error_propagate(errp, err);
 299        return;
 300    }
 301    sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, ASPEED_SOC_WDT_BASE);
 302}
 303
 304static void aspeed_soc_class_init(ObjectClass *oc, void *data)
 305{
 306    DeviceClass *dc = DEVICE_CLASS(oc);
 307    AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
 308
 309    sc->info = (AspeedSoCInfo *) data;
 310    dc->realize = aspeed_soc_realize;
 311}
 312
 313static const TypeInfo aspeed_soc_type_info = {
 314    .name           = TYPE_ASPEED_SOC,
 315    .parent         = TYPE_DEVICE,
 316    .instance_init  = aspeed_soc_init,
 317    .instance_size  = sizeof(AspeedSoCState),
 318    .class_size     = sizeof(AspeedSoCClass),
 319    .abstract       = true,
 320};
 321
 322static void aspeed_soc_register_types(void)
 323{
 324    int i;
 325
 326    type_register_static(&aspeed_soc_type_info);
 327    for (i = 0; i < ARRAY_SIZE(aspeed_socs); ++i) {
 328        TypeInfo ti = {
 329            .name       = aspeed_socs[i].name,
 330            .parent     = TYPE_ASPEED_SOC,
 331            .class_init = aspeed_soc_class_init,
 332            .class_data = (void *) &aspeed_socs[i],
 333        };
 334        type_register(&ti);
 335    }
 336}
 337
 338type_init(aspeed_soc_register_types)
 339