qemu/hw/gpio/xilinx_iomod_gpo.c
<<
>>
Prefs
   1/*
   2 * QEMU model of Xilinx I/O Module GPO
   3 *
   4 * Copyright (c) 2013 Xilinx Inc
   5 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "hw/sysbus.h"
  28#include "hw/register.h"
  29#include "qemu/log.h"
  30
  31#ifndef XILINX_IO_MODULE_GPO_ERR_DEBUG
  32#define XILINX_IO_MODULE_GPO_ERR_DEBUG 0
  33#endif
  34
  35#define TYPE_XILINX_IO_MODULE_GPO "xlnx.io_gpo"
  36
  37#define XILINX_IO_MODULE_GPO(obj) \
  38     OBJECT_CHECK(XilinxGPO, (obj), TYPE_XILINX_IO_MODULE_GPO)
  39
  40#define R_IOM_GPO                   (0x00 / 4)
  41#define R_MAX                       (1)
  42
  43typedef struct XilinxGPO {
  44    SysBusDevice parent_obj;
  45    MemoryRegion iomem;
  46
  47    struct {
  48        bool use;
  49        uint32_t size;
  50        uint32_t init;
  51    } cfg;
  52    RegisterInfo regs_info[R_MAX];
  53
  54    qemu_irq outputs[32];
  55    const char *prefix;
  56} XilinxGPO;
  57
  58static Property xlx_iom_properties[] = {
  59    DEFINE_PROP_BOOL("use-gpo", XilinxGPO, cfg.use, 0),
  60    DEFINE_PROP_UINT32("gpo-size", XilinxGPO, cfg.size, 0),
  61    DEFINE_PROP_UINT32("gpo-init", XilinxGPO, cfg.init, 0),
  62    DEFINE_PROP_END_OF_LIST(),
  63};
  64
  65static const MemoryRegionOps iom_gpo_ops = {
  66    .read = register_read_memory_le,
  67    .write = register_write_memory_le,
  68    .endianness = DEVICE_LITTLE_ENDIAN,
  69    .valid = {
  70        .min_access_size = 4,
  71        .max_access_size = 4,
  72    },
  73};
  74
  75static void gpo_pw(RegisterInfo *reg, uint64_t value)
  76{
  77    XilinxGPO *s = XILINX_IO_MODULE_GPO(reg->opaque);
  78    unsigned int i;
  79
  80    for (i = 0; i < s->cfg.size; i++) {
  81        bool flag = !!(value & (1 << i));
  82        qemu_set_irq(s->outputs[i], flag);
  83    }
  84}
  85
  86static uint64_t gpo_pr(RegisterInfo *reg, uint64_t value)
  87{
  88    return 0;
  89}
  90
  91static const RegisterAccessInfo gpo_regs_info[] = {
  92    [R_IOM_GPO] = { .name = "GPO", .post_write = gpo_pw, .post_read = gpo_pr, },
  93};
  94
  95static void iom_gpo_reset(DeviceState *dev)
  96{
  97    XilinxGPO *s = XILINX_IO_MODULE_GPO(dev);
  98
  99    gpo_pw(&s->regs_info[R_IOM_GPO], s->cfg.init);
 100}
 101
 102static void xlx_iom_realize(DeviceState *dev, Error **errp)
 103{
 104    XilinxGPO *s = XILINX_IO_MODULE_GPO(dev);
 105    unsigned int i;
 106    s->prefix = object_get_canonical_path(OBJECT(dev));
 107
 108    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 109        RegisterInfo *r = &s->regs_info[i];
 110
 111        *r = (RegisterInfo) {
 112            .data_size = sizeof(uint32_t),
 113            .access = &gpo_regs_info[i],
 114            .debug = XILINX_IO_MODULE_GPO_ERR_DEBUG,
 115            .prefix = s->prefix,
 116            .opaque = s,
 117        };
 118        memory_region_init_io(&r->mem, OBJECT(dev), &iom_gpo_ops, r,
 119                              r->access->name, 4);
 120        memory_region_add_subregion(&s->iomem, i * 4, &r->mem);
 121    }
 122
 123    assert(s->cfg.size <= 32);
 124    qdev_init_gpio_out(dev, s->outputs, s->cfg.size);
 125}
 126
 127static void xlx_iom_init(Object *obj)
 128{
 129    XilinxGPO *s = XILINX_IO_MODULE_GPO(obj);
 130    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 131
 132    memory_region_init_io(&s->iomem, obj, &iom_gpo_ops, s,
 133                          TYPE_XILINX_IO_MODULE_GPO,
 134                          R_MAX * 4);
 135    sysbus_init_mmio(sbd, &s->iomem);
 136}
 137
 138static const VMStateDescription vmstate_xlx_iom = {
 139    .name = TYPE_XILINX_IO_MODULE_GPO,
 140    .version_id = 1,
 141    .minimum_version_id = 1,
 142    .minimum_version_id_old = 1,
 143    .fields = (VMStateField[]) {
 144        VMSTATE_END_OF_LIST(),
 145    }
 146};
 147
 148static void xlx_iom_class_init(ObjectClass *klass, void *data)
 149{
 150    DeviceClass *dc = DEVICE_CLASS(klass);
 151
 152    dc->reset = iom_gpo_reset;
 153    dc->realize = xlx_iom_realize;
 154    dc->props = xlx_iom_properties;
 155    dc->vmsd = &vmstate_xlx_iom;
 156}
 157
 158static const TypeInfo xlx_iom_info = {
 159    .name          = TYPE_XILINX_IO_MODULE_GPO,
 160    .parent        = TYPE_SYS_BUS_DEVICE,
 161    .instance_size = sizeof(XilinxGPO),
 162    .class_init    = xlx_iom_class_init,
 163    .instance_init = xlx_iom_init,
 164};
 165
 166static void xlx_iom_register_types(void)
 167{
 168    type_register_static(&xlx_iom_info);
 169}
 170
 171type_init(xlx_iom_register_types)
 172