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