qemu/hw/gpio/omap_gpio.c
<<
>>
Prefs
   1/*
   2 * TI OMAP processors GPIO emulation.
   3 *
   4 * Copyright (C) 2006-2008 Andrzej Zaborowski  <balrog@zabor.org>
   5 * Copyright (C) 2007-2009 Nokia Corporation
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License as
   9 * published by the Free Software Foundation; either version 2 or
  10 * (at your option) version 3 of the License.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along
  18 * with this program; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "hw/hw.h"
  23#include "hw/arm/omap.h"
  24#include "hw/sysbus.h"
  25#include "qemu/error-report.h"
  26
  27struct omap_gpio_s {
  28    qemu_irq irq;
  29    qemu_irq handler[16];
  30
  31    uint16_t inputs;
  32    uint16_t outputs;
  33    uint16_t dir;
  34    uint16_t edge;
  35    uint16_t mask;
  36    uint16_t ints;
  37    uint16_t pins;
  38};
  39
  40#define TYPE_OMAP1_GPIO "omap-gpio"
  41#define OMAP1_GPIO(obj) \
  42    OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO)
  43
  44struct omap_gpif_s {
  45    SysBusDevice parent_obj;
  46
  47    MemoryRegion iomem;
  48    int mpu_model;
  49    void *clk;
  50    struct omap_gpio_s omap1;
  51};
  52
  53/* General-Purpose I/O of OMAP1 */
  54static void omap_gpio_set(void *opaque, int line, int level)
  55{
  56    struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
  57    uint16_t prev = s->inputs;
  58
  59    if (level)
  60        s->inputs |= 1 << line;
  61    else
  62        s->inputs &= ~(1 << line);
  63
  64    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
  65                    (1 << line) & s->dir & ~s->mask) {
  66        s->ints |= 1 << line;
  67        qemu_irq_raise(s->irq);
  68    }
  69}
  70
  71static uint64_t omap_gpio_read(void *opaque, hwaddr addr,
  72                               unsigned size)
  73{
  74    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  75    int offset = addr & OMAP_MPUI_REG_MASK;
  76
  77    if (size != 2) {
  78        return omap_badwidth_read16(opaque, addr);
  79    }
  80
  81    switch (offset) {
  82    case 0x00:  /* DATA_INPUT */
  83        return s->inputs & s->pins;
  84
  85    case 0x04:  /* DATA_OUTPUT */
  86        return s->outputs;
  87
  88    case 0x08:  /* DIRECTION_CONTROL */
  89        return s->dir;
  90
  91    case 0x0c:  /* INTERRUPT_CONTROL */
  92        return s->edge;
  93
  94    case 0x10:  /* INTERRUPT_MASK */
  95        return s->mask;
  96
  97    case 0x14:  /* INTERRUPT_STATUS */
  98        return s->ints;
  99
 100    case 0x18:  /* PIN_CONTROL (not in OMAP310) */
 101        OMAP_BAD_REG(addr);
 102        return s->pins;
 103    }
 104
 105    OMAP_BAD_REG(addr);
 106    return 0;
 107}
 108
 109static void omap_gpio_write(void *opaque, hwaddr addr,
 110                            uint64_t value, unsigned size)
 111{
 112    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
 113    int offset = addr & OMAP_MPUI_REG_MASK;
 114    uint16_t diff;
 115    int ln;
 116
 117    if (size != 2) {
 118        omap_badwidth_write16(opaque, addr, value);
 119        return;
 120    }
 121
 122    switch (offset) {
 123    case 0x00:  /* DATA_INPUT */
 124        OMAP_RO_REG(addr);
 125        return;
 126
 127    case 0x04:  /* DATA_OUTPUT */
 128        diff = (s->outputs ^ value) & ~s->dir;
 129        s->outputs = value;
 130        while ((ln = ctz32(diff)) != 32) {
 131            if (s->handler[ln])
 132                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 133            diff &= ~(1 << ln);
 134        }
 135        break;
 136
 137    case 0x08:  /* DIRECTION_CONTROL */
 138        diff = s->outputs & (s->dir ^ value);
 139        s->dir = value;
 140
 141        value = s->outputs & ~s->dir;
 142        while ((ln = ctz32(diff)) != 32) {
 143            if (s->handler[ln])
 144                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 145            diff &= ~(1 << ln);
 146        }
 147        break;
 148
 149    case 0x0c:  /* INTERRUPT_CONTROL */
 150        s->edge = value;
 151        break;
 152
 153    case 0x10:  /* INTERRUPT_MASK */
 154        s->mask = value;
 155        break;
 156
 157    case 0x14:  /* INTERRUPT_STATUS */
 158        s->ints &= ~value;
 159        if (!s->ints)
 160            qemu_irq_lower(s->irq);
 161        break;
 162
 163    case 0x18:  /* PIN_CONTROL (not in OMAP310 TRM) */
 164        OMAP_BAD_REG(addr);
 165        s->pins = value;
 166        break;
 167
 168    default:
 169        OMAP_BAD_REG(addr);
 170        return;
 171    }
 172}
 173
 174/* *Some* sources say the memory region is 32-bit.  */
 175static const MemoryRegionOps omap_gpio_ops = {
 176    .read = omap_gpio_read,
 177    .write = omap_gpio_write,
 178    .endianness = DEVICE_NATIVE_ENDIAN,
 179};
 180
 181static void omap_gpio_reset(struct omap_gpio_s *s)
 182{
 183    s->inputs = 0;
 184    s->outputs = ~0;
 185    s->dir = ~0;
 186    s->edge = ~0;
 187    s->mask = ~0;
 188    s->ints = 0;
 189    s->pins = ~0;
 190}
 191
 192struct omap2_gpio_s {
 193    qemu_irq irq[2];
 194    qemu_irq wkup;
 195    qemu_irq *handler;
 196    MemoryRegion iomem;
 197
 198    uint8_t revision;
 199    uint8_t config[2];
 200    uint32_t inputs;
 201    uint32_t outputs;
 202    uint32_t dir;
 203    uint32_t level[2];
 204    uint32_t edge[2];
 205    uint32_t mask[2];
 206    uint32_t wumask;
 207    uint32_t ints[2];
 208    uint32_t debounce;
 209    uint8_t delay;
 210};
 211
 212#define TYPE_OMAP2_GPIO "omap2-gpio"
 213#define OMAP2_GPIO(obj) \
 214    OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO)
 215
 216struct omap2_gpif_s {
 217    SysBusDevice parent_obj;
 218
 219    MemoryRegion iomem;
 220    int mpu_model;
 221    void *iclk;
 222    void *fclk[6];
 223    int modulecount;
 224    struct omap2_gpio_s *modules;
 225    qemu_irq *handler;
 226    int autoidle;
 227    int gpo;
 228};
 229
 230/* General-Purpose Interface of OMAP2/3 */
 231static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
 232                                                int line)
 233{
 234    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
 235}
 236
 237static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
 238{
 239    if (!(s->config[0] & (1 << 2)))                     /* ENAWAKEUP */
 240        return;
 241    if (!(s->config[0] & (3 << 3)))                     /* Force Idle */
 242        return;
 243    if (!(s->wumask & (1 << line)))
 244        return;
 245
 246    qemu_irq_raise(s->wkup);
 247}
 248
 249static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
 250                uint32_t diff)
 251{
 252    int ln;
 253
 254    s->outputs ^= diff;
 255    diff &= ~s->dir;
 256    while ((ln = ctz32(diff)) != 32) {
 257        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
 258        diff &= ~(1 << ln);
 259    }
 260}
 261
 262static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
 263{
 264    s->ints[line] |= s->dir &
 265            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
 266    omap2_gpio_module_int_update(s, line);
 267}
 268
 269static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
 270{
 271    s->ints[0] |= 1 << line;
 272    omap2_gpio_module_int_update(s, 0);
 273    s->ints[1] |= 1 << line;
 274    omap2_gpio_module_int_update(s, 1);
 275    omap2_gpio_module_wake(s, line);
 276}
 277
 278static void omap2_gpio_set(void *opaque, int line, int level)
 279{
 280    struct omap2_gpif_s *p = opaque;
 281    struct omap2_gpio_s *s = &p->modules[line >> 5];
 282
 283    line &= 31;
 284    if (level) {
 285        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
 286            omap2_gpio_module_int(s, line);
 287        s->inputs |= 1 << line;
 288    } else {
 289        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
 290            omap2_gpio_module_int(s, line);
 291        s->inputs &= ~(1 << line);
 292    }
 293}
 294
 295static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
 296{
 297    s->config[0] = 0;
 298    s->config[1] = 2;
 299    s->ints[0] = 0;
 300    s->ints[1] = 0;
 301    s->mask[0] = 0;
 302    s->mask[1] = 0;
 303    s->wumask = 0;
 304    s->dir = ~0;
 305    s->level[0] = 0;
 306    s->level[1] = 0;
 307    s->edge[0] = 0;
 308    s->edge[1] = 0;
 309    s->debounce = 0;
 310    s->delay = 0;
 311}
 312
 313static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr)
 314{
 315    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 316
 317    switch (addr) {
 318    case 0x00:  /* GPIO_REVISION */
 319        return s->revision;
 320
 321    case 0x10:  /* GPIO_SYSCONFIG */
 322        return s->config[0];
 323
 324    case 0x14:  /* GPIO_SYSSTATUS */
 325        return 0x01;
 326
 327    case 0x18:  /* GPIO_IRQSTATUS1 */
 328        return s->ints[0];
 329
 330    case 0x1c:  /* GPIO_IRQENABLE1 */
 331    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 332    case 0x64:  /* GPIO_SETIRQENABLE1 */
 333        return s->mask[0];
 334
 335    case 0x20:  /* GPIO_WAKEUPENABLE */
 336    case 0x80:  /* GPIO_CLEARWKUENA */
 337    case 0x84:  /* GPIO_SETWKUENA */
 338        return s->wumask;
 339
 340    case 0x28:  /* GPIO_IRQSTATUS2 */
 341        return s->ints[1];
 342
 343    case 0x2c:  /* GPIO_IRQENABLE2 */
 344    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 345    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 346        return s->mask[1];
 347
 348    case 0x30:  /* GPIO_CTRL */
 349        return s->config[1];
 350
 351    case 0x34:  /* GPIO_OE */
 352        return s->dir;
 353
 354    case 0x38:  /* GPIO_DATAIN */
 355        return s->inputs;
 356
 357    case 0x3c:  /* GPIO_DATAOUT */
 358    case 0x90:  /* GPIO_CLEARDATAOUT */
 359    case 0x94:  /* GPIO_SETDATAOUT */
 360        return s->outputs;
 361
 362    case 0x40:  /* GPIO_LEVELDETECT0 */
 363        return s->level[0];
 364
 365    case 0x44:  /* GPIO_LEVELDETECT1 */
 366        return s->level[1];
 367
 368    case 0x48:  /* GPIO_RISINGDETECT */
 369        return s->edge[0];
 370
 371    case 0x4c:  /* GPIO_FALLINGDETECT */
 372        return s->edge[1];
 373
 374    case 0x50:  /* GPIO_DEBOUNCENABLE */
 375        return s->debounce;
 376
 377    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 378        return s->delay;
 379    }
 380
 381    OMAP_BAD_REG(addr);
 382    return 0;
 383}
 384
 385static void omap2_gpio_module_write(void *opaque, hwaddr addr,
 386                uint32_t value)
 387{
 388    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 389    uint32_t diff;
 390    int ln;
 391
 392    switch (addr) {
 393    case 0x00:  /* GPIO_REVISION */
 394    case 0x14:  /* GPIO_SYSSTATUS */
 395    case 0x38:  /* GPIO_DATAIN */
 396        OMAP_RO_REG(addr);
 397        break;
 398
 399    case 0x10:  /* GPIO_SYSCONFIG */
 400        if (((value >> 3) & 3) == 3)
 401            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
 402        if (value & 2)
 403            omap2_gpio_module_reset(s);
 404        s->config[0] = value & 0x1d;
 405        break;
 406
 407    case 0x18:  /* GPIO_IRQSTATUS1 */
 408        if (s->ints[0] & value) {
 409            s->ints[0] &= ~value;
 410            omap2_gpio_module_level_update(s, 0);
 411        }
 412        break;
 413
 414    case 0x1c:  /* GPIO_IRQENABLE1 */
 415        s->mask[0] = value;
 416        omap2_gpio_module_int_update(s, 0);
 417        break;
 418
 419    case 0x20:  /* GPIO_WAKEUPENABLE */
 420        s->wumask = value;
 421        break;
 422
 423    case 0x28:  /* GPIO_IRQSTATUS2 */
 424        if (s->ints[1] & value) {
 425            s->ints[1] &= ~value;
 426            omap2_gpio_module_level_update(s, 1);
 427        }
 428        break;
 429
 430    case 0x2c:  /* GPIO_IRQENABLE2 */
 431        s->mask[1] = value;
 432        omap2_gpio_module_int_update(s, 1);
 433        break;
 434
 435    case 0x30:  /* GPIO_CTRL */
 436        s->config[1] = value & 7;
 437        break;
 438
 439    case 0x34:  /* GPIO_OE */
 440        diff = s->outputs & (s->dir ^ value);
 441        s->dir = value;
 442
 443        value = s->outputs & ~s->dir;
 444        while ((ln = ctz32(diff)) != 32) {
 445            diff &= ~(1 << ln);
 446            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 447        }
 448
 449        omap2_gpio_module_level_update(s, 0);
 450        omap2_gpio_module_level_update(s, 1);
 451        break;
 452
 453    case 0x3c:  /* GPIO_DATAOUT */
 454        omap2_gpio_module_out_update(s, s->outputs ^ value);
 455        break;
 456
 457    case 0x40:  /* GPIO_LEVELDETECT0 */
 458        s->level[0] = value;
 459        omap2_gpio_module_level_update(s, 0);
 460        omap2_gpio_module_level_update(s, 1);
 461        break;
 462
 463    case 0x44:  /* GPIO_LEVELDETECT1 */
 464        s->level[1] = value;
 465        omap2_gpio_module_level_update(s, 0);
 466        omap2_gpio_module_level_update(s, 1);
 467        break;
 468
 469    case 0x48:  /* GPIO_RISINGDETECT */
 470        s->edge[0] = value;
 471        break;
 472
 473    case 0x4c:  /* GPIO_FALLINGDETECT */
 474        s->edge[1] = value;
 475        break;
 476
 477    case 0x50:  /* GPIO_DEBOUNCENABLE */
 478        s->debounce = value;
 479        break;
 480
 481    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 482        s->delay = value;
 483        break;
 484
 485    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 486        s->mask[0] &= ~value;
 487        omap2_gpio_module_int_update(s, 0);
 488        break;
 489
 490    case 0x64:  /* GPIO_SETIRQENABLE1 */
 491        s->mask[0] |= value;
 492        omap2_gpio_module_int_update(s, 0);
 493        break;
 494
 495    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 496        s->mask[1] &= ~value;
 497        omap2_gpio_module_int_update(s, 1);
 498        break;
 499
 500    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 501        s->mask[1] |= value;
 502        omap2_gpio_module_int_update(s, 1);
 503        break;
 504
 505    case 0x80:  /* GPIO_CLEARWKUENA */
 506        s->wumask &= ~value;
 507        break;
 508
 509    case 0x84:  /* GPIO_SETWKUENA */
 510        s->wumask |= value;
 511        break;
 512
 513    case 0x90:  /* GPIO_CLEARDATAOUT */
 514        omap2_gpio_module_out_update(s, s->outputs & value);
 515        break;
 516
 517    case 0x94:  /* GPIO_SETDATAOUT */
 518        omap2_gpio_module_out_update(s, ~s->outputs & value);
 519        break;
 520
 521    default:
 522        OMAP_BAD_REG(addr);
 523        return;
 524    }
 525}
 526
 527static uint32_t omap2_gpio_module_readp(void *opaque, hwaddr addr)
 528{
 529    return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3);
 530}
 531
 532static void omap2_gpio_module_writep(void *opaque, hwaddr addr,
 533                uint32_t value)
 534{
 535    uint32_t cur = 0;
 536    uint32_t mask = 0xffff;
 537
 538    switch (addr & ~3) {
 539    case 0x00:  /* GPIO_REVISION */
 540    case 0x14:  /* GPIO_SYSSTATUS */
 541    case 0x38:  /* GPIO_DATAIN */
 542        OMAP_RO_REG(addr);
 543        break;
 544
 545    case 0x10:  /* GPIO_SYSCONFIG */
 546    case 0x1c:  /* GPIO_IRQENABLE1 */
 547    case 0x20:  /* GPIO_WAKEUPENABLE */
 548    case 0x2c:  /* GPIO_IRQENABLE2 */
 549    case 0x30:  /* GPIO_CTRL */
 550    case 0x34:  /* GPIO_OE */
 551    case 0x3c:  /* GPIO_DATAOUT */
 552    case 0x40:  /* GPIO_LEVELDETECT0 */
 553    case 0x44:  /* GPIO_LEVELDETECT1 */
 554    case 0x48:  /* GPIO_RISINGDETECT */
 555    case 0x4c:  /* GPIO_FALLINGDETECT */
 556    case 0x50:  /* GPIO_DEBOUNCENABLE */
 557    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 558        cur = omap2_gpio_module_read(opaque, addr & ~3) &
 559                ~(mask << ((addr & 3) << 3));
 560
 561        /* Fall through.  */
 562    case 0x18:  /* GPIO_IRQSTATUS1 */
 563    case 0x28:  /* GPIO_IRQSTATUS2 */
 564    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 565    case 0x64:  /* GPIO_SETIRQENABLE1 */
 566    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 567    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 568    case 0x80:  /* GPIO_CLEARWKUENA */
 569    case 0x84:  /* GPIO_SETWKUENA */
 570    case 0x90:  /* GPIO_CLEARDATAOUT */
 571    case 0x94:  /* GPIO_SETDATAOUT */
 572        value <<= (addr & 3) << 3;
 573        omap2_gpio_module_write(opaque, addr, cur | value);
 574        break;
 575
 576    default:
 577        OMAP_BAD_REG(addr);
 578        return;
 579    }
 580}
 581
 582static const MemoryRegionOps omap2_gpio_module_ops = {
 583    .old_mmio = {
 584        .read = {
 585            omap2_gpio_module_readp,
 586            omap2_gpio_module_readp,
 587            omap2_gpio_module_read,
 588        },
 589        .write = {
 590            omap2_gpio_module_writep,
 591            omap2_gpio_module_writep,
 592            omap2_gpio_module_write,
 593        },
 594    },
 595    .endianness = DEVICE_NATIVE_ENDIAN,
 596};
 597
 598static void omap_gpif_reset(DeviceState *dev)
 599{
 600    struct omap_gpif_s *s = OMAP1_GPIO(dev);
 601
 602    omap_gpio_reset(&s->omap1);
 603}
 604
 605static void omap2_gpif_reset(DeviceState *dev)
 606{
 607    struct omap2_gpif_s *s = OMAP2_GPIO(dev);
 608    int i;
 609
 610    for (i = 0; i < s->modulecount; i++) {
 611        omap2_gpio_module_reset(&s->modules[i]);
 612    }
 613    s->autoidle = 0;
 614    s->gpo = 0;
 615}
 616
 617static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr,
 618                                    unsigned size)
 619{
 620    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 621
 622    switch (addr) {
 623    case 0x00:  /* IPGENERICOCPSPL_REVISION */
 624        return 0x18;
 625
 626    case 0x10:  /* IPGENERICOCPSPL_SYSCONFIG */
 627        return s->autoidle;
 628
 629    case 0x14:  /* IPGENERICOCPSPL_SYSSTATUS */
 630        return 0x01;
 631
 632    case 0x18:  /* IPGENERICOCPSPL_IRQSTATUS */
 633        return 0x00;
 634
 635    case 0x40:  /* IPGENERICOCPSPL_GPO */
 636        return s->gpo;
 637
 638    case 0x50:  /* IPGENERICOCPSPL_GPI */
 639        return 0x00;
 640    }
 641
 642    OMAP_BAD_REG(addr);
 643    return 0;
 644}
 645
 646static void omap2_gpif_top_write(void *opaque, hwaddr addr,
 647                                 uint64_t value, unsigned size)
 648{
 649    struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
 650
 651    switch (addr) {
 652    case 0x00:  /* IPGENERICOCPSPL_REVISION */
 653    case 0x14:  /* IPGENERICOCPSPL_SYSSTATUS */
 654    case 0x18:  /* IPGENERICOCPSPL_IRQSTATUS */
 655    case 0x50:  /* IPGENERICOCPSPL_GPI */
 656        OMAP_RO_REG(addr);
 657        break;
 658
 659    case 0x10:  /* IPGENERICOCPSPL_SYSCONFIG */
 660        if (value & (1 << 1))                                   /* SOFTRESET */
 661            omap2_gpif_reset(DEVICE(s));
 662        s->autoidle = value & 1;
 663        break;
 664
 665    case 0x40:  /* IPGENERICOCPSPL_GPO */
 666        s->gpo = value & 1;
 667        break;
 668
 669    default:
 670        OMAP_BAD_REG(addr);
 671        return;
 672    }
 673}
 674
 675static const MemoryRegionOps omap2_gpif_top_ops = {
 676    .read = omap2_gpif_top_read,
 677    .write = omap2_gpif_top_write,
 678    .endianness = DEVICE_NATIVE_ENDIAN,
 679};
 680
 681static int omap_gpio_init(SysBusDevice *sbd)
 682{
 683    DeviceState *dev = DEVICE(sbd);
 684    struct omap_gpif_s *s = OMAP1_GPIO(dev);
 685
 686    if (!s->clk) {
 687        error_report("omap-gpio: clk not connected");
 688        return -1;
 689    }
 690    qdev_init_gpio_in(dev, omap_gpio_set, 16);
 691    qdev_init_gpio_out(dev, s->omap1.handler, 16);
 692    sysbus_init_irq(sbd, &s->omap1.irq);
 693    memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1,
 694                          "omap.gpio", 0x1000);
 695    sysbus_init_mmio(sbd, &s->iomem);
 696    return 0;
 697}
 698
 699static int omap2_gpio_init(SysBusDevice *sbd)
 700{
 701    DeviceState *dev = DEVICE(sbd);
 702    struct omap2_gpif_s *s = OMAP2_GPIO(dev);
 703    int i;
 704
 705    if (!s->iclk) {
 706        error_report("omap2-gpio: iclk not connected");
 707        return -1;
 708    }
 709
 710    s->modulecount = s->mpu_model < omap2430 ? 4
 711                   : s->mpu_model < omap3430 ? 5
 712                   : 6;
 713
 714    for (i = 0; i < s->modulecount; i++) {
 715        if (!s->fclk[i]) {
 716            error_report("omap2-gpio: fclk%d not connected", i);
 717            return -1;
 718        }
 719    }
 720
 721    if (s->mpu_model < omap3430) {
 722        memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s,
 723                              "omap2.gpio", 0x1000);
 724        sysbus_init_mmio(sbd, &s->iomem);
 725    }
 726
 727    s->modules = g_new0(struct omap2_gpio_s, s->modulecount);
 728    s->handler = g_new0(qemu_irq, s->modulecount * 32);
 729    qdev_init_gpio_in(dev, omap2_gpio_set, s->modulecount * 32);
 730    qdev_init_gpio_out(dev, s->handler, s->modulecount * 32);
 731
 732    for (i = 0; i < s->modulecount; i++) {
 733        struct omap2_gpio_s *m = &s->modules[i];
 734
 735        m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
 736        m->handler = &s->handler[i * 32];
 737        sysbus_init_irq(sbd, &m->irq[0]); /* mpu irq */
 738        sysbus_init_irq(sbd, &m->irq[1]); /* dsp irq */
 739        sysbus_init_irq(sbd, &m->wkup);
 740        memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m,
 741                              "omap.gpio-module", 0x1000);
 742        sysbus_init_mmio(sbd, &m->iomem);
 743    }
 744
 745    return 0;
 746}
 747
 748/* Using qdev pointer properties for the clocks is not ideal.
 749 * qdev should support a generic means of defining a 'port' with
 750 * an arbitrary interface for connecting two devices. Then we
 751 * could reframe the omap clock API in terms of clock ports,
 752 * and get some type safety. For now the best qdev provides is
 753 * passing an arbitrary pointer.
 754 * (It's not possible to pass in the string which is the clock
 755 * name, because this device does not have the necessary information
 756 * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
 757 * translation.)
 758 */
 759
 760static Property omap_gpio_properties[] = {
 761    DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
 762    DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
 763    DEFINE_PROP_END_OF_LIST(),
 764};
 765
 766static void omap_gpio_class_init(ObjectClass *klass, void *data)
 767{
 768    DeviceClass *dc = DEVICE_CLASS(klass);
 769    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 770
 771    k->init = omap_gpio_init;
 772    dc->reset = omap_gpif_reset;
 773    dc->props = omap_gpio_properties;
 774    /* Reason: pointer property "clk" */
 775    dc->cannot_instantiate_with_device_add_yet = true;
 776}
 777
 778static const TypeInfo omap_gpio_info = {
 779    .name          = TYPE_OMAP1_GPIO,
 780    .parent        = TYPE_SYS_BUS_DEVICE,
 781    .instance_size = sizeof(struct omap_gpif_s),
 782    .class_init    = omap_gpio_class_init,
 783};
 784
 785static Property omap2_gpio_properties[] = {
 786    DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
 787    DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
 788    DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
 789    DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
 790    DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
 791    DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
 792    DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
 793    DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
 794    DEFINE_PROP_END_OF_LIST(),
 795};
 796
 797static void omap2_gpio_class_init(ObjectClass *klass, void *data)
 798{
 799    DeviceClass *dc = DEVICE_CLASS(klass);
 800    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 801
 802    k->init = omap2_gpio_init;
 803    dc->reset = omap2_gpif_reset;
 804    dc->props = omap2_gpio_properties;
 805    /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */
 806    dc->cannot_instantiate_with_device_add_yet = true;
 807}
 808
 809static const TypeInfo omap2_gpio_info = {
 810    .name          = TYPE_OMAP2_GPIO,
 811    .parent        = TYPE_SYS_BUS_DEVICE,
 812    .instance_size = sizeof(struct omap2_gpif_s),
 813    .class_init    = omap2_gpio_class_init,
 814};
 815
 816static void omap_gpio_register_types(void)
 817{
 818    type_register_static(&omap_gpio_info);
 819    type_register_static(&omap2_gpio_info);
 820}
 821
 822type_init(omap_gpio_register_types)
 823