qemu/hw/gpio/puv3_gpio.c
<<
>>
Prefs
   1/*
   2 * GPIO device simulation in PKUnity SoC
   3 *
   4 * Copyright (C) 2010-2012 Guan Xuetao
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation, or any later version.
   9 * See the COPYING file in the top-level directory.
  10 */
  11#include "hw/hw.h"
  12#include "hw/sysbus.h"
  13
  14#undef DEBUG_PUV3
  15#include "hw/unicore32/puv3.h"
  16
  17#define TYPE_PUV3_GPIO "puv3_gpio"
  18#define PUV3_GPIO(obj) OBJECT_CHECK(PUV3GPIOState, (obj), TYPE_PUV3_GPIO)
  19
  20typedef struct PUV3GPIOState {
  21    SysBusDevice parent_obj;
  22
  23    MemoryRegion iomem;
  24    qemu_irq irq[9];
  25
  26    uint32_t reg_GPLR;
  27    uint32_t reg_GPDR;
  28    uint32_t reg_GPIR;
  29} PUV3GPIOState;
  30
  31static uint64_t puv3_gpio_read(void *opaque, hwaddr offset,
  32        unsigned size)
  33{
  34    PUV3GPIOState *s = opaque;
  35    uint32_t ret = 0;
  36
  37    switch (offset) {
  38    case 0x00:
  39        ret = s->reg_GPLR;
  40        break;
  41    case 0x04:
  42        ret = s->reg_GPDR;
  43        break;
  44    case 0x20:
  45        ret = s->reg_GPIR;
  46        break;
  47    default:
  48        DPRINTF("Bad offset 0x%x\n", offset);
  49    }
  50    DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
  51
  52    return ret;
  53}
  54
  55static void puv3_gpio_write(void *opaque, hwaddr offset,
  56        uint64_t value, unsigned size)
  57{
  58    PUV3GPIOState *s = opaque;
  59
  60    DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
  61    switch (offset) {
  62    case 0x04:
  63        s->reg_GPDR = value;
  64        break;
  65    case 0x08:
  66        if (s->reg_GPDR & value) {
  67            s->reg_GPLR |= value;
  68        } else {
  69            DPRINTF("Write gpio input port error!");
  70        }
  71        break;
  72    case 0x0c:
  73        if (s->reg_GPDR & value) {
  74            s->reg_GPLR &= ~value;
  75        } else {
  76            DPRINTF("Write gpio input port error!");
  77        }
  78        break;
  79    case 0x10: /* GRER */
  80    case 0x14: /* GFER */
  81    case 0x18: /* GEDR */
  82        break;
  83    case 0x20: /* GPIR */
  84        s->reg_GPIR = value;
  85        break;
  86    default:
  87        DPRINTF("Bad offset 0x%x\n", offset);
  88    }
  89}
  90
  91static const MemoryRegionOps puv3_gpio_ops = {
  92    .read = puv3_gpio_read,
  93    .write = puv3_gpio_write,
  94    .impl = {
  95        .min_access_size = 4,
  96        .max_access_size = 4,
  97    },
  98    .endianness = DEVICE_NATIVE_ENDIAN,
  99};
 100
 101static int puv3_gpio_init(SysBusDevice *dev)
 102{
 103    PUV3GPIOState *s = PUV3_GPIO(dev);
 104
 105    s->reg_GPLR = 0;
 106    s->reg_GPDR = 0;
 107
 108    /* FIXME: these irqs not handled yet */
 109    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW0]);
 110    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW1]);
 111    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW2]);
 112    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW3]);
 113    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW4]);
 114    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW5]);
 115    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW6]);
 116    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW7]);
 117    sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOHIGH]);
 118
 119    memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio",
 120            PUV3_REGS_OFFSET);
 121    sysbus_init_mmio(dev, &s->iomem);
 122
 123    return 0;
 124}
 125
 126static void puv3_gpio_class_init(ObjectClass *klass, void *data)
 127{
 128    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 129
 130    sdc->init = puv3_gpio_init;
 131}
 132
 133static const TypeInfo puv3_gpio_info = {
 134    .name = TYPE_PUV3_GPIO,
 135    .parent = TYPE_SYS_BUS_DEVICE,
 136    .instance_size = sizeof(PUV3GPIOState),
 137    .class_init = puv3_gpio_class_init,
 138};
 139
 140static void puv3_gpio_register_type(void)
 141{
 142    type_register_static(&puv3_gpio_info);
 143}
 144
 145type_init(puv3_gpio_register_type)
 146