qemu/hw/gpio/xilinx-axi-gpio.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the Xilinx AXI GPIO Registers
   3 *
   4 * Copyright (c) 2016 Xilinx Inc.
   5 * Written by Alistair Francis <alistair.francis@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/bitops.h"
  30#include "qemu/log.h"
  31
  32#ifndef XLNX_AXI_GPIO_ERR_DEBUG
  33#define XLNX_AXI_GPIO_ERR_DEBUG 0
  34#endif
  35
  36#define TYPE_XLNX_AXI_GPIO "xlnx.axi-gpio"
  37
  38#define XLNX_AXI_GPIO(obj) \
  39     OBJECT_CHECK(XlnxAXIGPIO, (obj), TYPE_XLNX_AXI_GPIO)
  40
  41REG32(GPIO_DATA, 0x00)
  42REG32(GPIO_TRI, 0x04)
  43REG32(GPIO2_DATA, 0x08)
  44REG32(GPIO2_TRI, 0x0C)
  45REG32(GIER, 0x11C)
  46    FIELD(GIER, GIE, 1, 31)
  47REG32(IP_ISR, 0x120)
  48    FIELD(IP_ISR, CHANNEL1_ST, 1, 0)
  49    FIELD(IP_ISR, CHANNEL2_ST, 1, 1)
  50REG32(IP_IER, 0x128)
  51    FIELD(IP_IER, CHANNEL1_EN, 1, 0)
  52    FIELD(IP_IER, CHANNEL2_EN, 1, 1)
  53
  54#define R_MAX (R_IP_IER + 1)
  55
  56typedef struct XlnxAXIGPIO {
  57    SysBusDevice parent_obj;
  58    MemoryRegion iomem;
  59
  60    qemu_irq parent_irq;
  61    qemu_irq outputs1[32], outputs2[32];
  62
  63    uint32_t regs[R_MAX];
  64    RegisterInfo regs_info[R_MAX];
  65} XlnxAXIGPIO;
  66
  67/* The interrupts should be triggered when a change arrives on the GPIO pins */
  68static void irq_update(XlnxAXIGPIO *s)
  69{
  70    bool general_enable = AF_EX32(s->regs, GIER, GIE);
  71    bool pending = !!(s->regs[R_IP_ISR] & s->regs[R_IP_IER]);
  72
  73    qemu_set_irq(s->parent_irq, general_enable & pending);
  74}
  75
  76static void data_handler(void *opaque, int irq, int level, int channel)
  77{
  78    XlnxAXIGPIO *s = XLNX_AXI_GPIO(opaque);
  79    unsigned int data_regnr, tri_regnr;
  80
  81    assert(channel > 0 && channel < 3);
  82    data_regnr = channel == 1 ? R_GPIO_DATA : R_GPIO2_DATA;
  83    tri_regnr = channel == 1 ? R_GPIO_TRI : R_GPIO2_TRI;
  84
  85    if (!extract32(s->regs[tri_regnr], irq, 1) ||
  86        extract32(s->regs[data_regnr], irq, 1) == level) {
  87        /* GPIO is configured as output, or there is no change */
  88        return;
  89    }
  90
  91    s->regs[data_regnr] = deposit32(s->regs[data_regnr], irq, 1, level);
  92
  93    switch (channel) {
  94    case 1:
  95        AF_DP32(s->regs, IP_ISR, CHANNEL1_ST, 1);
  96        break;
  97    case 2:
  98        AF_DP32(s->regs, IP_ISR, CHANNEL2_ST, 1);
  99        break;
 100    }
 101
 102    irq_update(s);
 103}
 104
 105static void data_handler1(void *opaque, int irq, int level)
 106{
 107    data_handler(opaque, irq, level, 1);
 108}
 109
 110static void data_handler2(void *opaque, int irq, int level)
 111{
 112    data_handler(opaque, irq, level, 2);
 113}
 114
 115static void xlnx_axi_gpio_data_post_write(XlnxAXIGPIO *s, uint64_t val,
 116                                          int channel)
 117{
 118    unsigned int tri_regnr;
 119    bool gpio_set;
 120    int i;
 121
 122    assert(channel > 0 && channel < 3);
 123    tri_regnr = channel == 1 ? R_GPIO_TRI : R_GPIO2_TRI;
 124
 125    for (i = 0; i < 32; i++) {
 126        if (extract32(s->regs[tri_regnr], i, 1)) {
 127            /* GPIO is configured as input, don't change anything */
 128            continue;
 129        }
 130
 131        gpio_set = extract32(val, i, 1);
 132
 133        switch (channel) {
 134        case 1:
 135            qemu_set_irq(s->outputs1[i], gpio_set);
 136            break;
 137        case 2:
 138            qemu_set_irq(s->outputs2[i], gpio_set);
 139            break;
 140        }
 141    }
 142}
 143
 144static void xlnx_axi_gpio_data_post_write1(RegisterInfo *reg, uint64_t val)
 145{
 146    XlnxAXIGPIO *s = XLNX_AXI_GPIO(reg->opaque);
 147
 148    xlnx_axi_gpio_data_post_write(s, val, 1);
 149}
 150
 151static void xlnx_axi_gpio_data_post_write2(RegisterInfo *reg, uint64_t val)
 152{
 153    XlnxAXIGPIO *s = XLNX_AXI_GPIO(reg->opaque);
 154
 155    xlnx_axi_gpio_data_post_write(s, val, 2);
 156}
 157
 158static void xlnx_axi_gpio_post_write(RegisterInfo *reg, uint64_t val)
 159{
 160    XlnxAXIGPIO *s = XLNX_AXI_GPIO(reg->opaque);
 161
 162    irq_update(s);
 163}
 164
 165static uint64_t xlnx_axi_gpi_data_read(RegisterInfo *reg, uint64_t val,
 166                                       uint8_t channel)
 167{
 168    XlnxAXIGPIO *s = XLNX_AXI_GPIO(reg->opaque);
 169
 170    switch (channel) {
 171    case 1:
 172        return val & s->regs[R_GPIO_TRI];
 173    case 2:
 174        return val & s->regs[R_GPIO2_TRI];
 175    default:
 176        return val;
 177    }
 178}
 179
 180static uint64_t xlnx_axi_gpio_data_post_read(RegisterInfo *reg, uint64_t val)
 181{
 182    return xlnx_axi_gpi_data_read(reg, val, 1);
 183}
 184
 185static uint64_t xlnx_axi_gpio2_data_post_read(RegisterInfo *reg, uint64_t val)
 186{
 187    return xlnx_axi_gpi_data_read(reg, val, 2);
 188}
 189
 190static RegisterAccessInfo xlnx_axi_gpio_regs_info[] = {
 191    {   .name = "GPIO_DATA",  .decode.addr = A_GPIO_DATA,
 192        .post_read = xlnx_axi_gpio_data_post_read,
 193        .post_write = xlnx_axi_gpio_data_post_write1,
 194    },{ .name = "GPIO_TRI",  .decode.addr = A_GPIO_TRI,
 195    },{ .name = "GPIO2_DATA",  .decode.addr = A_GPIO2_DATA,
 196        .post_read = xlnx_axi_gpio2_data_post_read,
 197        .post_write = xlnx_axi_gpio_data_post_write2,
 198    },{ .name = "GPIO2_TRI",  .decode.addr = A_GPIO2_TRI,
 199    },{ .name = "GIER",  .decode.addr = A_GIER,
 200        .post_write = xlnx_axi_gpio_post_write,
 201    },{ .name = "IP_IER",  .decode.addr = A_IP_IER,
 202        .post_write = xlnx_axi_gpio_post_write,
 203    },{ .name = "IP_ISR",  .decode.addr = A_IP_ISR,
 204        .post_write = xlnx_axi_gpio_post_write,
 205    }
 206};
 207
 208static void xlnx_axi_gpio_reset(DeviceState *dev)
 209{
 210    XlnxAXIGPIO *s = XLNX_AXI_GPIO(dev);
 211    unsigned int i;
 212
 213    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 214        register_reset(&s->regs_info[i]);
 215    }
 216
 217    irq_update(s);
 218}
 219
 220static uint64_t xlnx_axi_gpio_read(void *opaque, hwaddr addr, unsigned size)
 221{
 222    XlnxAXIGPIO *s = XLNX_AXI_GPIO(opaque);
 223    RegisterInfo *r = &s->regs_info[addr / 4];
 224
 225    if (!r->data) {
 226        qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
 227                 object_get_canonical_path(OBJECT(s)),
 228                 addr);
 229        return 0;
 230    }
 231    return register_read(r);
 232}
 233
 234static void xlnx_axi_gpio_write(void *opaque, hwaddr addr, uint64_t value,
 235                      unsigned size)
 236{
 237    XlnxAXIGPIO *s = XLNX_AXI_GPIO(opaque);
 238    RegisterInfo *r = &s->regs_info[addr / 4];
 239
 240    if (!r->data) {
 241        qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
 242                 object_get_canonical_path(OBJECT(s)),
 243                 addr, value);
 244        return;
 245    }
 246    register_write(r, value, ~0);
 247}
 248
 249static const MemoryRegionOps xlnx_axi_gpio_ops = {
 250    .read = xlnx_axi_gpio_read,
 251    .write = xlnx_axi_gpio_write,
 252    .endianness = DEVICE_LITTLE_ENDIAN,
 253    .valid = {
 254        .min_access_size = 4,
 255        .max_access_size = 4,
 256    },
 257};
 258
 259static void xlnx_axi_gpio_realize(DeviceState *dev, Error **errp)
 260{
 261    XlnxAXIGPIO *s = XLNX_AXI_GPIO(dev);
 262    const char *prefix = object_get_canonical_path(OBJECT(dev));
 263    unsigned int i;
 264
 265    for (i = 0; i < ARRAY_SIZE(xlnx_axi_gpio_regs_info); ++i) {
 266        RegisterInfo *r =
 267                    &s->regs_info[xlnx_axi_gpio_regs_info[i].decode.addr/4];
 268
 269        *r = (RegisterInfo) {
 270            .data = (uint8_t *)&s->regs[
 271                    xlnx_axi_gpio_regs_info[i].decode.addr/4],
 272            .data_size = sizeof(uint32_t),
 273            .access = &xlnx_axi_gpio_regs_info[i],
 274            .debug = XLNX_AXI_GPIO_ERR_DEBUG,
 275            .prefix = prefix,
 276            .opaque = s,
 277        };
 278    }
 279
 280    /* Create two GPIO in banks that QTest can use */
 281    qdev_init_gpio_in(dev, data_handler1, 32);
 282    qdev_init_gpio_in(dev, data_handler2, 32);
 283
 284    /* Create GPIO banks as well */
 285    qdev_init_gpio_out(dev, s->outputs1, 32);
 286    qdev_init_gpio_out(dev, s->outputs2, 32);
 287}
 288
 289static void xlnx_axi_gpio_init(Object *obj)
 290{
 291    XlnxAXIGPIO *s = XLNX_AXI_GPIO(obj);
 292    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 293
 294    memory_region_init_io(&s->iomem, obj, &xlnx_axi_gpio_ops, s,
 295                          TYPE_XLNX_AXI_GPIO, R_MAX * 4);
 296    sysbus_init_mmio(sbd, &s->iomem);
 297
 298    sysbus_init_irq(sbd, &s->parent_irq);
 299}
 300
 301static const VMStateDescription vmstate_gpio = {
 302    .name = TYPE_XLNX_AXI_GPIO,
 303    .version_id = 1,
 304    .minimum_version_id = 1,
 305    .minimum_version_id_old = 1,
 306    .fields = (VMStateField[]) {
 307        VMSTATE_UINT32_ARRAY(regs, XlnxAXIGPIO, R_MAX),
 308        VMSTATE_END_OF_LIST(),
 309    }
 310};
 311
 312static void xlnx_axi_gpio_class_init(ObjectClass *klass, void *data)
 313{
 314    DeviceClass *dc = DEVICE_CLASS(klass);
 315
 316    dc->reset = xlnx_axi_gpio_reset;
 317    dc->realize = xlnx_axi_gpio_realize;
 318    dc->vmsd = &vmstate_gpio;
 319}
 320
 321static const TypeInfo xlnx_axi_gpio_info = {
 322    .name          = TYPE_XLNX_AXI_GPIO,
 323    .parent        = TYPE_SYS_BUS_DEVICE,
 324    .instance_size = sizeof(XlnxAXIGPIO),
 325    .class_init    = xlnx_axi_gpio_class_init,
 326    .instance_init = xlnx_axi_gpio_init,
 327};
 328
 329static void xlnx_axi_gpio_register_types(void)
 330{
 331    type_register_static(&xlnx_axi_gpio_info);
 332}
 333
 334type_init(xlnx_axi_gpio_register_types)
 335