qemu/hw/arm/pxa2xx_gpio.c
<<
>>
Prefs
   1/*
   2 * Intel XScale PXA255/270 GPIO controller emulation.
   3 *
   4 * Copyright (c) 2006 Openedhand Ltd.
   5 * Written by Andrzej Zaborowski <balrog@zabor.org>
   6 *
   7 * This code is licensed under the GPL.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "cpu.h"
  12#include "hw/hw.h"
  13#include "hw/irq.h"
  14#include "hw/qdev-properties.h"
  15#include "hw/sysbus.h"
  16#include "migration/vmstate.h"
  17#include "hw/arm/pxa.h"
  18#include "qemu/log.h"
  19#include "qemu/module.h"
  20
  21#define PXA2XX_GPIO_BANKS       4
  22
  23#define TYPE_PXA2XX_GPIO "pxa2xx-gpio"
  24#define PXA2XX_GPIO(obj) \
  25    OBJECT_CHECK(PXA2xxGPIOInfo, (obj), TYPE_PXA2XX_GPIO)
  26
  27typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
  28struct PXA2xxGPIOInfo {
  29    /*< private >*/
  30    SysBusDevice parent_obj;
  31    /*< public >*/
  32
  33    MemoryRegion iomem;
  34    qemu_irq irq0, irq1, irqX;
  35    int lines;
  36    int ncpu;
  37    ARMCPU *cpu;
  38
  39    /* XXX: GNU C vectors are more suitable */
  40    uint32_t ilevel[PXA2XX_GPIO_BANKS];
  41    uint32_t olevel[PXA2XX_GPIO_BANKS];
  42    uint32_t dir[PXA2XX_GPIO_BANKS];
  43    uint32_t rising[PXA2XX_GPIO_BANKS];
  44    uint32_t falling[PXA2XX_GPIO_BANKS];
  45    uint32_t status[PXA2XX_GPIO_BANKS];
  46    uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
  47
  48    uint32_t prev_level[PXA2XX_GPIO_BANKS];
  49    qemu_irq handler[PXA2XX_GPIO_BANKS * 32];
  50    qemu_irq read_notify;
  51};
  52
  53static struct {
  54    enum {
  55        GPIO_NONE,
  56        GPLR,
  57        GPSR,
  58        GPCR,
  59        GPDR,
  60        GRER,
  61        GFER,
  62        GEDR,
  63        GAFR_L,
  64        GAFR_U,
  65    } reg;
  66    int bank;
  67} pxa2xx_gpio_regs[0x200] = {
  68    [0 ... 0x1ff] = { GPIO_NONE, 0 },
  69#define PXA2XX_REG(reg, a0, a1, a2, a3) \
  70    [a0] = { reg, 0 }, [a1] = { reg, 1 }, [a2] = { reg, 2 }, [a3] = { reg, 3 },
  71
  72    PXA2XX_REG(GPLR, 0x000, 0x004, 0x008, 0x100)
  73    PXA2XX_REG(GPSR, 0x018, 0x01c, 0x020, 0x118)
  74    PXA2XX_REG(GPCR, 0x024, 0x028, 0x02c, 0x124)
  75    PXA2XX_REG(GPDR, 0x00c, 0x010, 0x014, 0x10c)
  76    PXA2XX_REG(GRER, 0x030, 0x034, 0x038, 0x130)
  77    PXA2XX_REG(GFER, 0x03c, 0x040, 0x044, 0x13c)
  78    PXA2XX_REG(GEDR, 0x048, 0x04c, 0x050, 0x148)
  79    PXA2XX_REG(GAFR_L, 0x054, 0x05c, 0x064, 0x06c)
  80    PXA2XX_REG(GAFR_U, 0x058, 0x060, 0x068, 0x070)
  81};
  82
  83static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
  84{
  85    if (s->status[0] & (1 << 0))
  86        qemu_irq_raise(s->irq0);
  87    else
  88        qemu_irq_lower(s->irq0);
  89
  90    if (s->status[0] & (1 << 1))
  91        qemu_irq_raise(s->irq1);
  92    else
  93        qemu_irq_lower(s->irq1);
  94
  95    if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
  96        qemu_irq_raise(s->irqX);
  97    else
  98        qemu_irq_lower(s->irqX);
  99}
 100
 101/* Bitmap of pins used as standby and sleep wake-up sources.  */
 102static const int pxa2xx_gpio_wake[PXA2XX_GPIO_BANKS] = {
 103    0x8003fe1b, 0x002001fc, 0xec080000, 0x0012007f,
 104};
 105
 106static void pxa2xx_gpio_set(void *opaque, int line, int level)
 107{
 108    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
 109    CPUState *cpu = CPU(s->cpu);
 110    int bank;
 111    uint32_t mask;
 112
 113    if (line >= s->lines) {
 114        printf("%s: No GPIO pin %i\n", __func__, line);
 115        return;
 116    }
 117
 118    bank = line >> 5;
 119    mask = 1U << (line & 31);
 120
 121    if (level) {
 122        s->status[bank] |= s->rising[bank] & mask &
 123                ~s->ilevel[bank] & ~s->dir[bank];
 124        s->ilevel[bank] |= mask;
 125    } else {
 126        s->status[bank] |= s->falling[bank] & mask &
 127                s->ilevel[bank] & ~s->dir[bank];
 128        s->ilevel[bank] &= ~mask;
 129    }
 130
 131    if (s->status[bank] & mask)
 132        pxa2xx_gpio_irq_update(s);
 133
 134    /* Wake-up GPIOs */
 135    if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
 136        cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
 137    }
 138}
 139
 140static void pxa2xx_gpio_handler_update(PXA2xxGPIOInfo *s) {
 141    uint32_t level, diff;
 142    int i, bit, line;
 143    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
 144        level = s->olevel[i] & s->dir[i];
 145
 146        for (diff = s->prev_level[i] ^ level; diff; diff ^= 1 << bit) {
 147            bit = ctz32(diff);
 148            line = bit + 32 * i;
 149            qemu_set_irq(s->handler[line], (level >> bit) & 1);
 150        }
 151
 152        s->prev_level[i] = level;
 153    }
 154}
 155
 156static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
 157                                 unsigned size)
 158{
 159    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
 160    uint32_t ret;
 161    int bank;
 162    if (offset >= 0x200)
 163        return 0;
 164
 165    bank = pxa2xx_gpio_regs[offset].bank;
 166    switch (pxa2xx_gpio_regs[offset].reg) {
 167    case GPDR:          /* GPIO Pin-Direction registers */
 168        return s->dir[bank];
 169
 170    case GPSR:          /* GPIO Pin-Output Set registers */
 171        qemu_log_mask(LOG_GUEST_ERROR,
 172                      "pxa2xx GPIO: read from write only register GPSR\n");
 173        return 0;
 174
 175    case GPCR:          /* GPIO Pin-Output Clear registers */
 176        qemu_log_mask(LOG_GUEST_ERROR,
 177                      "pxa2xx GPIO: read from write only register GPCR\n");
 178        return 0;
 179
 180    case GRER:          /* GPIO Rising-Edge Detect Enable registers */
 181        return s->rising[bank];
 182
 183    case GFER:          /* GPIO Falling-Edge Detect Enable registers */
 184        return s->falling[bank];
 185
 186    case GAFR_L:        /* GPIO Alternate Function registers */
 187        return s->gafr[bank * 2];
 188
 189    case GAFR_U:        /* GPIO Alternate Function registers */
 190        return s->gafr[bank * 2 + 1];
 191
 192    case GPLR:          /* GPIO Pin-Level registers */
 193        ret = (s->olevel[bank] & s->dir[bank]) |
 194                (s->ilevel[bank] & ~s->dir[bank]);
 195        qemu_irq_raise(s->read_notify);
 196        return ret;
 197
 198    case GEDR:          /* GPIO Edge Detect Status registers */
 199        return s->status[bank];
 200
 201    default:
 202        hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
 203    }
 204
 205    return 0;
 206}
 207
 208static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
 209                              uint64_t value, unsigned size)
 210{
 211    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
 212    int bank;
 213    if (offset >= 0x200)
 214        return;
 215
 216    bank = pxa2xx_gpio_regs[offset].bank;
 217    switch (pxa2xx_gpio_regs[offset].reg) {
 218    case GPDR:          /* GPIO Pin-Direction registers */
 219        s->dir[bank] = value;
 220        pxa2xx_gpio_handler_update(s);
 221        break;
 222
 223    case GPSR:          /* GPIO Pin-Output Set registers */
 224        s->olevel[bank] |= value;
 225        pxa2xx_gpio_handler_update(s);
 226        break;
 227
 228    case GPCR:          /* GPIO Pin-Output Clear registers */
 229        s->olevel[bank] &= ~value;
 230        pxa2xx_gpio_handler_update(s);
 231        break;
 232
 233    case GRER:          /* GPIO Rising-Edge Detect Enable registers */
 234        s->rising[bank] = value;
 235        break;
 236
 237    case GFER:          /* GPIO Falling-Edge Detect Enable registers */
 238        s->falling[bank] = value;
 239        break;
 240
 241    case GAFR_L:        /* GPIO Alternate Function registers */
 242        s->gafr[bank * 2] = value;
 243        break;
 244
 245    case GAFR_U:        /* GPIO Alternate Function registers */
 246        s->gafr[bank * 2 + 1] = value;
 247        break;
 248
 249    case GEDR:          /* GPIO Edge Detect Status registers */
 250        s->status[bank] &= ~value;
 251        pxa2xx_gpio_irq_update(s);
 252        break;
 253
 254    default:
 255        hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
 256    }
 257}
 258
 259static const MemoryRegionOps pxa_gpio_ops = {
 260    .read = pxa2xx_gpio_read,
 261    .write = pxa2xx_gpio_write,
 262    .endianness = DEVICE_NATIVE_ENDIAN,
 263};
 264
 265DeviceState *pxa2xx_gpio_init(hwaddr base,
 266                              ARMCPU *cpu, DeviceState *pic, int lines)
 267{
 268    CPUState *cs = CPU(cpu);
 269    DeviceState *dev;
 270
 271    dev = qdev_create(NULL, TYPE_PXA2XX_GPIO);
 272    qdev_prop_set_int32(dev, "lines", lines);
 273    qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
 274    qdev_init_nofail(dev);
 275
 276    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 277    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
 278                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
 279    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
 280                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
 281    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2,
 282                    qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
 283
 284    return dev;
 285}
 286
 287static void pxa2xx_gpio_initfn(Object *obj)
 288{
 289    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 290    DeviceState *dev = DEVICE(sbd);
 291    PXA2xxGPIOInfo *s = PXA2XX_GPIO(dev);
 292
 293    memory_region_init_io(&s->iomem, obj, &pxa_gpio_ops,
 294                          s, "pxa2xx-gpio", 0x1000);
 295    sysbus_init_mmio(sbd, &s->iomem);
 296    sysbus_init_irq(sbd, &s->irq0);
 297    sysbus_init_irq(sbd, &s->irq1);
 298    sysbus_init_irq(sbd, &s->irqX);
 299}
 300
 301static void pxa2xx_gpio_realize(DeviceState *dev, Error **errp)
 302{
 303    PXA2xxGPIOInfo *s = PXA2XX_GPIO(dev);
 304
 305    s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
 306
 307    qdev_init_gpio_in(dev, pxa2xx_gpio_set, s->lines);
 308    qdev_init_gpio_out(dev, s->handler, s->lines);
 309}
 310
 311/*
 312 * Registers a callback to notify on GPLR reads.  This normally
 313 * shouldn't be needed but it is used for the hack on Spitz machines.
 314 */
 315void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
 316{
 317    PXA2xxGPIOInfo *s = PXA2XX_GPIO(dev);
 318
 319    s->read_notify = handler;
 320}
 321
 322static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
 323    .name = "pxa2xx-gpio",
 324    .version_id = 1,
 325    .minimum_version_id = 1,
 326    .fields = (VMStateField[]) {
 327        VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 328        VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 329        VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 330        VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 331        VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 332        VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 333        VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
 334        VMSTATE_UINT32_ARRAY(prev_level, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
 335        VMSTATE_END_OF_LIST(),
 336    },
 337};
 338
 339static Property pxa2xx_gpio_properties[] = {
 340    DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
 341    DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
 342    DEFINE_PROP_END_OF_LIST(),
 343};
 344
 345static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
 346{
 347    DeviceClass *dc = DEVICE_CLASS(klass);
 348
 349    dc->desc = "PXA2xx GPIO controller";
 350    dc->props = pxa2xx_gpio_properties;
 351    dc->vmsd = &vmstate_pxa2xx_gpio_regs;
 352    dc->realize = pxa2xx_gpio_realize;
 353}
 354
 355static const TypeInfo pxa2xx_gpio_info = {
 356    .name          = TYPE_PXA2XX_GPIO,
 357    .parent        = TYPE_SYS_BUS_DEVICE,
 358    .instance_size = sizeof(PXA2xxGPIOInfo),
 359    .instance_init = pxa2xx_gpio_initfn,
 360    .class_init    = pxa2xx_gpio_class_init,
 361};
 362
 363static void pxa2xx_gpio_register_types(void)
 364{
 365    type_register_static(&pxa2xx_gpio_info);
 366}
 367
 368type_init(pxa2xx_gpio_register_types)
 369