qemu/hw/arm/arm_generic_fdt.c
<<
>>
Prefs
   1/*
   2 * Xilinx Zynq Baseboard System emulation.
   3 *
   4 * Copyright (c) 2012 Xilinx. Inc
   5 * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@xilinx.com)
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License
   9 * as published by the Free Software Foundation; either version
  10 * 2 of the License, or (at your option) any later version.
  11 *
  12 * You should have received a copy of the GNU General Public License along
  13 * with this program; if not, see <http://www.gnu.org/licenses/>.
  14 */
  15
  16#include "qemu/osdep.h"
  17#include "cpu.h"
  18#include "hw/boards.h"
  19#include "hw/loader.h"
  20#include "qapi/error.h"
  21#include "hw/block/flash.h"
  22#include "qemu/error-report.h"
  23#include "qemu/log.h"
  24#include "sysemu/qtest.h"
  25#include "hw/arm/xlnx-zynqmp.h"
  26
  27#include <libfdt.h>
  28#include "hw/fdt_generic_util.h"
  29#include "hw/fdt_generic_devices.h"
  30
  31#ifndef ARM_GENERIC_FDT_DEBUG
  32#define ARM_GENERIC_FDT_DEBUG 3
  33#endif
  34#define DB_PRINT(lvl, ...) do { \
  35    if (ARM_GENERIC_FDT_DEBUG > (lvl)) { \
  36        qemu_log_mask(LOG_FDT, ": %s: ", __func__); \
  37        qemu_log_mask(LOG_FDT, ## __VA_ARGS__); \
  38    } \
  39} while (0);
  40
  41#define DB_PRINT_RAW(lvl, ...) do { \
  42    if (ARM_GENERIC_FDT_DEBUG > (lvl)) { \
  43        qemu_log_mask(LOG_FDT, ## __VA_ARGS__); \
  44    } \
  45} while (0);
  46
  47#define GENERAL_MACHINE_NAME "arm-generic-fdt"
  48#define ZYNQ7000_MACHINE_NAME "arm-generic-fdt-7series"
  49#define DEP_GENERAL_MACHINE_NAME "arm-generic-fdt-plnx"
  50
  51#define QTEST_RUNNING (qtest_enabled() && qtest_driver())
  52
  53#define MAX_CPUS 4
  54
  55#define ZYNQ7000_MPCORE_PERIPHBASE 0xF8F00000
  56
  57#define SMP_BOOT_ADDR 0xfffffff0
  58/* Meaningless, but keeps arm boot happy */
  59#define SMP_BOOTREG_ADDR 0xfffffffc
  60
  61static struct arm_boot_info arm_generic_fdt_binfo = {};
  62
  63/* Entry point for secondary CPU */
  64static uint32_t zynq_smpboot[] = {
  65    0xe320f003, /* wfi */
  66    0xeafffffd, /* beq     <wfi> */
  67};
  68
  69typedef struct {
  70    ram_addr_t ram_kernel_base;
  71    ram_addr_t ram_kernel_size;
  72} memory_info;
  73
  74static void arm_write_secondary_boot(ARMCPU *cpu,
  75                                      const struct arm_boot_info *info)
  76{
  77    int n;
  78
  79    for (n = 0; n < ARRAY_SIZE(zynq_smpboot); n++) {
  80        zynq_smpboot[n] = tswap32(zynq_smpboot[n]);
  81    }
  82    rom_add_blob_fixed("smpboot", zynq_smpboot, sizeof(zynq_smpboot),
  83                       SMP_BOOT_ADDR);
  84}
  85
  86static void zynq7000_usb_nuke_phy(void *fdt)
  87{
  88    char usb_node_path[DT_PATH_LENGTH];
  89
  90    int ret = qemu_devtree_node_by_compatible(fdt, usb_node_path,
  91                                              "xlnx,ps7-usb-1.00.a");
  92    if (!ret) {
  93        qemu_fdt_setprop_string(fdt, usb_node_path, "dr_mode", "host");
  94    }
  95}
  96
  97static int zynq7000_mdio_phy_connect(char *node_path, FDTMachineInfo *fdti,
  98                                     void *Opaque)
  99{
 100    Object *parent;
 101    char parent_node_path[DT_PATH_LENGTH];
 102
 103    /* Register MDIO obj instance to fdti, useful during child registration */
 104    fdt_init_set_opaque(fdti, node_path, Opaque);
 105    if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
 106        abort();
 107    }
 108
 109    /* Wait for the parent to be created */
 110    while (!fdt_init_has_opaque(fdti, parent_node_path)) {
 111        fdt_init_yield(fdti);
 112    }
 113
 114    /* Get the parent obj (i.e gem object), which was registerd in fdti */
 115    parent = fdt_init_get_opaque(fdti, parent_node_path);
 116
 117    /* Add parent to mdio node */
 118    object_property_add_child(OBJECT(parent), "mdio_child", OBJECT(Opaque),
 119                              NULL);
 120
 121    /* Set mdio property of gem device */
 122    object_property_set_link(OBJECT(parent), OBJECT(Opaque), "mdio", NULL);
 123    return 0;
 124}
 125
 126static int zynq7000_mdio_phy_create(char *node_path, FDTMachineInfo *fdti,
 127                                     void *Opaque)
 128{
 129    bool has_mdio = false;
 130    char parent_node_path[DT_PATH_LENGTH];
 131    DeviceState *dev;
 132    uint32_t reg;
 133
 134    if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
 135        abort();
 136    }
 137
 138    if (!strcmp(qemu_devtree_get_node_name(fdti->fdt, parent_node_path),
 139                "mdio")) {
 140        /* To not break the backward compatiblity lets also consider mdio node
 141         * dts can as be as below, with mdio node, when which we do not connect
 142         * mdio to ethernet instance as mdio node has other instance handler
 143         *
 144         * mdio {
 145         *    ethernet-phy@7 {
 146         *        reg = <0x7>;
 147         *        device_type = "ethernet-phy";
 148         *    };
 149         * };
 150         */
 151        has_mdio = true;
 152    }
 153
 154    if (!has_mdio) {
 155        zynq7000_mdio_phy_connect(node_path, fdti, Opaque);
 156    }
 157
 158    /* Wait for the parent to be created */
 159    while (!fdt_init_has_opaque(fdti, parent_node_path)) {
 160        fdt_init_yield(fdti);
 161    }
 162
 163    dev = DEVICE(object_new("88e1116r"));
 164    qdev_set_parent_bus(dev, qdev_get_child_bus(Opaque, "mdio-bus"));
 165    reg = qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg", 0, false,
 166                                NULL);
 167    object_property_set_int(OBJECT(dev), reg, "reg", NULL);
 168    return 0;
 169}
 170
 171static char *zynq7000_qspi_flash_node_clone(void *fdt)
 172{
 173    char qspi_node_path[DT_PATH_LENGTH];
 174    char qspi_new_node_path[DT_PATH_LENGTH];
 175    char *qspi_clone_name = NULL;
 176    uint32_t val[2];
 177
 178    /* clear node paths */
 179    memset(qspi_node_path, 0, sizeof(qspi_node_path));
 180    memset(qspi_new_node_path, 0, sizeof(qspi_new_node_path));
 181
 182    /* search for ps7 qspi node */
 183    int ret = qemu_devtree_node_by_compatible(fdt, qspi_node_path,
 184                                              "xlnx,zynq-qspi-1.0");
 185    if (ret == 0) {
 186        int qspi_is_dual = qemu_fdt_getprop_cell(fdt, qspi_node_path,
 187                                                 "is-dual", 0, false, NULL);
 188        /* Set bus-cells property to 1 */
 189        val[0] = cpu_to_be32(1);
 190        val[1] = 0;
 191        fdt_setprop(fdt, fdt_path_offset(fdt, qspi_node_path),
 192                    "#bus-cells", val, 4);
 193
 194        /* Generate dummy name */
 195        snprintf(qspi_new_node_path, DT_PATH_LENGTH, "%s/ps7-qspi-dummy@0",
 196                 qspi_node_path);
 197
 198        /* get the spi flash node to clone from (assume first child node) */
 199        int child_num = qemu_devtree_get_num_children(fdt, qspi_node_path, 1);
 200        char **child_flash = qemu_devtree_get_children(fdt, qspi_node_path, 1);
 201        if (child_num > 0) {
 202            char *compat_str = NULL;
 203            compat_str = qemu_fdt_getprop(fdt, child_flash[0],
 204                                          "compatible", NULL, false, NULL);
 205        /* Attach Default flash node to bus 1 */
 206        val[0] = 0;
 207        val[1] = 0;
 208        fdt_setprop(fdt, fdt_path_offset(fdt, child_flash[0]), "reg", val, 8);
 209
 210            /* Create the cloned node if the qspi controller is in dual spi mode
 211             * and the compatible string is avaliable */
 212            if (compat_str != NULL) {
 213                if (qspi_is_dual == 1) {
 214                    /* Clone first node, preserving only 'compatible' value */
 215                    qemu_fdt_add_subnode(fdt, qspi_new_node_path);
 216                    qemu_fdt_setprop_string(fdt, qspi_new_node_path,
 217                                             "compatible", compat_str);
 218                    qspi_clone_name = g_strdup(qspi_new_node_path);
 219
 220                    /* Attach Dummy flash node to bus 0 */
 221                    val[0] = 0;
 222                    val[1] = cpu_to_be32(1);
 223                    fdt_setprop(fdt, fdt_path_offset(fdt, qspi_new_node_path),
 224                                "reg", val, 8);
 225                }
 226                g_free(compat_str);
 227            }
 228        }
 229        g_free(child_flash);
 230    }
 231
 232    return qspi_clone_name;
 233}
 234
 235static memory_info init_memory(void *fdt, ram_addr_t ram_size, bool zynq_7000)
 236{
 237    FDTMachineInfo *fdti;
 238    char node_path[DT_PATH_LENGTH];
 239    MemoryRegion *mem_area;
 240    memory_info kernel_info;
 241    ram_addr_t start_addr;
 242    int mem_offset = 0;
 243
 244    /* Find a memory node or add new one if needed */
 245    while (qemu_devtree_get_node_by_name(fdt, node_path, "memory")) {
 246        qemu_fdt_add_subnode(fdt, "/memory@0");
 247        qemu_fdt_setprop_cells(fdt, "/memory@0", "reg", 0, ram_size);
 248    }
 249
 250    if (!qemu_fdt_getprop(fdt, "/memory", "compatible", NULL, 0, NULL)) {
 251        qemu_fdt_setprop_string(fdt, "/memory", "compatible",
 252                                "qemu:memory-region");
 253        qemu_fdt_setprop_cells(fdt, "/memory", "qemu,ram", 1);
 254    }
 255
 256    /* Instantiate peripherals from the FDT.  */
 257    fdti = fdt_generic_create_machine(fdt, NULL);
 258
 259    mem_area = MEMORY_REGION(object_resolve_path(node_path, NULL));
 260    kernel_info.ram_kernel_base = object_property_get_int(OBJECT(mem_area),
 261                                                          "addr", NULL);
 262    kernel_info.ram_kernel_size = object_property_get_int(OBJECT(mem_area),
 263                                                          "size", NULL);
 264
 265    if (zynq_7000) {
 266        do {
 267            mem_offset = fdt_node_offset_by_compatible(fdt, mem_offset,
 268                                                       "qemu:memory-region");
 269            if (mem_offset > 0) {
 270                fdt_get_path(fdt, mem_offset, node_path, DT_PATH_LENGTH);
 271                mem_area = MEMORY_REGION(object_resolve_path(node_path, NULL));
 272
 273                if (!memory_region_is_mapped(mem_area)) {
 274                    start_addr =  object_property_get_int(OBJECT(mem_area),
 275                                                          "addr", NULL);
 276                    memory_region_add_subregion(get_system_memory(),
 277                                                start_addr, mem_area);
 278                }
 279            }
 280        } while (mem_offset > 0);
 281    } else {
 282        /* Let's find out how much memory we have already created, then
 283         * based on what the user ser with '-m' let's add more if needed.
 284         */
 285        uint64_t reg_value, mem_created = 0;
 286        int mem_container;
 287        char mem_node_path[DT_PATH_LENGTH];
 288
 289        do {
 290            mem_offset =
 291                fdt_node_offset_by_compatible(fdt, mem_offset,
 292                                              "qemu:memory-region");
 293
 294            /* Check if we found anything and that it is top level memory */
 295            if (mem_offset > 0 &&
 296                    fdt_node_depth(fdt, mem_offset) == 1) {
 297                fdt_get_path(fdt, mem_offset, mem_node_path,
 298                             DT_PATH_LENGTH);
 299
 300                mem_container = qemu_fdt_getprop_cell(fdt, mem_node_path,
 301                                                      "container",
 302                                                      0, 0, NULL);
 303
 304                /* We only want RAM, so we filter to make sure the container of
 305                 * what we are looking at is the same as the main memory@0 node
 306                 * we just found above.
 307                 */
 308                if (mem_container != qemu_fdt_get_phandle(fdt, node_path)) {
 309                    continue;
 310                }
 311
 312                DB_PRINT(0, "Found top level memory region %s\n",
 313                         mem_node_path);
 314
 315                reg_value = qemu_fdt_getprop_cell(fdt, mem_node_path,
 316                                                  "reg", 0, 0, NULL);
 317                reg_value = reg_value << 32;
 318                reg_value += qemu_fdt_getprop_cell(fdt, mem_node_path,
 319                                                   "reg", 1, 0, NULL);
 320
 321                DB_PRINT(1, "    Address: 0x%" PRIx64 " ", reg_value);
 322
 323                reg_value += qemu_fdt_getprop_cell(fdt, mem_node_path,
 324                                                   "reg", 2, 0, NULL);
 325
 326                DB_PRINT_RAW(1, "Size: 0x%" PRIx64 "\n", reg_value);
 327
 328                /* Find the largest address (start address + size) */
 329                if (mem_created < reg_value) {
 330                    mem_created = reg_value;
 331                }
 332            }
 333        } while (mem_offset > 0);
 334
 335        DB_PRINT(0, "Highest memory address from DTS is: " \
 336                 "0x%" PRIx64 "/0x" RAM_ADDR_FMT "\n", mem_created, ram_size);
 337
 338        /* We now have the maximum amount of DDR that has been created. */
 339        if (mem_created == 0) {
 340            qemu_log_mask(LOG_GUEST_ERROR, "No memory was specified in the " \
 341                          "device tree, are there no memory nodes on the " \
 342                          "root level?\n");
 343        } else if (mem_created < ram_size) {
 344            /* We need to create more memory to match what the user asked for.
 345             * We do this based on the qemu:memory-region-spec values.
 346             */
 347            do {
 348                mem_offset =
 349                    fdt_node_offset_by_compatible(fdt, mem_offset,
 350                                                  "qemu:memory-region-spec");
 351
 352                if (mem_offset > 0) {
 353                    MemoryRegion *container;
 354                    MemoryRegion *ram_region = g_new(MemoryRegion, 1);
 355                    const char *region_name;
 356                    uint64_t region_start, region_size;
 357                    int container_offset, container_phandle, ram_prop;
 358
 359                    fdt_get_path(fdt, mem_offset, mem_node_path,
 360                                 DT_PATH_LENGTH);
 361
 362                    DB_PRINT(0, "Connecting %s\n", mem_node_path);
 363
 364                    region_name = fdt_get_name(fdt, mem_offset, NULL);
 365
 366                    /* This assumes two address cells and two size cells */
 367                    region_start = qemu_fdt_getprop_cell(fdt, mem_node_path,
 368                                                       "reg", 0, 0, NULL);
 369                    region_start = region_start << 32;
 370                    region_start += qemu_fdt_getprop_cell(fdt, mem_node_path,
 371                                                       "reg", 1, 0, NULL);
 372
 373                    DB_PRINT(1, "    Address: 0x%" PRIx64 " ", region_start);
 374
 375                    region_size = qemu_fdt_getprop_cell(fdt, mem_node_path,
 376                                                         "reg", 2, 0, NULL);
 377                    region_size = region_size << 32;
 378                    region_size += qemu_fdt_getprop_cell(fdt, mem_node_path,
 379                                                         "reg", 3, 0, NULL);
 380
 381                    region_size = MIN(region_size, ram_size - mem_created);
 382                    ram_size -= region_size;
 383
 384                    DB_PRINT_RAW(1, "Size: 0x%" PRIx64 "\n", region_size);
 385
 386                    container_phandle = qemu_fdt_getprop_cell(fdt,
 387                                                              mem_node_path,
 388                                                              "container", 0,
 389                                                              0, NULL);
 390                    container_offset =
 391                            fdt_node_offset_by_phandle(fdt, container_phandle);
 392                    fdt_get_path(fdt, container_offset,
 393                                 node_path, DT_PATH_LENGTH);
 394                    container = MEMORY_REGION(
 395                                        object_resolve_path(node_path, NULL));
 396
 397                    ram_prop = qemu_fdt_getprop_cell(fdt, mem_node_path,
 398                                                     "qemu,ram", 0,
 399                                                     0, NULL);
 400
 401                    memory_region_init_ram(ram_region, NULL, region_name,
 402                                           region_size, &error_fatal);
 403                    object_property_set_int(OBJECT(ram_region), ram_prop,
 404                                            "ram", &error_abort);
 405                    memory_region_add_subregion(container, region_start,
 406                                                ram_region);
 407                }
 408            } while (mem_offset > 0 && ram_size > mem_created);
 409        } else {
 410            /* The device tree generated more or equal amount of memory then
 411             * the user specified. Set that internally in QEMU.
 412             */
 413            DB_PRINT(0, "No extra memory is required\n");
 414
 415            ram_size = mem_created;
 416            qemu_opt_set_number(qemu_find_opts_singleton("memory"), "size",
 417                                mem_created, &error_fatal);
 418        }
 419    }
 420
 421    fdt_init_destroy_fdti(fdti);
 422
 423    return kernel_info;
 424}
 425
 426static void arm_generic_fdt_init(MachineState *machine)
 427{
 428    void *fdt = NULL, *sw_fdt = NULL;
 429    int fdt_size, sw_fdt_size;
 430    const char *dtb_arg, *hw_dtb_arg;
 431    char node_path[DT_PATH_LENGTH];
 432    char *qspi_clone_spi_flash_node_name = NULL;
 433    memory_info kernel_info;
 434    bool zynq_7000 = false;
 435
 436    /* If booting a Zynq-7000 Machine*/
 437    if (!strcmp(MACHINE_GET_CLASS(machine)->name, ZYNQ7000_MACHINE_NAME)) {
 438        zynq_7000 = true;
 439    } else if (!strcmp(MACHINE_GET_CLASS(machine)->name,
 440                       DEP_GENERAL_MACHINE_NAME)) {
 441        if (!QTEST_RUNNING) {
 442            /* Don't print this error if running qtest */
 443            fprintf(stderr, "The '" DEP_GENERAL_MACHINE_NAME "' machine has " \
 444                    "been deprecated and will be removed after the 2017.4 " \
 445                    "release.Please use '" ZYNQ7000_MACHINE_NAME \
 446                    "' instead.\n");
 447        }
 448        zynq_7000 = true;
 449    }
 450
 451    dtb_arg = qemu_opt_get(qemu_get_machine_opts(), "dtb");
 452    hw_dtb_arg = qemu_opt_get(qemu_get_machine_opts(), "hw-dtb");
 453    if (!dtb_arg && !hw_dtb_arg) {
 454        if (!QTEST_RUNNING) {
 455            /* Just return without error if running qtest, as we never have a
 456             * device tree
 457             */
 458            hw_error("DTB must be specified for %s machine model\n",
 459                     MACHINE_GET_CLASS(machine)->name);
 460        }
 461        return;
 462    }
 463
 464    /* Software dtb is always the -dtb arg */
 465    if (dtb_arg) {
 466        sw_fdt = load_device_tree(dtb_arg, &sw_fdt_size);
 467        if (!sw_fdt) {
 468            error_report("Error: Unable to load Device Tree %s", dtb_arg);
 469            exit(1);
 470        }
 471    }
 472
 473    /* If the user provided a -hw-dtb, use it as the hw description.  */
 474    if (hw_dtb_arg) {
 475        fdt = load_device_tree(hw_dtb_arg, &fdt_size);
 476        if (!fdt) {
 477            error_report("Error: Unable to load Device Tree %s", hw_dtb_arg);
 478            exit(1);
 479        }
 480    } else if (sw_fdt) {
 481        fdt = sw_fdt;
 482        fdt_size = sw_fdt_size;
 483    }
 484
 485    if (zynq_7000) {
 486        int node_offset = 0;
 487
 488        /* Added a dummy flash node, if is-dual property is set to 1*/
 489        qspi_clone_spi_flash_node_name = zynq7000_qspi_flash_node_clone(fdt);
 490
 491        /* Ensure that an interrupt controller exists before disabling it */
 492        if (!qemu_devtree_get_node_by_name(fdt, node_path,
 493                                           "interrupt-controller")) {
 494            qemu_fdt_setprop_cells(fdt, node_path,
 495                                   "disable-linux-gic-init", true);
 496        }
 497
 498        /* The Zynq-7000 device tree doesn't contain information about the
 499         * Configuation Base Address Register (reset-cbar) but we need to set
 500         * it in order for Linux to find the SCU. So add it into the device
 501         * tree for every A9 CPU.
 502         */
 503        do {
 504            node_offset = fdt_node_offset_by_compatible(fdt, node_offset,
 505                                                        "arm,cortex-a9");
 506            if (node_offset > 0) {
 507                fdt_get_path(fdt, node_offset, node_path, DT_PATH_LENGTH);
 508                qemu_fdt_setprop_cells(fdt, node_path, "reset-cbar",
 509                                       ZYNQ7000_MPCORE_PERIPHBASE);
 510            }
 511        } while (node_offset > 0);
 512    }
 513
 514    kernel_info = init_memory(fdt, machine->ram_size, zynq_7000);
 515
 516    arm_generic_fdt_binfo.fdt = sw_fdt;
 517    arm_generic_fdt_binfo.fdt_size = sw_fdt_size;
 518    arm_generic_fdt_binfo.ram_size = kernel_info.ram_kernel_size;
 519    arm_generic_fdt_binfo.kernel_filename = machine->kernel_filename;
 520    arm_generic_fdt_binfo.kernel_cmdline = machine->kernel_cmdline;
 521    arm_generic_fdt_binfo.initrd_filename = machine->initrd_filename;
 522    arm_generic_fdt_binfo.nb_cpus = fdt_generic_num_cpus;
 523    arm_generic_fdt_binfo.write_secondary_boot = arm_write_secondary_boot;
 524    arm_generic_fdt_binfo.smp_loader_start = SMP_BOOT_ADDR;
 525    arm_generic_fdt_binfo.smp_bootreg_addr = SMP_BOOTREG_ADDR;
 526    arm_generic_fdt_binfo.board_id = 0xd32;
 527    arm_generic_fdt_binfo.loader_start = kernel_info.ram_kernel_base;
 528    arm_generic_fdt_binfo.secure_boot = true;
 529
 530    if (qspi_clone_spi_flash_node_name != NULL) {
 531        /* Remove cloned DTB node */
 532        int offset = fdt_path_offset(fdt, qspi_clone_spi_flash_node_name);
 533        fdt_del_node(fdt, offset);
 534        g_free(qspi_clone_spi_flash_node_name);
 535    }
 536
 537    if (zynq_7000) {
 538        zynq7000_usb_nuke_phy(fdt);
 539    }
 540
 541    if (machine->kernel_filename) {
 542        arm_load_kernel(ARM_CPU(first_cpu), &arm_generic_fdt_binfo);
 543    }
 544
 545    return;
 546}
 547
 548static void arm_generic_fdt_7000_init(MachineState *machine)
 549{
 550    MemoryRegion *address_space_mem = get_system_memory();
 551    DeviceState *dev;
 552    SysBusDevice *busdev;
 553    MemoryRegion *ocm_ram;
 554    DriveInfo *dinfo;
 555    DeviceState *att_dev;
 556
 557    ocm_ram = g_new(MemoryRegion, 1);
 558    memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10,
 559                           &error_abort);
 560    vmstate_register_ram_global(ocm_ram);
 561    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
 562
 563    dev = qdev_create(NULL, "arm.pl35x");
 564    object_property_add_child(container_get(qdev_get_machine(), "/unattached"),
 565                              "pl353", OBJECT(dev), NULL);
 566    qdev_prop_set_uint8(dev, "x", 3);
 567    dinfo = drive_get_next(IF_PFLASH);
 568    att_dev = nand_init(dinfo ? blk_by_legacy_dinfo(dinfo)
 569                              : NULL,
 570                        NAND_MFR_STMICRO, 0xaa);
 571    object_property_set_link(OBJECT(dev), OBJECT(att_dev), "dev1",
 572                             &error_abort);
 573
 574    qdev_init_nofail(dev);
 575    busdev = SYS_BUS_DEVICE(dev);
 576    sysbus_mmio_map(busdev, 0, 0xe000e000);
 577    sysbus_mmio_map(busdev, 2, 0xe1000000);
 578
 579    /* Mark the simple-bus as incompatible as it breaks the Zynq boot */
 580    add_to_compat_table(NULL, "compatible:simple-bus", NULL);
 581
 582    dev = qdev_create(NULL, "mdio");
 583    qdev_init_nofail(dev);
 584    /* Add MDIO Connect Call back */
 585    add_to_inst_bind_table(zynq7000_mdio_phy_connect, "mdio", dev);
 586    add_to_compat_table(zynq7000_mdio_phy_create, "device_type:ethernet-phy",
 587                        dev);
 588
 589    arm_generic_fdt_init(machine);
 590
 591    dev = qdev_create(NULL, "a9-scu");
 592    busdev = SYS_BUS_DEVICE(dev);
 593    qdev_prop_set_uint32(dev, "num-cpu", fdt_generic_num_cpus);
 594    qdev_init_nofail(dev);
 595    sysbus_mmio_map(busdev, 0, ZYNQ7000_MPCORE_PERIPHBASE);
 596}
 597
 598static void arm_generic_fdt_machine_init(MachineClass *mc)
 599{
 600    mc->desc = "ARM device tree driven machine model";
 601    mc->init = arm_generic_fdt_init;
 602    mc->max_cpus = MAX_CPUS;
 603}
 604
 605static void arm_generic_fdt_7000_machine_init(MachineClass *mc)
 606{
 607    mc->desc = "ARM device tree driven machine model for the Zynq-7000";
 608    mc->init = arm_generic_fdt_7000_init;
 609    mc->max_cpus = MAX_CPUS;
 610}
 611
 612/* Deprecated, remove this */
 613static void arm_generic_fdt_dep_machine_init(MachineClass *mc)
 614{
 615    mc->desc = "Deprecated ARM device tree driven machine for the Zynq-7000";
 616    mc->init = arm_generic_fdt_7000_init;
 617    mc->max_cpus = MAX_CPUS;
 618}
 619
 620fdt_register_compatibility_opaque(pflash_cfi01_fdt_init,
 621                                  "compatibile:cfi-flash", 0, NULL);
 622
 623DEFINE_MACHINE(GENERAL_MACHINE_NAME, arm_generic_fdt_machine_init)
 624DEFINE_MACHINE(ZYNQ7000_MACHINE_NAME, arm_generic_fdt_7000_machine_init)
 625DEFINE_MACHINE(DEP_GENERAL_MACHINE_NAME, arm_generic_fdt_dep_machine_init)
 626