qemu/hw/mst_fpga.c
<<
>>
Prefs
   1/*
   2 * PXA270-based Intel Mainstone platforms.
   3 * FPGA driver
   4 *
   5 * Copyright (c) 2007 by Armin Kuster <akuster@kama-aina.net> or
   6 *                                    <akuster@mvista.com>
   7 *
   8 * This code is licensed under the GNU GPL v2.
   9 *
  10 * Contributions after 2012-01-13 are licensed under the terms of the
  11 * GNU GPL, version 2 or (at your option) any later version.
  12 */
  13#include "hw.h"
  14#include "sysbus.h"
  15
  16/* Mainstone FPGA for extern irqs */
  17#define FPGA_GPIO_PIN   0
  18#define MST_NUM_IRQS    16
  19#define MST_LEDDAT1             0x10
  20#define MST_LEDDAT2             0x14
  21#define MST_LEDCTRL             0x40
  22#define MST_GPSWR               0x60
  23#define MST_MSCWR1              0x80
  24#define MST_MSCWR2              0x84
  25#define MST_MSCWR3              0x88
  26#define MST_MSCRD               0x90
  27#define MST_INTMSKENA   0xc0
  28#define MST_INTSETCLR   0xd0
  29#define MST_PCMCIA0             0xe0
  30#define MST_PCMCIA1             0xe4
  31
  32#define MST_PCMCIAx_READY       (1 << 10)
  33#define MST_PCMCIAx_nCD         (1 << 5)
  34
  35#define MST_PCMCIA_CD0_IRQ      9
  36#define MST_PCMCIA_CD1_IRQ      13
  37
  38typedef struct mst_irq_state{
  39        SysBusDevice busdev;
  40        MemoryRegion iomem;
  41
  42        qemu_irq parent;
  43
  44        uint32_t prev_level;
  45        uint32_t leddat1;
  46        uint32_t leddat2;
  47        uint32_t ledctrl;
  48        uint32_t gpswr;
  49        uint32_t mscwr1;
  50        uint32_t mscwr2;
  51        uint32_t mscwr3;
  52        uint32_t mscrd;
  53        uint32_t intmskena;
  54        uint32_t intsetclr;
  55        uint32_t pcmcia0;
  56        uint32_t pcmcia1;
  57}mst_irq_state;
  58
  59static void
  60mst_fpga_set_irq(void *opaque, int irq, int level)
  61{
  62        mst_irq_state *s = (mst_irq_state *)opaque;
  63        uint32_t oldint = s->intsetclr & s->intmskena;
  64
  65        if (level)
  66                s->prev_level |= 1u << irq;
  67        else
  68                s->prev_level &= ~(1u << irq);
  69
  70        switch(irq) {
  71        case MST_PCMCIA_CD0_IRQ:
  72                if (level)
  73                        s->pcmcia0 &= ~MST_PCMCIAx_nCD;
  74                else
  75                        s->pcmcia0 |=  MST_PCMCIAx_nCD;
  76                break;
  77        case MST_PCMCIA_CD1_IRQ:
  78                if (level)
  79                        s->pcmcia1 &= ~MST_PCMCIAx_nCD;
  80                else
  81                        s->pcmcia1 |=  MST_PCMCIAx_nCD;
  82                break;
  83        }
  84
  85        if ((s->intmskena & (1u << irq)) && level)
  86                s->intsetclr |= 1u << irq;
  87
  88        if (oldint != (s->intsetclr & s->intmskena))
  89                qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
  90}
  91
  92
  93static uint64_t
  94mst_fpga_readb(void *opaque, hwaddr addr, unsigned size)
  95{
  96        mst_irq_state *s = (mst_irq_state *) opaque;
  97
  98        switch (addr) {
  99        case MST_LEDDAT1:
 100                return s->leddat1;
 101        case MST_LEDDAT2:
 102                return s->leddat2;
 103        case MST_LEDCTRL:
 104                return s->ledctrl;
 105        case MST_GPSWR:
 106                return s->gpswr;
 107        case MST_MSCWR1:
 108                return s->mscwr1;
 109        case MST_MSCWR2:
 110                return s->mscwr2;
 111        case MST_MSCWR3:
 112                return s->mscwr3;
 113        case MST_MSCRD:
 114                return s->mscrd;
 115        case MST_INTMSKENA:
 116                return s->intmskena;
 117        case MST_INTSETCLR:
 118                return s->intsetclr;
 119        case MST_PCMCIA0:
 120                return s->pcmcia0;
 121        case MST_PCMCIA1:
 122                return s->pcmcia1;
 123        default:
 124                printf("Mainstone - mst_fpga_readb: Bad register offset "
 125                        "0x" TARGET_FMT_plx "\n", addr);
 126        }
 127        return 0;
 128}
 129
 130static void
 131mst_fpga_writeb(void *opaque, hwaddr addr, uint64_t value,
 132                unsigned size)
 133{
 134        mst_irq_state *s = (mst_irq_state *) opaque;
 135        value &= 0xffffffff;
 136
 137        switch (addr) {
 138        case MST_LEDDAT1:
 139                s->leddat1 = value;
 140                break;
 141        case MST_LEDDAT2:
 142                s->leddat2 = value;
 143                break;
 144        case MST_LEDCTRL:
 145                s->ledctrl = value;
 146                break;
 147        case MST_GPSWR:
 148                s->gpswr = value;
 149                break;
 150        case MST_MSCWR1:
 151                s->mscwr1 = value;
 152                break;
 153        case MST_MSCWR2:
 154                s->mscwr2 = value;
 155                break;
 156        case MST_MSCWR3:
 157                s->mscwr3 = value;
 158                break;
 159        case MST_MSCRD:
 160                s->mscrd =  value;
 161                break;
 162        case MST_INTMSKENA:     /* Mask interrupt */
 163                s->intmskena = (value & 0xFEEFF);
 164                qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
 165                break;
 166        case MST_INTSETCLR:     /* clear or set interrupt */
 167                s->intsetclr = (value & 0xFEEFF);
 168                qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
 169                break;
 170                /* For PCMCIAx allow the to change only power and reset */
 171        case MST_PCMCIA0:
 172                s->pcmcia0 = (value & 0x1f) | (s->pcmcia0 & ~0x1f);
 173                break;
 174        case MST_PCMCIA1:
 175                s->pcmcia1 = (value & 0x1f) | (s->pcmcia1 & ~0x1f);
 176                break;
 177        default:
 178                printf("Mainstone - mst_fpga_writeb: Bad register offset "
 179                        "0x" TARGET_FMT_plx "\n", addr);
 180        }
 181}
 182
 183static const MemoryRegionOps mst_fpga_ops = {
 184        .read = mst_fpga_readb,
 185        .write = mst_fpga_writeb,
 186        .endianness = DEVICE_NATIVE_ENDIAN,
 187};
 188
 189static int mst_fpga_post_load(void *opaque, int version_id)
 190{
 191        mst_irq_state *s = (mst_irq_state *) opaque;
 192
 193        qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
 194        return 0;
 195}
 196
 197static int mst_fpga_init(SysBusDevice *dev)
 198{
 199        mst_irq_state *s;
 200
 201        s = FROM_SYSBUS(mst_irq_state, dev);
 202
 203        s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
 204        s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
 205
 206        sysbus_init_irq(dev, &s->parent);
 207
 208        /* alloc the external 16 irqs */
 209        qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
 210
 211        memory_region_init_io(&s->iomem, &mst_fpga_ops, s,
 212                            "fpga", 0x00100000);
 213        sysbus_init_mmio(dev, &s->iomem);
 214        return 0;
 215}
 216
 217static VMStateDescription vmstate_mst_fpga_regs = {
 218        .name = "mainstone_fpga",
 219        .version_id = 0,
 220        .minimum_version_id = 0,
 221        .minimum_version_id_old = 0,
 222        .post_load = mst_fpga_post_load,
 223        .fields = (VMStateField []) {
 224                VMSTATE_UINT32(prev_level, mst_irq_state),
 225                VMSTATE_UINT32(leddat1, mst_irq_state),
 226                VMSTATE_UINT32(leddat2, mst_irq_state),
 227                VMSTATE_UINT32(ledctrl, mst_irq_state),
 228                VMSTATE_UINT32(gpswr, mst_irq_state),
 229                VMSTATE_UINT32(mscwr1, mst_irq_state),
 230                VMSTATE_UINT32(mscwr2, mst_irq_state),
 231                VMSTATE_UINT32(mscwr3, mst_irq_state),
 232                VMSTATE_UINT32(mscrd, mst_irq_state),
 233                VMSTATE_UINT32(intmskena, mst_irq_state),
 234                VMSTATE_UINT32(intsetclr, mst_irq_state),
 235                VMSTATE_UINT32(pcmcia0, mst_irq_state),
 236                VMSTATE_UINT32(pcmcia1, mst_irq_state),
 237                VMSTATE_END_OF_LIST(),
 238        },
 239};
 240
 241static void mst_fpga_class_init(ObjectClass *klass, void *data)
 242{
 243    DeviceClass *dc = DEVICE_CLASS(klass);
 244    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 245
 246    k->init = mst_fpga_init;
 247    dc->desc = "Mainstone II FPGA";
 248    dc->vmsd = &vmstate_mst_fpga_regs;
 249}
 250
 251static const TypeInfo mst_fpga_info = {
 252    .name          = "mainstone-fpga",
 253    .parent        = TYPE_SYS_BUS_DEVICE,
 254    .instance_size = sizeof(mst_irq_state),
 255    .class_init    = mst_fpga_class_init,
 256};
 257
 258static void mst_fpga_register_types(void)
 259{
 260    type_register_static(&mst_fpga_info);
 261}
 262
 263type_init(mst_fpga_register_types)
 264