qemu/hw/core/fdt_generic_devices.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "hw/fdt_generic_util.h"
   3#include "hw/fdt_generic_devices.h"
   4#include "qom/object.h"
   5#include "sysemu/blockdev.h"
   6#include "exec/memory.h"
   7#include "exec/address-spaces.h"
   8#include "qemu/log.h"
   9#include "qapi/error.h"
  10#include "sysemu/char.h"
  11#include "qemu/coroutine.h"
  12#include "qapi-types.h"
  13
  14#include "hw/char/serial.h"
  15#include "hw/block/flash.h"
  16#include "hw/qdev-core.h"
  17
  18#define FLASH_SECTOR_SIZE (64 * 1024)
  19
  20/* FIXME: This file should go away. When these devices are properly QOMified
  21 * then these FDT creations should happen automatically without need for these
  22 * explict shim functions
  23 */
  24
  25/* Piggy back fdt_generic_util.c ERR_DEBUG symbol as these two are really the
  26 * same feature
  27 */
  28
  29#ifndef FDT_GENERIC_UTIL_ERR_DEBUG
  30#define FDT_GENERIC_UTIL_ERR_DEBUG 0
  31#endif
  32#define DB_PRINT(lvl, ...) do { \
  33    if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
  34        qemu_log_mask(lvl, ": %s: ", __func__); \
  35        qemu_log_mask(lvl, ## __VA_ARGS__); \
  36    } \
  37} while (0);
  38
  39#define DB_PRINT_NP(lvl, ...) do { \
  40    if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
  41        qemu_log_mask(lvl, "%s", node_path); \
  42        DB_PRINT((lvl), ## __VA_ARGS__); \
  43    } \
  44} while (0);
  45
  46int fdt_generic_num_cpus;
  47
  48int pflash_cfi01_fdt_init(char *node_path, FDTMachineInfo *fdti, void *opaque)
  49{
  50
  51    uint32_t flash_base = 0;
  52    uint32_t flash_size = 0;
  53
  54    DriveInfo *dinfo;
  55    uint32_t bank_width;
  56
  57    /* FIXME: respect #address and size cells */
  58    flash_base = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0,
  59                                       false, &error_abort);
  60    flash_size = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 1,
  61                                       false, &error_abort);
  62    bank_width = qemu_fdt_getprop_cell(fdti->fdt, node_path, "bank-width",
  63                                       0, false, &error_abort);
  64
  65    DB_PRINT_NP(0, "FLASH: baseaddr: 0x%x, size: 0x%x\n",
  66                flash_base, flash_size);
  67
  68    dinfo = drive_get_next(IF_PFLASH);
  69    pflash_cfi01_register(flash_base, NULL, node_path, flash_size,
  70                            dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
  71                            FLASH_SECTOR_SIZE, flash_size/FLASH_SECTOR_SIZE,
  72                            bank_width, 0x89, 0x18, 0x0000, 0x0, 0);
  73    return 0;
  74}
  75
  76static int uart16550_fdt_init(char *node_path, FDTMachineInfo *fdti,
  77    void *priv)
  78{
  79    /* FIXME: Pass in dynamically */
  80    MemoryRegion *address_space_mem = get_system_memory();
  81    hwaddr base;
  82    uint32_t baudrate;
  83    qemu_irq irqline;
  84    bool map_mode;
  85    char irq_info[1024];
  86    Error *err = NULL;
  87
  88    /* FIXME: respect #address and size cells */
  89    base = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0,
  90                                 false, &error_abort);
  91    base += qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg-offset", 0,
  92                                  false, &error_abort);
  93    base &= ~3ULL; /* qemu uart16550 model starts with 3* 8bit offset */
  94
  95    baudrate = qemu_fdt_getprop_cell(fdti->fdt, node_path, "current-speed",
  96                                     0, false, &err);
  97    if (err) {
  98        baudrate = 115200;
  99    }
 100
 101    irqline = *fdt_get_irq_info(fdti, node_path, 0, irq_info, &map_mode);
 102    assert(!map_mode);
 103    DB_PRINT_NP(0, "UART16550a: baseaddr: 0x" TARGET_FMT_plx
 104                ", irq: %s, baud %d\n", base, irq_info, baudrate);
 105
 106    /* it_shift = 2, reg-shift in DTS - for Xilnx IP is hardcoded */
 107    serial_mm_init(address_space_mem, base, 2, irqline, baudrate,
 108                   qemu_char_get_next_serial(), DEVICE_LITTLE_ENDIAN);
 109    return 0;
 110}
 111
 112static int i2c_bus_fdt_init(char *node_path, FDTMachineInfo *fdti, void *priv)
 113{
 114    Object *parent;
 115    DeviceState *dev;
 116    char parent_node_path[DT_PATH_LENGTH];
 117    char *node_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
 118
 119    DB_PRINT_NP(1, "\n");
 120    /* FIXME: share this code with fdt_generic_util.c/fdt_init_qdev() */
 121    if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
 122        abort();
 123    }
 124    while (!fdt_init_has_opaque(fdti, parent_node_path)) {
 125        fdt_init_yield(fdti);
 126    }
 127    parent = fdt_init_get_opaque(fdti, parent_node_path);
 128    dev = (DeviceState *)object_dynamic_cast(parent, TYPE_DEVICE);
 129    if (parent && dev) {
 130        while (!dev->realized) {
 131            fdt_init_yield(fdti);
 132        }
 133        DB_PRINT_NP(0, "parenting i2c bus to %s bus %s\n", parent_node_path,
 134                 node_name);
 135        fdt_init_set_opaque(fdti, node_path,
 136                            qdev_get_child_bus(dev, node_name));
 137    } else {
 138        DB_PRINT_NP(0, "orphaning i2c bus\n");
 139    }
 140    return 0;
 141}
 142
 143static int sysmem_fdt_init(char *node_path, FDTMachineInfo *fdti,
 144                           void *priv)
 145{
 146    fdt_init_set_opaque(fdti, node_path, OBJECT(get_system_memory()));
 147    return 0;
 148}
 149
 150static inline void razwi_unimp_rw(void *opaque, hwaddr addr, uint64_t val64,
 151                           unsigned int size, bool rnw) {
 152    char str[1024];
 153
 154    snprintf(str, sizeof(str), "%s: RAZ/WI device %s: addr: %#llx data: %#llx"
 155             " size: %d\n",
 156             opaque ? (const char *)opaque : "(none)", rnw ? "read" : "write",
 157             (unsigned long long)addr, (unsigned long long)val64, size);
 158
 159    DB_PRINT(0, "%s", str);
 160    qemu_log_mask(LOG_UNIMP, "%s", str);
 161}
 162
 163fdt_register_compatibility(sysmem_fdt_init, "compatible:qemu:system-memory");
 164fdt_register_compatibility_n(uart16550_fdt_init, "compatible:ns16550", 0);
 165fdt_register_compatibility_n(uart16550_fdt_init, "compatible:ns16550a", 1);
 166
 167static const void *null;
 168
 169fdt_register_compatibility_n(null, "compatible:marvell,88e1111", 1);
 170fdt_register_compatibility_n(null, "compatible:arm,pl310-cache", 2);
 171fdt_register_compatibility_n(null, "compatible:xlnx,ps7-cortexa9-1.00.a", 3);
 172fdt_register_compatibility_n(null, "compatible:xlnx,zynq_remoteproc", 4);
 173fdt_register_compatibility_n(null, "compatible:xlnx,ps7-smcc-1.00.a", 5);
 174fdt_register_compatibility_n(null, "compatible:xlnx,ps7-smc", 6);
 175fdt_register_compatibility_n(null, "compatible:xlnx,ps7-nand-1.00.a", 7);
 176fdt_register_compatibility_n(null, "compatible:xlnx,ps7-ram-1.00.a", 8);
 177fdt_register_compatibility_n(null, "compatible:xlnx,ps7-ocm", 9);
 178fdt_register_compatibility_n(null, "compatible:marvell,88e1118r", 10);
 179fdt_register_compatibility_n(null, "compatible:xlnx,ps7-clkc", 11);
 180fdt_register_compatibility_n(null, "compatible:xlnx,ps7-ddrc", 12);
 181fdt_register_compatibility_n(null, "compatible:xlnx,ps7-scuc-1.00.a", 13);
 182fdt_register_compatibility_n(null, "compatible:fixed-clock", 14);
 183fdt_register_compatibility_n(null, "compatible:xlnx,pinctrl-zynq", 15);
 184fdt_register_compatibility_n(null, "compatible:ulpi-phy", 16);
 185fdt_register_compatibility_n(null, "compatible:xlnx,zynq-efuse", 17);
 186fdt_register_compatibility_n(null, "compatible:qemu:memory-region-spec", 18);
 187
 188fdt_register_instance_n(i2c_bus_fdt_init, "i2c@0", 0);
 189fdt_register_instance_n(i2c_bus_fdt_init, "i2c@1", 1);
 190fdt_register_instance_n(i2c_bus_fdt_init, "i2c@2", 2);
 191fdt_register_instance_n(i2c_bus_fdt_init, "i2c@3", 3);
 192fdt_register_instance_n(i2c_bus_fdt_init, "i2c@4", 4);
 193fdt_register_instance_n(i2c_bus_fdt_init, "i2c@5", 5);
 194fdt_register_instance_n(i2c_bus_fdt_init, "i2c@6", 6);
 195fdt_register_instance_n(i2c_bus_fdt_init, "i2c@7", 7);
 196
 197static const TypeInfo fdt_qom_aliases [] = {
 198    {   .name = "xlnx.ps7-ethernet",        .parent = "cadence_gem"         },
 199    {   .name = "cdns,gem",                 .parent = "cadence_gem"         },
 200    {   .name = "cdns,zynq-gem",            .parent = "cadence_gem"         },
 201    {   .name = "cdns,zynqmp-gem",          .parent = "cadence_gem"         },
 202    {   .name = "xlnx.ps7-ttc",             .parent = "cadence_ttc"         },
 203    {   .name = "cdns.ttc",                 .parent = "cadence_ttc"         },
 204    {   .name = "cdns.uart",                .parent = "cadence_uart"        },
 205    {   .name = "xlnx.ps7-uart",            .parent = "cadence_uart"        },
 206    {   .name = "silabs,si570",             .parent = "si57x"               },
 207/* When running MicroBlaze this is not include, which casues QEMU to crash as
 208 * it doesn't have information on the TYPE_SYS_BUS_EHCI device.
 209 */
 210#ifdef CONFIG_USB_EHCI_SYSBUS
 211    {   .name = "xlnx.ps7-usb",             .parent = "xlnx,ps7-usb"        },
 212    {   .name = "xlnx.zynq-usb",            .parent = "xlnx,ps7-usb"        },
 213#endif
 214    {   .name = "xlnx.zynq-qspi",           .parent = "xlnx.ps7-qspi"       },
 215    {   .name = "xlnx.xuartps",             .parent = "cadence_uart"        },
 216    {   .name = "simple-bus",               .parent = "qemu:memory-region"  },
 217    {   .name = "xlnx,axi-dpdma-1.0",       .parent = "xlnx.dpdma"          },
 218    {   .name = "xlnx,xps-gpio-1.00.a",     .parent = "xlnx.axi-gpio"       },
 219    {   .name = "arasan,sdhci-8.9a",        .parent = "xilinx.zynqmp-sdhci" },
 220    {   .name = "cdns.spi-r1p6",            .parent = "xlnx.ps7-spi"        },
 221    {   .name = "xlnx,eth-dma",             .parent = "xlnx.axi-dma"        },
 222};
 223
 224static void fdt_generic_register_types(void)
 225{
 226    int i;
 227
 228    for (i = 0; i < ARRAY_SIZE(fdt_qom_aliases); ++i) {
 229        type_register_static(&fdt_qom_aliases[i]);
 230    }
 231}
 232
 233type_init(fdt_generic_register_types)
 234