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 "qemu/osdep.h"
  26#include "qapi/error.h"
  27#include "hw/arm/fsl-imx25.h"
  28#include "sysemu/sysemu.h"
  29#include "hw/qdev-properties.h"
  30#include "chardev/char.h"
  31
  32#define IMX25_ESDHC_CAPABILITIES     0x07e20000
  33
  34static void fsl_imx25_init(Object *obj)
  35{
  36    FslIMX25State *s = FSL_IMX25(obj);
  37    int i;
  38
  39    object_initialize_child(obj, "cpu", &s->cpu, ARM_CPU_TYPE_NAME("arm926"));
  40
  41    object_initialize_child(obj, "avic", &s->avic, TYPE_IMX_AVIC);
  42
  43    object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX25_CCM);
  44
  45    for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
  46        object_initialize_child(obj, "uart[*]", &s->uart[i], TYPE_IMX_SERIAL);
  47    }
  48
  49    for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
  50        object_initialize_child(obj, "gpt[*]", &s->gpt[i], TYPE_IMX25_GPT);
  51    }
  52
  53    for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
  54        object_initialize_child(obj, "epit[*]", &s->epit[i], TYPE_IMX_EPIT);
  55    }
  56
  57    object_initialize_child(obj, "fec", &s->fec, TYPE_IMX_FEC);
  58
  59    object_initialize_child(obj, "rngc", &s->rngc, TYPE_IMX_RNGC);
  60
  61    for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
  62        object_initialize_child(obj, "i2c[*]", &s->i2c[i], TYPE_IMX_I2C);
  63    }
  64
  65    for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
  66        object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_IMX_GPIO);
  67    }
  68
  69    for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
  70        object_initialize_child(obj, "sdhc[*]", &s->esdhc[i], TYPE_IMX_USDHC);
  71    }
  72
  73    for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
  74        object_initialize_child(obj, "usb[*]", &s->usb[i], TYPE_CHIPIDEA);
  75    }
  76
  77    object_initialize_child(obj, "wdt", &s->wdt, TYPE_IMX2_WDT);
  78}
  79
  80static void fsl_imx25_realize(DeviceState *dev, Error **errp)
  81{
  82    FslIMX25State *s = FSL_IMX25(dev);
  83    uint8_t i;
  84    Error *err = NULL;
  85
  86    if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) {
  87        return;
  88    }
  89
  90    if (!sysbus_realize(SYS_BUS_DEVICE(&s->avic), errp)) {
  91        return;
  92    }
  93    sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX25_AVIC_ADDR);
  94    sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
  95                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
  96    sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
  97                       qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
  98
  99    if (!sysbus_realize(SYS_BUS_DEVICE(&s->ccm), errp)) {
 100        return;
 101    }
 102    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX25_CCM_ADDR);
 103
 104    /* Initialize all UARTs */
 105    for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
 106        static const struct {
 107            hwaddr addr;
 108            unsigned int irq;
 109        } serial_table[FSL_IMX25_NUM_UARTS] = {
 110            { FSL_IMX25_UART1_ADDR, FSL_IMX25_UART1_IRQ },
 111            { FSL_IMX25_UART2_ADDR, FSL_IMX25_UART2_IRQ },
 112            { FSL_IMX25_UART3_ADDR, FSL_IMX25_UART3_IRQ },
 113            { FSL_IMX25_UART4_ADDR, FSL_IMX25_UART4_IRQ },
 114            { FSL_IMX25_UART5_ADDR, FSL_IMX25_UART5_IRQ }
 115        };
 116
 117        qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
 118
 119        if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart[i]), errp)) {
 120            return;
 121        }
 122        sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
 123        sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
 124                           qdev_get_gpio_in(DEVICE(&s->avic),
 125                                            serial_table[i].irq));
 126    }
 127
 128    /* Initialize all GPT timers */
 129    for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
 130        static const struct {
 131            hwaddr addr;
 132            unsigned int irq;
 133        } gpt_table[FSL_IMX25_NUM_GPTS] = {
 134            { FSL_IMX25_GPT1_ADDR, FSL_IMX25_GPT1_IRQ },
 135            { FSL_IMX25_GPT2_ADDR, FSL_IMX25_GPT2_IRQ },
 136            { FSL_IMX25_GPT3_ADDR, FSL_IMX25_GPT3_IRQ },
 137            { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
 138        };
 139
 140        s->gpt[i].ccm = IMX_CCM(&s->ccm);
 141
 142        if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpt[i]), errp)) {
 143            return;
 144        }
 145        sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr);
 146        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
 147                           qdev_get_gpio_in(DEVICE(&s->avic),
 148                                            gpt_table[i].irq));
 149    }
 150
 151    /* Initialize all EPIT timers */
 152    for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
 153        static const struct {
 154            hwaddr addr;
 155            unsigned int irq;
 156        } epit_table[FSL_IMX25_NUM_EPITS] = {
 157            { FSL_IMX25_EPIT1_ADDR, FSL_IMX25_EPIT1_IRQ },
 158            { FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
 159        };
 160
 161        s->epit[i].ccm = IMX_CCM(&s->ccm);
 162
 163        if (!sysbus_realize(SYS_BUS_DEVICE(&s->epit[i]), errp)) {
 164            return;
 165        }
 166        sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
 167        sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
 168                           qdev_get_gpio_in(DEVICE(&s->avic),
 169                                            epit_table[i].irq));
 170    }
 171
 172    object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err);
 173    qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
 174
 175    if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) {
 176        return;
 177    }
 178    sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, FSL_IMX25_FEC_ADDR);
 179    sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0,
 180                       qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ));
 181
 182    if (!sysbus_realize(SYS_BUS_DEVICE(&s->rngc), errp)) {
 183        return;
 184    }
 185    sysbus_mmio_map(SYS_BUS_DEVICE(&s->rngc), 0, FSL_IMX25_RNGC_ADDR);
 186    sysbus_connect_irq(SYS_BUS_DEVICE(&s->rngc), 0,
 187                       qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_RNGC_IRQ));
 188
 189    /* Initialize all I2C */
 190    for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
 191        static const struct {
 192            hwaddr addr;
 193            unsigned int irq;
 194        } i2c_table[FSL_IMX25_NUM_I2CS] = {
 195            { FSL_IMX25_I2C1_ADDR, FSL_IMX25_I2C1_IRQ },
 196            { FSL_IMX25_I2C2_ADDR, FSL_IMX25_I2C2_IRQ },
 197            { FSL_IMX25_I2C3_ADDR, FSL_IMX25_I2C3_IRQ }
 198        };
 199
 200        if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c[i]), errp)) {
 201            return;
 202        }
 203        sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
 204        sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
 205                           qdev_get_gpio_in(DEVICE(&s->avic),
 206                                            i2c_table[i].irq));
 207    }
 208
 209    /* Initialize all GPIOs */
 210    for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
 211        static const struct {
 212            hwaddr addr;
 213            unsigned int irq;
 214        } gpio_table[FSL_IMX25_NUM_GPIOS] = {
 215            { FSL_IMX25_GPIO1_ADDR, FSL_IMX25_GPIO1_IRQ },
 216            { FSL_IMX25_GPIO2_ADDR, FSL_IMX25_GPIO2_IRQ },
 217            { FSL_IMX25_GPIO3_ADDR, FSL_IMX25_GPIO3_IRQ },
 218            { FSL_IMX25_GPIO4_ADDR, FSL_IMX25_GPIO4_IRQ }
 219        };
 220
 221        if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
 222            return;
 223        }
 224        sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
 225        /* Connect GPIO IRQ to PIC */
 226        sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
 227                           qdev_get_gpio_in(DEVICE(&s->avic),
 228                                            gpio_table[i].irq));
 229    }
 230
 231    /* Initialize all SDHC */
 232    for (i = 0; i < FSL_IMX25_NUM_ESDHCS; i++) {
 233        static const struct {
 234            hwaddr addr;
 235            unsigned int irq;
 236        } esdhc_table[FSL_IMX25_NUM_ESDHCS] = {
 237            { FSL_IMX25_ESDHC1_ADDR, FSL_IMX25_ESDHC1_IRQ },
 238            { FSL_IMX25_ESDHC2_ADDR, FSL_IMX25_ESDHC2_IRQ },
 239        };
 240
 241        object_property_set_uint(OBJECT(&s->esdhc[i]), "sd-spec-version", 2,
 242                                 &error_abort);
 243        object_property_set_uint(OBJECT(&s->esdhc[i]), "capareg",
 244                                 IMX25_ESDHC_CAPABILITIES, &error_abort);
 245        object_property_set_uint(OBJECT(&s->esdhc[i]), "vendor",
 246                                 SDHCI_VENDOR_IMX, &error_abort);
 247        if (!sysbus_realize(SYS_BUS_DEVICE(&s->esdhc[i]), errp)) {
 248            return;
 249        }
 250        sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr);
 251        sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0,
 252                           qdev_get_gpio_in(DEVICE(&s->avic),
 253                                            esdhc_table[i].irq));
 254    }
 255
 256    /* USB */
 257    for (i = 0; i < FSL_IMX25_NUM_USBS; i++) {
 258        static const struct {
 259            hwaddr addr;
 260            unsigned int irq;
 261        } usb_table[FSL_IMX25_NUM_USBS] = {
 262            { FSL_IMX25_USB1_ADDR, FSL_IMX25_USB1_IRQ },
 263            { FSL_IMX25_USB2_ADDR, FSL_IMX25_USB2_IRQ },
 264        };
 265
 266        sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), &error_abort);
 267        sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_table[i].addr);
 268        sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i]), 0,
 269                           qdev_get_gpio_in(DEVICE(&s->avic),
 270                                            usb_table[i].irq));
 271    }
 272
 273    /* Watchdog */
 274    object_property_set_bool(OBJECT(&s->wdt), "pretimeout-support", true,
 275                             &error_abort);
 276    sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_abort);
 277    sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX25_WDT_ADDR);
 278    sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt), 0,
 279                                      qdev_get_gpio_in(DEVICE(&s->avic),
 280                                                       FSL_IMX25_WDT_IRQ));
 281
 282    /* initialize 2 x 16 KB ROM */
 283    memory_region_init_rom(&s->rom[0], OBJECT(dev), "imx25.rom0",
 284                           FSL_IMX25_ROM0_SIZE, &err);
 285    if (err) {
 286        error_propagate(errp, err);
 287        return;
 288    }
 289    memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
 290                                &s->rom[0]);
 291    memory_region_init_rom(&s->rom[1], OBJECT(dev), "imx25.rom1",
 292                           FSL_IMX25_ROM1_SIZE, &err);
 293    if (err) {
 294        error_propagate(errp, err);
 295        return;
 296    }
 297    memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM1_ADDR,
 298                                &s->rom[1]);
 299
 300    /* initialize internal RAM (128 KB) */
 301    memory_region_init_ram(&s->iram, NULL, "imx25.iram", FSL_IMX25_IRAM_SIZE,
 302                           &err);
 303    if (err) {
 304        error_propagate(errp, err);
 305        return;
 306    }
 307    memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ADDR,
 308                                &s->iram);
 309
 310    /* internal RAM (128 KB) is aliased over 128 MB - 128 KB */
 311    memory_region_init_alias(&s->iram_alias, OBJECT(dev), "imx25.iram_alias",
 312                             &s->iram, 0, FSL_IMX25_IRAM_ALIAS_SIZE);
 313    memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ALIAS_ADDR,
 314                                &s->iram_alias);
 315}
 316
 317static Property fsl_imx25_properties[] = {
 318    DEFINE_PROP_UINT32("fec-phy-num", FslIMX25State, phy_num, 0),
 319    DEFINE_PROP_END_OF_LIST(),
 320};
 321
 322static void fsl_imx25_class_init(ObjectClass *oc, void *data)
 323{
 324    DeviceClass *dc = DEVICE_CLASS(oc);
 325
 326    device_class_set_props(dc, fsl_imx25_properties);
 327    dc->realize = fsl_imx25_realize;
 328    dc->desc = "i.MX25 SOC";
 329    /*
 330     * Reason: uses serial_hds in realize and the imx25 board does not
 331     * support multiple CPUs
 332     */
 333    dc->user_creatable = false;
 334}
 335
 336static const TypeInfo fsl_imx25_type_info = {
 337    .name = TYPE_FSL_IMX25,
 338    .parent = TYPE_DEVICE,
 339    .instance_size = sizeof(FslIMX25State),
 340    .instance_init = fsl_imx25_init,
 341    .class_init = fsl_imx25_class_init,
 342};
 343
 344static void fsl_imx25_register_types(void)
 345{
 346    type_register_static(&fsl_imx25_type_info);
 347}
 348
 349type_init(fsl_imx25_register_types)
 350