cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

npcm7xx_boards.c (15468B)


      1/*
      2 * Machine definitions for boards featuring an NPCM7xx SoC.
      3 *
      4 * Copyright 2020 Google LLC
      5 *
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms of the GNU General Public License as published by the
      8 * Free Software Foundation; either version 2 of the License, or
      9 * (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful, but WITHOUT
     12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     14 * for more details.
     15 */
     16
     17#include "qemu/osdep.h"
     18
     19#include "hw/arm/npcm7xx.h"
     20#include "hw/core/cpu.h"
     21#include "hw/i2c/i2c_mux_pca954x.h"
     22#include "hw/i2c/smbus_eeprom.h"
     23#include "hw/loader.h"
     24#include "hw/qdev-core.h"
     25#include "hw/qdev-properties.h"
     26#include "qapi/error.h"
     27#include "qemu-common.h"
     28#include "qemu/datadir.h"
     29#include "qemu/units.h"
     30
     31#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
     32#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
     33#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
     34#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
     35
     36static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
     37
     38static void npcm7xx_load_bootrom(MachineState *machine, NPCM7xxState *soc)
     39{
     40    const char *bios_name = machine->firmware ?: npcm7xx_default_bootrom;
     41    g_autofree char *filename = NULL;
     42    int ret;
     43
     44    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
     45    if (!filename) {
     46        error_report("Could not find ROM image '%s'", bios_name);
     47        if (!machine->kernel_filename) {
     48            /* We can't boot without a bootrom or a kernel image. */
     49            exit(1);
     50        }
     51        return;
     52    }
     53    ret = load_image_mr(filename, &soc->irom);
     54    if (ret < 0) {
     55        error_report("Failed to load ROM image '%s'", filename);
     56        exit(1);
     57    }
     58}
     59
     60static void npcm7xx_connect_flash(NPCM7xxFIUState *fiu, int cs_no,
     61                                  const char *flash_type, DriveInfo *dinfo)
     62{
     63    DeviceState *flash;
     64    qemu_irq flash_cs;
     65
     66    flash = qdev_new(flash_type);
     67    if (dinfo) {
     68        qdev_prop_set_drive(flash, "drive", blk_by_legacy_dinfo(dinfo));
     69    }
     70    qdev_realize_and_unref(flash, BUS(fiu->spi), &error_fatal);
     71
     72    flash_cs = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
     73    qdev_connect_gpio_out_named(DEVICE(fiu), "cs", cs_no, flash_cs);
     74}
     75
     76static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
     77{
     78    memory_region_add_subregion(get_system_memory(), NPCM7XX_DRAM_BA, dram);
     79
     80    object_property_set_link(OBJECT(soc), "dram-mr", OBJECT(dram),
     81                             &error_abort);
     82}
     83
     84static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
     85                                        uint32_t hw_straps)
     86{
     87    NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_GET_CLASS(machine);
     88    MachineClass *mc = MACHINE_CLASS(nmc);
     89    Object *obj;
     90
     91    if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
     92        error_report("This board can only be used with %s",
     93                     mc->default_cpu_type);
     94        exit(1);
     95    }
     96
     97    obj = object_new_with_props(nmc->soc_type, OBJECT(machine), "soc",
     98                                &error_abort, NULL);
     99    object_property_set_uint(obj, "power-on-straps", hw_straps, &error_abort);
    100
    101    return NPCM7XX(obj);
    102}
    103
    104static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num)
    105{
    106    g_assert(num < ARRAY_SIZE(soc->smbus));
    107    return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus"));
    108}
    109
    110static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
    111                              uint32_t rsize)
    112{
    113    I2CBus *i2c_bus = npcm7xx_i2c_get_bus(soc, bus);
    114    I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr);
    115    DeviceState *dev = DEVICE(i2c_dev);
    116
    117    qdev_prop_set_uint32(dev, "rom-size", rsize);
    118    i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
    119}
    120
    121static void npcm7xx_init_pwm_splitter(NPCM7xxMachine *machine,
    122                                      NPCM7xxState *soc, const int *fan_counts)
    123{
    124    SplitIRQ *splitters = machine->fan_splitter;
    125
    126    /*
    127     * PWM 0~3 belong to module 0 output 0~3.
    128     * PWM 4~7 belong to module 1 output 0~3.
    129     */
    130    for (int i = 0; i < NPCM7XX_NR_PWM_MODULES; ++i) {
    131        for (int j = 0; j < NPCM7XX_PWM_PER_MODULE; ++j) {
    132            int splitter_no = i * NPCM7XX_PWM_PER_MODULE + j;
    133            DeviceState *splitter;
    134
    135            if (fan_counts[splitter_no] < 1) {
    136                continue;
    137            }
    138            object_initialize_child(OBJECT(machine), "fan-splitter[*]",
    139                                    &splitters[splitter_no], TYPE_SPLIT_IRQ);
    140            splitter = DEVICE(&splitters[splitter_no]);
    141            qdev_prop_set_uint16(splitter, "num-lines",
    142                                 fan_counts[splitter_no]);
    143            qdev_realize(splitter, NULL, &error_abort);
    144            qdev_connect_gpio_out_named(DEVICE(&soc->pwm[i]), "duty-gpio-out",
    145                                        j, qdev_get_gpio_in(splitter, 0));
    146        }
    147    }
    148}
    149
    150static void npcm7xx_connect_pwm_fan(NPCM7xxState *soc, SplitIRQ *splitter,
    151                                    int fan_no, int output_no)
    152{
    153    DeviceState *fan;
    154    int fan_input;
    155    qemu_irq fan_duty_gpio;
    156
    157    g_assert(fan_no >= 0 && fan_no <= NPCM7XX_MFT_MAX_FAN_INPUT);
    158    /*
    159     * Fan 0~1 belong to module 0 input 0~1.
    160     * Fan 2~3 belong to module 1 input 0~1.
    161     * ...
    162     * Fan 14~15 belong to module 7 input 0~1.
    163     * Fan 16~17 belong to module 0 input 2~3.
    164     * Fan 18~19 belong to module 1 input 2~3.
    165     */
    166    if (fan_no < 16) {
    167        fan = DEVICE(&soc->mft[fan_no / 2]);
    168        fan_input = fan_no % 2;
    169    } else {
    170        fan = DEVICE(&soc->mft[(fan_no - 16) / 2]);
    171        fan_input = fan_no % 2 + 2;
    172    }
    173
    174    /* Connect the Fan to PWM module */
    175    fan_duty_gpio = qdev_get_gpio_in_named(fan, "duty", fan_input);
    176    qdev_connect_gpio_out(DEVICE(splitter), output_no, fan_duty_gpio);
    177}
    178
    179static void npcm750_evb_i2c_init(NPCM7xxState *soc)
    180{
    181    /* lm75 temperature sensor on SVB, tmp105 is compatible */
    182    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), "tmp105", 0x48);
    183    /* lm75 temperature sensor on EB, tmp105 is compatible */
    184    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x48);
    185    /* tmp100 temperature sensor on EB, tmp105 is compatible */
    186    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x48);
    187    /* tmp100 temperature sensor on SVB, tmp105 is compatible */
    188    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
    189}
    190
    191static void npcm750_evb_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
    192{
    193    SplitIRQ *splitter = machine->fan_splitter;
    194    static const int fan_counts[] = {2, 2, 2, 2, 2, 2, 2, 2};
    195
    196    npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
    197    npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
    198    npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
    199    npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
    200    npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
    201    npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
    202    npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
    203    npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x06, 0);
    204    npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x07, 1);
    205    npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x08, 0);
    206    npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x09, 1);
    207    npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0a, 0);
    208    npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0b, 1);
    209    npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0c, 0);
    210    npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0d, 1);
    211    npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0e, 0);
    212    npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0f, 1);
    213}
    214
    215static void quanta_gsj_i2c_init(NPCM7xxState *soc)
    216{
    217    /* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
    218    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x5c);
    219    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x5c);
    220    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 3), "tmp105", 0x5c);
    221    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), "tmp105", 0x5c);
    222
    223    at24c_eeprom_init(soc, 9, 0x55, 8192);
    224    at24c_eeprom_init(soc, 10, 0x55, 8192);
    225
    226    /*
    227     * i2c-11:
    228     * - power-brick@36: delta,dps800
    229     * - hotswap@15: ti,lm5066i
    230     */
    231
    232    /*
    233     * i2c-12:
    234     * - ucd90160@6b
    235     */
    236
    237    i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 15), "pca9548", 0x75);
    238}
    239
    240static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
    241{
    242    SplitIRQ *splitter = machine->fan_splitter;
    243    static const int fan_counts[] = {2, 2, 2, 0, 0, 0, 0, 0};
    244
    245    npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
    246    npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
    247    npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
    248    npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
    249    npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
    250    npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
    251    npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
    252}
    253
    254static void quanta_gbs_i2c_init(NPCM7xxState *soc)
    255{
    256    /*
    257     * i2c-0:
    258     *     pca9546@71
    259     *
    260     * i2c-1:
    261     *     pca9535@24
    262     *     pca9535@20
    263     *     pca9535@21
    264     *     pca9535@22
    265     *     pca9535@23
    266     *     pca9535@25
    267     *     pca9535@26
    268     *
    269     * i2c-2:
    270     *     sbtsi@4c
    271     *
    272     * i2c-5:
    273     *     atmel,24c64@50 mb_fru
    274     *     pca9546@71
    275     *         - channel 0: max31725@54
    276     *         - channel 1: max31725@55
    277     *         - channel 2: max31725@5d
    278     *                      atmel,24c64@51 fan_fru
    279     *         - channel 3: atmel,24c64@52 hsbp_fru
    280     *
    281     * i2c-6:
    282     *     pca9545@73
    283     *
    284     * i2c-7:
    285     *     pca9545@72
    286     *
    287     * i2c-8:
    288     *     adi,adm1272@10
    289     *
    290     * i2c-9:
    291     *     pca9546@71
    292     *         - channel 0: isil,isl68137@60
    293     *         - channel 1: isil,isl68137@61
    294     *         - channel 2: isil,isl68137@63
    295     *         - channel 3: isil,isl68137@45
    296     *
    297     * i2c-10:
    298     *     pca9545@71
    299     *
    300     * i2c-11:
    301     *     pca9545@76
    302     *
    303     * i2c-12:
    304     *     maxim,max34451@4e
    305     *     isil,isl68137@5d
    306     *     isil,isl68137@5e
    307     *
    308     * i2c-14:
    309     *     pca9545@70
    310     */
    311}
    312
    313static void npcm750_evb_init(MachineState *machine)
    314{
    315    NPCM7xxState *soc;
    316
    317    soc = npcm7xx_create_soc(machine, NPCM750_EVB_POWER_ON_STRAPS);
    318    npcm7xx_connect_dram(soc, machine->ram);
    319    qdev_realize(DEVICE(soc), NULL, &error_fatal);
    320
    321    npcm7xx_load_bootrom(machine, soc);
    322    npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
    323    npcm750_evb_i2c_init(soc);
    324    npcm750_evb_fan_init(NPCM7XX_MACHINE(machine), soc);
    325    npcm7xx_load_kernel(machine, soc);
    326}
    327
    328static void quanta_gsj_init(MachineState *machine)
    329{
    330    NPCM7xxState *soc;
    331
    332    soc = npcm7xx_create_soc(machine, QUANTA_GSJ_POWER_ON_STRAPS);
    333    npcm7xx_connect_dram(soc, machine->ram);
    334    qdev_realize(DEVICE(soc), NULL, &error_fatal);
    335
    336    npcm7xx_load_bootrom(machine, soc);
    337    npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
    338                          drive_get(IF_MTD, 0, 0));
    339    quanta_gsj_i2c_init(soc);
    340    quanta_gsj_fan_init(NPCM7XX_MACHINE(machine), soc);
    341    npcm7xx_load_kernel(machine, soc);
    342}
    343
    344static void quanta_gbs_init(MachineState *machine)
    345{
    346    NPCM7xxState *soc;
    347
    348    soc = npcm7xx_create_soc(machine, QUANTA_GBS_POWER_ON_STRAPS);
    349    npcm7xx_connect_dram(soc, machine->ram);
    350    qdev_realize(DEVICE(soc), NULL, &error_fatal);
    351
    352    npcm7xx_load_bootrom(machine, soc);
    353
    354    npcm7xx_connect_flash(&soc->fiu[0], 0, "mx66u51235f",
    355                          drive_get(IF_MTD, 0, 0));
    356
    357    quanta_gbs_i2c_init(soc);
    358    npcm7xx_load_kernel(machine, soc);
    359}
    360
    361static void kudo_bmc_init(MachineState *machine)
    362{
    363    NPCM7xxState *soc;
    364
    365    soc = npcm7xx_create_soc(machine, KUDO_BMC_POWER_ON_STRAPS);
    366    npcm7xx_connect_dram(soc, machine->ram);
    367    qdev_realize(DEVICE(soc), NULL, &error_fatal);
    368
    369    npcm7xx_load_bootrom(machine, soc);
    370    npcm7xx_connect_flash(&soc->fiu[0], 0, "mx66u51235f",
    371                          drive_get(IF_MTD, 0, 0));
    372    npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f",
    373                          drive_get(IF_MTD, 3, 0));
    374
    375    npcm7xx_load_kernel(machine, soc);
    376}
    377
    378static void npcm7xx_set_soc_type(NPCM7xxMachineClass *nmc, const char *type)
    379{
    380    NPCM7xxClass *sc = NPCM7XX_CLASS(object_class_by_name(type));
    381    MachineClass *mc = MACHINE_CLASS(nmc);
    382
    383    nmc->soc_type = type;
    384    mc->default_cpus = mc->min_cpus = mc->max_cpus = sc->num_cpus;
    385}
    386
    387static void npcm7xx_machine_class_init(ObjectClass *oc, void *data)
    388{
    389    MachineClass *mc = MACHINE_CLASS(oc);
    390
    391    mc->no_floppy = 1;
    392    mc->no_cdrom = 1;
    393    mc->no_parallel = 1;
    394    mc->default_ram_id = "ram";
    395    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a9");
    396}
    397
    398/*
    399 * Schematics:
    400 * https://github.com/Nuvoton-Israel/nuvoton-info/blob/master/npcm7xx-poleg/evaluation-board/board_deliverables/NPCM750x_EB_ver.A1.1_COMPLETE.pdf
    401 */
    402static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
    403{
    404    NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
    405    MachineClass *mc = MACHINE_CLASS(oc);
    406
    407    npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
    408
    409    mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex-A9)";
    410    mc->init = npcm750_evb_init;
    411    mc->default_ram_size = 512 * MiB;
    412};
    413
    414static void gsj_machine_class_init(ObjectClass *oc, void *data)
    415{
    416    NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
    417    MachineClass *mc = MACHINE_CLASS(oc);
    418
    419    npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
    420
    421    mc->desc = "Quanta GSJ (Cortex-A9)";
    422    mc->init = quanta_gsj_init;
    423    mc->default_ram_size = 512 * MiB;
    424};
    425
    426static void gbs_bmc_machine_class_init(ObjectClass *oc, void *data)
    427{
    428    NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
    429    MachineClass *mc = MACHINE_CLASS(oc);
    430
    431    npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
    432
    433    mc->desc = "Quanta GBS (Cortex-A9)";
    434    mc->init = quanta_gbs_init;
    435    mc->default_ram_size = 1 * GiB;
    436}
    437
    438static void kudo_bmc_machine_class_init(ObjectClass *oc, void *data)
    439{
    440    NPCM7xxMachineClass *nmc = NPCM7XX_MACHINE_CLASS(oc);
    441    MachineClass *mc = MACHINE_CLASS(oc);
    442
    443    npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
    444
    445    mc->desc = "Kudo BMC (Cortex-A9)";
    446    mc->init = kudo_bmc_init;
    447    mc->default_ram_size = 1 * GiB;
    448};
    449
    450static const TypeInfo npcm7xx_machine_types[] = {
    451    {
    452        .name           = TYPE_NPCM7XX_MACHINE,
    453        .parent         = TYPE_MACHINE,
    454        .instance_size  = sizeof(NPCM7xxMachine),
    455        .class_size     = sizeof(NPCM7xxMachineClass),
    456        .class_init     = npcm7xx_machine_class_init,
    457        .abstract       = true,
    458    }, {
    459        .name           = MACHINE_TYPE_NAME("npcm750-evb"),
    460        .parent         = TYPE_NPCM7XX_MACHINE,
    461        .class_init     = npcm750_evb_machine_class_init,
    462    }, {
    463        .name           = MACHINE_TYPE_NAME("quanta-gsj"),
    464        .parent         = TYPE_NPCM7XX_MACHINE,
    465        .class_init     = gsj_machine_class_init,
    466    }, {
    467        .name           = MACHINE_TYPE_NAME("quanta-gbs-bmc"),
    468        .parent         = TYPE_NPCM7XX_MACHINE,
    469        .class_init     = gbs_bmc_machine_class_init,
    470    }, {
    471        .name           = MACHINE_TYPE_NAME("kudo-bmc"),
    472        .parent         = TYPE_NPCM7XX_MACHINE,
    473        .class_init     = kudo_bmc_machine_class_init,
    474    },
    475};
    476
    477DEFINE_TYPES(npcm7xx_machine_types)