qemu/hw/arm/fsl-imx25.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
   3 *
   4 * i.MX25 SOC emulation.
   5 *
   6 * Based on hw/arm/xlnx-zynqmp.c
   7 *
   8 * Copyright (C) 2015 Xilinx Inc
   9 * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
  10 *
  11 *  This program is free software; you can redistribute it and/or modify it
  12 *  under the terms of the GNU General Public License as published by the
  13 *  Free Software Foundation; either version 2 of the License, or
  14 *  (at your option) any later version.
  15 *
  16 *  This program is distributed in the hope that it will be useful, but WITHOUT
  17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  18 *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  19 *  for more details.
  20 *
  21 *  You should have received a copy of the GNU General Public License along
  22 *  with this program; if not, see <http://www.gnu.org/licenses/>.
  23 */
  24
  25#include "hw/arm/fsl-imx25.h"
  26#include "sysemu/sysemu.h"
  27#include "exec/address-spaces.h"
  28#include "hw/boards.h"
  29#include "sysemu/char.h"
  30
  31static void fsl_imx25_init(Object *obj)
  32{
  33    FslIMX25State *s = FSL_IMX25(obj);
  34    int i;
  35
  36    object_initialize(&s->cpu, sizeof(s->cpu), "arm926-" TYPE_ARM_CPU);
  37
  38    object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
  39    qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
  40
  41    object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
  42    qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
  43
  44    for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
  45        object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
  46        qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
  47    }
  48
  49    for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
  50        object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT);
  51        qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default());
  52    }
  53
  54    for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
  55        object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
  56        qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
  57    }
  58
  59    object_initialize(&s->fec, sizeof(s->fec), TYPE_IMX_FEC);
  60    qdev_set_parent_bus(DEVICE(&s->fec), sysbus_get_default());
  61
  62    for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
  63        object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
  64        qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
  65    }
  66
  67    for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
  68        object_initialize(&s->gpio[i], sizeof(s->gpio[i]), TYPE_IMX_GPIO);
  69        qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus_get_default());
  70    }
  71}
  72
  73static void fsl_imx25_realize(DeviceState *dev, Error **errp)
  74{
  75    FslIMX25State *s = FSL_IMX25(dev);
  76    uint8_t i;
  77    Error *err = NULL;
  78
  79    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
  80    if (err) {
  81        error_propagate(errp, err);
  82        return;
  83    }
  84
  85    object_property_set_bool(OBJECT(&s->avic), true, "realized", &err);
  86    if (err) {
  87        error_propagate(errp, err);
  88        return;
  89    }
  90    sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX25_AVIC_ADDR);
  91    sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
  92                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
  93    sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
  94                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
  95
  96    object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
  97    if (err) {
  98        error_propagate(errp, err);
  99        return;
 100    }
 101    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX25_CCM_ADDR);
 102
 103    /* Initialize all UARTs */
 104    for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
 105        static const struct {
 106            hwaddr addr;
 107            unsigned int irq;
 108        } serial_table[FSL_IMX25_NUM_UARTS] = {
 109            { FSL_IMX25_UART1_ADDR, FSL_IMX25_UART1_IRQ },
 110            { FSL_IMX25_UART2_ADDR, FSL_IMX25_UART2_IRQ },
 111            { FSL_IMX25_UART3_ADDR, FSL_IMX25_UART3_IRQ },
 112            { FSL_IMX25_UART4_ADDR, FSL_IMX25_UART4_IRQ },
 113            { FSL_IMX25_UART5_ADDR, FSL_IMX25_UART5_IRQ }
 114        };
 115
 116        if (i < MAX_SERIAL_PORTS) {
 117            CharDriverState *chr;
 118
 119            chr = serial_hds[i];
 120
 121            if (!chr) {
 122                char label[20];
 123                snprintf(label, sizeof(label), "imx31.uart%d", i);
 124                chr = qemu_chr_new(label, "null", NULL);
 125            }
 126
 127            qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
 128        }
 129
 130        object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
 131        if (err) {
 132            error_propagate(errp, err);
 133            return;
 134        }
 135        sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
 136        sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
 137                           qdev_get_gpio_in(DEVICE(&s->avic),
 138                                            serial_table[i].irq));
 139    }
 140
 141    /* Initialize all GPT timers */
 142    for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
 143        static const struct {
 144            hwaddr addr;
 145            unsigned int irq;
 146        } gpt_table[FSL_IMX25_NUM_GPTS] = {
 147            { FSL_IMX25_GPT1_ADDR, FSL_IMX25_GPT1_IRQ },
 148            { FSL_IMX25_GPT2_ADDR, FSL_IMX25_GPT2_IRQ },
 149            { FSL_IMX25_GPT3_ADDR, FSL_IMX25_GPT3_IRQ },
 150            { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
 151        };
 152
 153        s->gpt[i].ccm = DEVICE(&s->ccm);
 154
 155        object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
 156        if (err) {
 157            error_propagate(errp, err);
 158            return;
 159        }
 160        sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr);
 161        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
 162                           qdev_get_gpio_in(DEVICE(&s->avic),
 163                                            gpt_table[i].irq));
 164    }
 165
 166    /* Initialize all EPIT timers */
 167    for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
 168        static const struct {
 169            hwaddr addr;
 170            unsigned int irq;
 171        } epit_table[FSL_IMX25_NUM_EPITS] = {
 172            { FSL_IMX25_EPIT1_ADDR, FSL_IMX25_EPIT1_IRQ },
 173            { FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
 174        };
 175
 176        s->epit[i].ccm = DEVICE(&s->ccm);
 177
 178        object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
 179        if (err) {
 180            error_propagate(errp, err);
 181            return;
 182        }
 183        sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
 184        sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
 185                           qdev_get_gpio_in(DEVICE(&s->avic),
 186                                            epit_table[i].irq));
 187    }
 188
 189    qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
 190    object_property_set_bool(OBJECT(&s->fec), true, "realized", &err);
 191    if (err) {
 192        error_propagate(errp, err);
 193        return;
 194    }
 195    sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, FSL_IMX25_FEC_ADDR);
 196    sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0,
 197                       qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ));
 198
 199
 200    /* Initialize all I2C */
 201    for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
 202        static const struct {
 203            hwaddr addr;
 204            unsigned int irq;
 205        } i2c_table[FSL_IMX25_NUM_I2CS] = {
 206            { FSL_IMX25_I2C1_ADDR, FSL_IMX25_I2C1_IRQ },
 207            { FSL_IMX25_I2C2_ADDR, FSL_IMX25_I2C2_IRQ },
 208            { FSL_IMX25_I2C3_ADDR, FSL_IMX25_I2C3_IRQ }
 209        };
 210
 211        object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
 212        if (err) {
 213            error_propagate(errp, err);
 214            return;
 215        }
 216        sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
 217        sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
 218                           qdev_get_gpio_in(DEVICE(&s->avic),
 219                                            i2c_table[i].irq));
 220    }
 221
 222    /* Initialize all GPIOs */
 223    for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
 224        static const struct {
 225            hwaddr addr;
 226            unsigned int irq;
 227        } gpio_table[FSL_IMX25_NUM_GPIOS] = {
 228            { FSL_IMX25_GPIO1_ADDR, FSL_IMX25_GPIO1_IRQ },
 229            { FSL_IMX25_GPIO2_ADDR, FSL_IMX25_GPIO2_IRQ },
 230            { FSL_IMX25_GPIO3_ADDR, FSL_IMX25_GPIO3_IRQ },
 231            { FSL_IMX25_GPIO4_ADDR, FSL_IMX25_GPIO4_IRQ }
 232        };
 233
 234        object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err);
 235        if (err) {
 236            error_propagate(errp, err);
 237            return;
 238        }
 239        sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
 240        /* Connect GPIO IRQ to PIC */
 241        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
 242                           qdev_get_gpio_in(DEVICE(&s->avic),
 243                                            gpio_table[i].irq));
 244    }
 245
 246    /* initialize 2 x 16 KB ROM */
 247    memory_region_init_rom_device(&s->rom[0], NULL, NULL, NULL,
 248                                  "imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
 249    if (err) {
 250        error_propagate(errp, err);
 251        return;
 252    }
 253    memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
 254                                &s->rom[0]);
 255    memory_region_init_rom_device(&s->rom[1], NULL, NULL, NULL,
 256                                  "imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
 257    if (err) {
 258        error_propagate(errp, err);
 259        return;
 260    }
 261    memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM1_ADDR,
 262                                &s->rom[1]);
 263
 264    /* initialize internal RAM (128 KB) */
 265    memory_region_init_ram(&s->iram, NULL, "imx25.iram", FSL_IMX25_IRAM_SIZE,
 266                           &err);
 267    if (err) {
 268        error_propagate(errp, err);
 269        return;
 270    }
 271    memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ADDR,
 272                                &s->iram);
 273    vmstate_register_ram_global(&s->iram);
 274
 275    /* internal RAM (128 KB) is aliased over 128 MB - 128 KB */
 276    memory_region_init_alias(&s->iram_alias, NULL, "imx25.iram_alias",
 277                             &s->iram, 0, FSL_IMX25_IRAM_ALIAS_SIZE);
 278    memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ALIAS_ADDR,
 279                                &s->iram_alias);
 280}
 281
 282static void fsl_imx25_class_init(ObjectClass *oc, void *data)
 283{
 284    DeviceClass *dc = DEVICE_CLASS(oc);
 285
 286    dc->realize = fsl_imx25_realize;
 287
 288    /*
 289     * Reason: creates an ARM CPU, thus use after free(), see
 290     * arm_cpu_class_init()
 291     */
 292    dc->cannot_destroy_with_object_finalize_yet = true;
 293}
 294
 295static const TypeInfo fsl_imx25_type_info = {
 296    .name = TYPE_FSL_IMX25,
 297    .parent = TYPE_DEVICE,
 298    .instance_size = sizeof(FslIMX25State),
 299    .instance_init = fsl_imx25_init,
 300    .class_init = fsl_imx25_class_init,
 301};
 302
 303static void fsl_imx25_register_types(void)
 304{
 305    type_register_static(&fsl_imx25_type_info);
 306}
 307
 308type_init(fsl_imx25_register_types)
 309