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#include "hw.h"
  11#include "pxa.h"
  12#include "mainstone.h"
  13
  14/* Mainstone FPGA for extern irqs */
  15#define FPGA_GPIO_PIN   0
  16#define MST_NUM_IRQS    16
  17#define MST_LEDDAT1             0x10
  18#define MST_LEDDAT2             0x14
  19#define MST_LEDCTRL             0x40
  20#define MST_GPSWR               0x60
  21#define MST_MSCWR1              0x80
  22#define MST_MSCWR2              0x84
  23#define MST_MSCWR3              0x88
  24#define MST_MSCRD               0x90
  25#define MST_INTMSKENA   0xc0
  26#define MST_INTSETCLR   0xd0
  27#define MST_PCMCIA0             0xe0
  28#define MST_PCMCIA1             0xe4
  29
  30typedef struct mst_irq_state{
  31        qemu_irq *parent;
  32        qemu_irq *pins;
  33
  34        uint32_t prev_level;
  35        uint32_t leddat1;
  36        uint32_t leddat2;
  37        uint32_t ledctrl;
  38        uint32_t gpswr;
  39        uint32_t mscwr1;
  40        uint32_t mscwr2;
  41        uint32_t mscwr3;
  42        uint32_t mscrd;
  43        uint32_t intmskena;
  44        uint32_t intsetclr;
  45        uint32_t pcmcia0;
  46        uint32_t pcmcia1;
  47}mst_irq_state;
  48
  49static void
  50mst_fpga_update_gpio(mst_irq_state *s)
  51{
  52        uint32_t level, diff;
  53        int bit;
  54        level = s->prev_level ^ s->intsetclr;
  55
  56        for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
  57                bit = ffs(diff) - 1;
  58                qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
  59        }
  60        s->prev_level = level;
  61}
  62
  63static void
  64mst_fpga_set_irq(void *opaque, int irq, int level)
  65{
  66        mst_irq_state *s = (mst_irq_state *)opaque;
  67
  68        if (level)
  69                s->prev_level |= 1u << irq;
  70        else
  71                s->prev_level &= ~(1u << irq);
  72
  73        if(s->intmskena & (1u << irq)) {
  74                s->intsetclr = 1u << irq;
  75                qemu_set_irq(s->parent[0], level);
  76        }
  77}
  78
  79
  80static uint32_t
  81mst_fpga_readb(void *opaque, target_phys_addr_t addr)
  82{
  83        mst_irq_state *s = (mst_irq_state *) opaque;
  84
  85        switch (addr) {
  86        case MST_LEDDAT1:
  87                return s->leddat1;
  88        case MST_LEDDAT2:
  89                return s->leddat2;
  90        case MST_LEDCTRL:
  91                return s->ledctrl;
  92        case MST_GPSWR:
  93                return s->gpswr;
  94        case MST_MSCWR1:
  95                return s->mscwr1;
  96        case MST_MSCWR2:
  97                return s->mscwr2;
  98        case MST_MSCWR3:
  99                return s->mscwr3;
 100        case MST_MSCRD:
 101                return s->mscrd;
 102        case MST_INTMSKENA:
 103                return s->intmskena;
 104        case MST_INTSETCLR:
 105                return s->intsetclr;
 106        case MST_PCMCIA0:
 107                return s->pcmcia0;
 108        case MST_PCMCIA1:
 109                return s->pcmcia1;
 110        default:
 111                printf("Mainstone - mst_fpga_readb: Bad register offset "
 112                        REG_FMT " \n", addr);
 113        }
 114        return 0;
 115}
 116
 117static void
 118mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
 119{
 120        mst_irq_state *s = (mst_irq_state *) opaque;
 121        value &= 0xffffffff;
 122
 123        switch (addr) {
 124        case MST_LEDDAT1:
 125                s->leddat1 = value;
 126                break;
 127        case MST_LEDDAT2:
 128                s->leddat2 = value;
 129                break;
 130        case MST_LEDCTRL:
 131                s->ledctrl = value;
 132                break;
 133        case MST_GPSWR:
 134                s->gpswr = value;
 135                break;
 136        case MST_MSCWR1:
 137                s->mscwr1 = value;
 138                break;
 139        case MST_MSCWR2:
 140                s->mscwr2 = value;
 141                break;
 142        case MST_MSCWR3:
 143                s->mscwr3 = value;
 144                break;
 145        case MST_MSCRD:
 146                s->mscrd =  value;
 147                break;
 148        case MST_INTMSKENA:     /* Mask interupt */
 149                s->intmskena = (value & 0xFEEFF);
 150                mst_fpga_update_gpio(s);
 151                break;
 152        case MST_INTSETCLR:     /* clear or set interrupt */
 153                s->intsetclr = (value & 0xFEEFF);
 154                break;
 155        case MST_PCMCIA0:
 156                s->pcmcia0 = value;
 157                break;
 158        case MST_PCMCIA1:
 159                s->pcmcia1 = value;
 160                break;
 161        default:
 162                printf("Mainstone - mst_fpga_writeb: Bad register offset "
 163                        REG_FMT " \n", addr);
 164        }
 165}
 166
 167static CPUReadMemoryFunc *mst_fpga_readfn[] = {
 168        mst_fpga_readb,
 169        mst_fpga_readb,
 170        mst_fpga_readb,
 171};
 172static CPUWriteMemoryFunc *mst_fpga_writefn[] = {
 173        mst_fpga_writeb,
 174        mst_fpga_writeb,
 175        mst_fpga_writeb,
 176};
 177
 178static void
 179mst_fpga_save(QEMUFile *f, void *opaque)
 180{
 181        struct mst_irq_state *s = (mst_irq_state *) opaque;
 182
 183        qemu_put_be32s(f, &s->prev_level);
 184        qemu_put_be32s(f, &s->leddat1);
 185        qemu_put_be32s(f, &s->leddat2);
 186        qemu_put_be32s(f, &s->ledctrl);
 187        qemu_put_be32s(f, &s->gpswr);
 188        qemu_put_be32s(f, &s->mscwr1);
 189        qemu_put_be32s(f, &s->mscwr2);
 190        qemu_put_be32s(f, &s->mscwr3);
 191        qemu_put_be32s(f, &s->mscrd);
 192        qemu_put_be32s(f, &s->intmskena);
 193        qemu_put_be32s(f, &s->intsetclr);
 194        qemu_put_be32s(f, &s->pcmcia0);
 195        qemu_put_be32s(f, &s->pcmcia1);
 196}
 197
 198static int
 199mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
 200{
 201        mst_irq_state *s = (mst_irq_state *) opaque;
 202
 203        qemu_get_be32s(f, &s->prev_level);
 204        qemu_get_be32s(f, &s->leddat1);
 205        qemu_get_be32s(f, &s->leddat2);
 206        qemu_get_be32s(f, &s->ledctrl);
 207        qemu_get_be32s(f, &s->gpswr);
 208        qemu_get_be32s(f, &s->mscwr1);
 209        qemu_get_be32s(f, &s->mscwr2);
 210        qemu_get_be32s(f, &s->mscwr3);
 211        qemu_get_be32s(f, &s->mscrd);
 212        qemu_get_be32s(f, &s->intmskena);
 213        qemu_get_be32s(f, &s->intsetclr);
 214        qemu_get_be32s(f, &s->pcmcia0);
 215        qemu_get_be32s(f, &s->pcmcia1);
 216        return 0;
 217}
 218
 219qemu_irq *mst_irq_init(struct pxa2xx_state_s *cpu, uint32_t base, int irq)
 220{
 221        mst_irq_state *s;
 222        int iomemtype;
 223        qemu_irq *qi;
 224
 225        s = (mst_irq_state  *)
 226                qemu_mallocz(sizeof(mst_irq_state));
 227
 228        s->parent = &cpu->pic[irq];
 229
 230        /* alloc the external 16 irqs */
 231        qi  = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
 232        s->pins = qi;
 233
 234        iomemtype = cpu_register_io_memory(0, mst_fpga_readfn,
 235                mst_fpga_writefn, s);
 236        cpu_register_physical_memory(base, 0x00100000, iomemtype);
 237        register_savevm("mainstone_fpga", 0, 0, mst_fpga_save, mst_fpga_load, s);
 238        return qi;
 239}
 240