qemu/hw/arm/aspeed.c
<<
>>
Prefs
   1/*
   2 * OpenPOWER Palmetto BMC
   3 *
   4 * Andrew Jeffery <andrew@aj.id.au>
   5 *
   6 * Copyright 2016 IBM Corp.
   7 *
   8 * This code is licensed under the GPL version 2 or later.  See
   9 * the COPYING file in the top-level directory.
  10 */
  11
  12#include "qemu/osdep.h"
  13#include "qapi/error.h"
  14#include "qemu-common.h"
  15#include "cpu.h"
  16#include "exec/address-spaces.h"
  17#include "hw/arm/arm.h"
  18#include "hw/arm/aspeed_soc.h"
  19#include "hw/boards.h"
  20#include "qemu/log.h"
  21#include "sysemu/block-backend.h"
  22#include "sysemu/blockdev.h"
  23#include "hw/loader.h"
  24#include "qemu/error-report.h"
  25
  26static struct arm_boot_info aspeed_board_binfo = {
  27    .board_id = -1, /* device-tree-only board */
  28    .nb_cpus = 1,
  29};
  30
  31typedef struct AspeedBoardState {
  32    AspeedSoCState soc;
  33    MemoryRegion ram;
  34} AspeedBoardState;
  35
  36typedef struct AspeedBoardConfig {
  37    const char *soc_name;
  38    uint32_t hw_strap1;
  39    const char *fmc_model;
  40    const char *spi_model;
  41    uint32_t num_cs;
  42    void (*i2c_init)(AspeedBoardState *bmc);
  43} AspeedBoardConfig;
  44
  45enum {
  46    PALMETTO_BMC,
  47    AST2500_EVB,
  48    ROMULUS_BMC,
  49};
  50
  51/* Palmetto hardware value: 0x120CE416 */
  52#define PALMETTO_BMC_HW_STRAP1 (                                        \
  53        SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) |               \
  54        SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
  55        SCU_AST2400_HW_STRAP_ACPI_DIS |                                 \
  56        SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) |       \
  57        SCU_HW_STRAP_VGA_CLASS_CODE |                                   \
  58        SCU_HW_STRAP_LPC_RESET_PIN |                                    \
  59        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) |                \
  60        SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
  61        SCU_HW_STRAP_SPI_WIDTH |                                        \
  62        SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) |                       \
  63        SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
  64
  65/* AST2500 evb hardware value: 0xF100C2E6 */
  66#define AST2500_EVB_HW_STRAP1 ((                                        \
  67        AST2500_HW_STRAP1_DEFAULTS |                                    \
  68        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
  69        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
  70        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
  71        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
  72        SCU_HW_STRAP_MAC1_RGMII |                                       \
  73        SCU_HW_STRAP_MAC0_RGMII) &                                      \
  74        ~SCU_HW_STRAP_2ND_BOOT_WDT)
  75
  76/* Romulus hardware value: 0xF10AD206 */
  77#define ROMULUS_BMC_HW_STRAP1 (                                         \
  78        AST2500_HW_STRAP1_DEFAULTS |                                    \
  79        SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE |                     \
  80        SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE |                        \
  81        SCU_AST2500_HW_STRAP_UART_DEBUG |                               \
  82        SCU_AST2500_HW_STRAP_DDR4_ENABLE |                              \
  83        SCU_AST2500_HW_STRAP_ACPI_ENABLE |                              \
  84        SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
  85
  86static void palmetto_bmc_i2c_init(AspeedBoardState *bmc);
  87static void ast2500_evb_i2c_init(AspeedBoardState *bmc);
  88
  89static const AspeedBoardConfig aspeed_boards[] = {
  90    [PALMETTO_BMC] = {
  91        .soc_name  = "ast2400-a1",
  92        .hw_strap1 = PALMETTO_BMC_HW_STRAP1,
  93        .fmc_model = "n25q256a",
  94        .spi_model = "mx25l25635e",
  95        .num_cs    = 1,
  96        .i2c_init  = palmetto_bmc_i2c_init,
  97    },
  98    [AST2500_EVB]  = {
  99        .soc_name  = "ast2500-a1",
 100        .hw_strap1 = AST2500_EVB_HW_STRAP1,
 101        .fmc_model = "n25q256a",
 102        .spi_model = "mx25l25635e",
 103        .num_cs    = 1,
 104        .i2c_init  = ast2500_evb_i2c_init,
 105    },
 106    [ROMULUS_BMC]  = {
 107        .soc_name  = "ast2500-a1",
 108        .hw_strap1 = ROMULUS_BMC_HW_STRAP1,
 109        .fmc_model = "n25q256a",
 110        .spi_model = "mx66l1g45g",
 111        .num_cs    = 2,
 112    },
 113};
 114
 115#define FIRMWARE_ADDR 0x0
 116
 117static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
 118                           Error **errp)
 119{
 120    BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
 121    uint8_t *storage;
 122    int64_t size;
 123
 124    /* The block backend size should have already been 'validated' by
 125     * the creation of the m25p80 object.
 126     */
 127    size = blk_getlength(blk);
 128    if (size <= 0) {
 129        error_setg(errp, "failed to get flash size");
 130        return;
 131    }
 132
 133    if (rom_size > size) {
 134        rom_size = size;
 135    }
 136
 137    storage = g_new0(uint8_t, rom_size);
 138    if (blk_pread(blk, 0, storage, rom_size) < 0) {
 139        error_setg(errp, "failed to read the initial flash content");
 140        return;
 141    }
 142
 143    rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr);
 144    g_free(storage);
 145}
 146
 147static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
 148                                      Error **errp)
 149{
 150    int i ;
 151
 152    for (i = 0; i < s->num_cs; ++i) {
 153        AspeedSMCFlash *fl = &s->flashes[i];
 154        DriveInfo *dinfo = drive_get_next(IF_MTD);
 155        qemu_irq cs_line;
 156
 157        fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
 158        if (dinfo) {
 159            qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
 160                                errp);
 161        }
 162        qdev_init_nofail(fl->flash);
 163
 164        cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
 165        sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
 166    }
 167}
 168
 169static void aspeed_board_init(MachineState *machine,
 170                              const AspeedBoardConfig *cfg)
 171{
 172    AspeedBoardState *bmc;
 173    AspeedSoCClass *sc;
 174    DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
 175
 176    bmc = g_new0(AspeedBoardState, 1);
 177    object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
 178    object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
 179                              &error_abort);
 180
 181    sc = ASPEED_SOC_GET_CLASS(&bmc->soc);
 182
 183    object_property_set_uint(OBJECT(&bmc->soc), ram_size, "ram-size",
 184                             &error_abort);
 185    object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
 186                            &error_abort);
 187    object_property_set_int(OBJECT(&bmc->soc), cfg->num_cs, "num-cs",
 188                            &error_abort);
 189    if (machine->kernel_filename) {
 190        /*
 191         * When booting with a -kernel command line there is no u-boot
 192         * that runs to unlock the SCU. In this case set the default to
 193         * be unlocked as the kernel expects
 194         */
 195        object_property_set_int(OBJECT(&bmc->soc), ASPEED_SCU_PROT_KEY,
 196                                "hw-prot-key", &error_abort);
 197    }
 198    object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
 199                             &error_abort);
 200
 201    /*
 202     * Allocate RAM after the memory controller has checked the size
 203     * was valid. If not, a default value is used.
 204     */
 205    ram_size = object_property_get_uint(OBJECT(&bmc->soc), "ram-size",
 206                                        &error_abort);
 207
 208    memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
 209    memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
 210                                &bmc->ram);
 211    object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
 212                                   &error_abort);
 213
 214    aspeed_board_init_flashes(&bmc->soc.fmc, cfg->fmc_model, &error_abort);
 215    aspeed_board_init_flashes(&bmc->soc.spi[0], cfg->spi_model, &error_abort);
 216
 217    /* Install first FMC flash content as a boot rom. */
 218    if (drive0) {
 219        AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0];
 220        MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
 221
 222        /*
 223         * create a ROM region using the default mapping window size of
 224         * the flash module. The window size is 64MB for the AST2400
 225         * SoC and 128MB for the AST2500 SoC, which is twice as big as
 226         * needed by the flash modules of the Aspeed machines.
 227         */
 228        memory_region_init_rom_nomigrate(boot_rom, OBJECT(bmc), "aspeed.boot_rom",
 229                               fl->size, &error_abort);
 230        memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
 231                                    boot_rom);
 232        write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
 233    }
 234
 235    aspeed_board_binfo.kernel_filename = machine->kernel_filename;
 236    aspeed_board_binfo.initrd_filename = machine->initrd_filename;
 237    aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
 238    aspeed_board_binfo.ram_size = ram_size;
 239    aspeed_board_binfo.loader_start = sc->info->sdram_base;
 240
 241    if (cfg->i2c_init) {
 242        cfg->i2c_init(bmc);
 243    }
 244
 245    arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo);
 246}
 247
 248static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
 249{
 250    AspeedSoCState *soc = &bmc->soc;
 251    DeviceState *dev;
 252
 253    /* The palmetto platform expects a ds3231 RTC but a ds1338 is
 254     * enough to provide basic RTC features. Alarms will be missing */
 255    i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68);
 256
 257    /* add a TMP423 temperature sensor */
 258    dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2),
 259                           "tmp423", 0x4c);
 260    object_property_set_int(OBJECT(dev), 31000, "temperature0", &error_abort);
 261    object_property_set_int(OBJECT(dev), 28000, "temperature1", &error_abort);
 262    object_property_set_int(OBJECT(dev), 20000, "temperature2", &error_abort);
 263    object_property_set_int(OBJECT(dev), 110000, "temperature3", &error_abort);
 264}
 265
 266static void palmetto_bmc_init(MachineState *machine)
 267{
 268    aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]);
 269}
 270
 271static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
 272{
 273    MachineClass *mc = MACHINE_CLASS(oc);
 274
 275    mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
 276    mc->init = palmetto_bmc_init;
 277    mc->max_cpus = 1;
 278    mc->no_sdcard = 1;
 279    mc->no_floppy = 1;
 280    mc->no_cdrom = 1;
 281    mc->no_parallel = 1;
 282    mc->ignore_memory_transaction_failures = true;
 283}
 284
 285static const TypeInfo palmetto_bmc_type = {
 286    .name = MACHINE_TYPE_NAME("palmetto-bmc"),
 287    .parent = TYPE_MACHINE,
 288    .class_init = palmetto_bmc_class_init,
 289};
 290
 291static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
 292{
 293    AspeedSoCState *soc = &bmc->soc;
 294
 295    /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
 296    i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d);
 297}
 298
 299static void ast2500_evb_init(MachineState *machine)
 300{
 301    aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]);
 302}
 303
 304static void ast2500_evb_class_init(ObjectClass *oc, void *data)
 305{
 306    MachineClass *mc = MACHINE_CLASS(oc);
 307
 308    mc->desc = "Aspeed AST2500 EVB (ARM1176)";
 309    mc->init = ast2500_evb_init;
 310    mc->max_cpus = 1;
 311    mc->no_sdcard = 1;
 312    mc->no_floppy = 1;
 313    mc->no_cdrom = 1;
 314    mc->no_parallel = 1;
 315    mc->ignore_memory_transaction_failures = true;
 316}
 317
 318static const TypeInfo ast2500_evb_type = {
 319    .name = MACHINE_TYPE_NAME("ast2500-evb"),
 320    .parent = TYPE_MACHINE,
 321    .class_init = ast2500_evb_class_init,
 322};
 323
 324static void romulus_bmc_init(MachineState *machine)
 325{
 326    aspeed_board_init(machine, &aspeed_boards[ROMULUS_BMC]);
 327}
 328
 329static void romulus_bmc_class_init(ObjectClass *oc, void *data)
 330{
 331    MachineClass *mc = MACHINE_CLASS(oc);
 332
 333    mc->desc = "OpenPOWER Romulus BMC (ARM1176)";
 334    mc->init = romulus_bmc_init;
 335    mc->max_cpus = 1;
 336    mc->no_sdcard = 1;
 337    mc->no_floppy = 1;
 338    mc->no_cdrom = 1;
 339    mc->no_parallel = 1;
 340    mc->ignore_memory_transaction_failures = true;
 341}
 342
 343static const TypeInfo romulus_bmc_type = {
 344    .name = MACHINE_TYPE_NAME("romulus-bmc"),
 345    .parent = TYPE_MACHINE,
 346    .class_init = romulus_bmc_class_init,
 347};
 348
 349static void aspeed_machine_init(void)
 350{
 351    type_register_static(&palmetto_bmc_type);
 352    type_register_static(&ast2500_evb_type);
 353    type_register_static(&romulus_bmc_type);
 354}
 355
 356type_init(aspeed_machine_init)
 357