qemu/hw/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 "hw.h"
  22#include "omap.h"
  23/* General-Purpose I/O */
  24struct omap_gpio_s {
  25    qemu_irq irq;
  26    qemu_irq *in;
  27    qemu_irq handler[16];
  28
  29    uint16_t inputs;
  30    uint16_t outputs;
  31    uint16_t dir;
  32    uint16_t edge;
  33    uint16_t mask;
  34    uint16_t ints;
  35    uint16_t pins;
  36};
  37
  38static void omap_gpio_set(void *opaque, int line, int level)
  39{
  40    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  41    uint16_t prev = s->inputs;
  42
  43    if (level)
  44        s->inputs |= 1 << line;
  45    else
  46        s->inputs &= ~(1 << line);
  47
  48    if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
  49                    (1 << line) & s->dir & ~s->mask) {
  50        s->ints |= 1 << line;
  51        qemu_irq_raise(s->irq);
  52    }
  53}
  54
  55static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
  56{
  57    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  58    int offset = addr & OMAP_MPUI_REG_MASK;
  59
  60    switch (offset) {
  61    case 0x00:  /* DATA_INPUT */
  62        return s->inputs & s->pins;
  63
  64    case 0x04:  /* DATA_OUTPUT */
  65        return s->outputs;
  66
  67    case 0x08:  /* DIRECTION_CONTROL */
  68        return s->dir;
  69
  70    case 0x0c:  /* INTERRUPT_CONTROL */
  71        return s->edge;
  72
  73    case 0x10:  /* INTERRUPT_MASK */
  74        return s->mask;
  75
  76    case 0x14:  /* INTERRUPT_STATUS */
  77        return s->ints;
  78
  79    case 0x18:  /* PIN_CONTROL (not in OMAP310) */
  80        OMAP_BAD_REG(addr);
  81        return s->pins;
  82    }
  83
  84    OMAP_BAD_REG(addr);
  85    return 0;
  86}
  87
  88static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
  89                uint32_t value)
  90{
  91    struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  92    int offset = addr & OMAP_MPUI_REG_MASK;
  93    uint16_t diff;
  94    int ln;
  95
  96    switch (offset) {
  97    case 0x00:  /* DATA_INPUT */
  98        OMAP_RO_REG(addr);
  99        return;
 100
 101    case 0x04:  /* DATA_OUTPUT */
 102        diff = (s->outputs ^ value) & ~s->dir;
 103        s->outputs = value;
 104        while ((ln = ffs(diff))) {
 105            ln --;
 106            if (s->handler[ln])
 107                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 108            diff &= ~(1 << ln);
 109        }
 110        break;
 111
 112    case 0x08:  /* DIRECTION_CONTROL */
 113        diff = s->outputs & (s->dir ^ value);
 114        s->dir = value;
 115
 116        value = s->outputs & ~s->dir;
 117        while ((ln = ffs(diff))) {
 118            ln --;
 119            if (s->handler[ln])
 120                qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 121            diff &= ~(1 << ln);
 122        }
 123        break;
 124
 125    case 0x0c:  /* INTERRUPT_CONTROL */
 126        s->edge = value;
 127        break;
 128
 129    case 0x10:  /* INTERRUPT_MASK */
 130        s->mask = value;
 131        break;
 132
 133    case 0x14:  /* INTERRUPT_STATUS */
 134        s->ints &= ~value;
 135        if (!s->ints)
 136            qemu_irq_lower(s->irq);
 137        break;
 138
 139    case 0x18:  /* PIN_CONTROL (not in OMAP310 TRM) */
 140        OMAP_BAD_REG(addr);
 141        s->pins = value;
 142        break;
 143
 144    default:
 145        OMAP_BAD_REG(addr);
 146        return;
 147    }
 148}
 149
 150/* *Some* sources say the memory region is 32-bit.  */
 151static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
 152    omap_badwidth_read16,
 153    omap_gpio_read,
 154    omap_badwidth_read16,
 155};
 156
 157static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
 158    omap_badwidth_write16,
 159    omap_gpio_write,
 160    omap_badwidth_write16,
 161};
 162
 163void omap_gpio_reset(struct omap_gpio_s *s)
 164{
 165    s->inputs = 0;
 166    s->outputs = ~0;
 167    s->dir = ~0;
 168    s->edge = ~0;
 169    s->mask = ~0;
 170    s->ints = 0;
 171    s->pins = ~0;
 172}
 173
 174struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
 175                qemu_irq irq, omap_clk clk)
 176{
 177    int iomemtype;
 178    struct omap_gpio_s *s = (struct omap_gpio_s *)
 179            qemu_mallocz(sizeof(struct omap_gpio_s));
 180
 181    s->irq = irq;
 182    s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
 183    omap_gpio_reset(s);
 184
 185    iomemtype = cpu_register_io_memory(omap_gpio_readfn,
 186                    omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
 187    cpu_register_physical_memory(base, 0x1000, iomemtype);
 188
 189    return s;
 190}
 191
 192qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
 193{
 194    return s->in;
 195}
 196
 197void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
 198{
 199    if (line >= 16 || line < 0)
 200        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
 201    s->handler[line] = handler;
 202}
 203
 204/* General-Purpose Interface of OMAP2 */
 205struct omap2_gpio_s {
 206    qemu_irq irq[2];
 207    qemu_irq wkup;
 208    qemu_irq *in;
 209    qemu_irq handler[32];
 210
 211    uint8_t config[2];
 212    uint32_t inputs;
 213    uint32_t outputs;
 214    uint32_t dir;
 215    uint32_t level[2];
 216    uint32_t edge[2];
 217    uint32_t mask[2];
 218    uint32_t wumask;
 219    uint32_t ints[2];
 220    uint32_t debounce;
 221    uint8_t delay;
 222};
 223
 224static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
 225                int line)
 226{
 227    qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
 228}
 229
 230static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
 231{
 232    if (!(s->config[0] & (1 << 2)))                     /* ENAWAKEUP */
 233        return;
 234    if (!(s->config[0] & (3 << 3)))                     /* Force Idle */
 235        return;
 236    if (!(s->wumask & (1 << line)))
 237        return;
 238
 239    qemu_irq_raise(s->wkup);
 240}
 241
 242static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
 243                uint32_t diff)
 244{
 245    int ln;
 246
 247    s->outputs ^= diff;
 248    diff &= ~s->dir;
 249    while ((ln = ffs(diff))) {
 250        ln --;
 251        qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
 252        diff &= ~(1 << ln);
 253    }
 254}
 255
 256static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
 257{
 258    s->ints[line] |= s->dir &
 259            ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
 260    omap2_gpio_module_int_update(s, line);
 261}
 262
 263static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
 264{
 265    s->ints[0] |= 1 << line;
 266    omap2_gpio_module_int_update(s, 0);
 267    s->ints[1] |= 1 << line;
 268    omap2_gpio_module_int_update(s, 1);
 269    omap2_gpio_module_wake(s, line);
 270}
 271
 272static void omap2_gpio_module_set(void *opaque, int line, int level)
 273{
 274    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 275
 276    if (level) {
 277        if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
 278            omap2_gpio_module_int(s, line);
 279        s->inputs |= 1 << line;
 280    } else {
 281        if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
 282            omap2_gpio_module_int(s, line);
 283        s->inputs &= ~(1 << line);
 284    }
 285}
 286
 287static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
 288{
 289    s->config[0] = 0;
 290    s->config[1] = 2;
 291    s->ints[0] = 0;
 292    s->ints[1] = 0;
 293    s->mask[0] = 0;
 294    s->mask[1] = 0;
 295    s->wumask = 0;
 296    s->dir = ~0;
 297    s->level[0] = 0;
 298    s->level[1] = 0;
 299    s->edge[0] = 0;
 300    s->edge[1] = 0;
 301    s->debounce = 0;
 302    s->delay = 0;
 303}
 304
 305static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
 306{
 307    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 308
 309    switch (addr) {
 310    case 0x00:  /* GPIO_REVISION */
 311        return 0x18;
 312
 313    case 0x10:  /* GPIO_SYSCONFIG */
 314        return s->config[0];
 315
 316    case 0x14:  /* GPIO_SYSSTATUS */
 317        return 0x01;
 318
 319    case 0x18:  /* GPIO_IRQSTATUS1 */
 320        return s->ints[0];
 321
 322    case 0x1c:  /* GPIO_IRQENABLE1 */
 323    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 324    case 0x64:  /* GPIO_SETIRQENABLE1 */
 325        return s->mask[0];
 326
 327    case 0x20:  /* GPIO_WAKEUPENABLE */
 328    case 0x80:  /* GPIO_CLEARWKUENA */
 329    case 0x84:  /* GPIO_SETWKUENA */
 330        return s->wumask;
 331
 332    case 0x28:  /* GPIO_IRQSTATUS2 */
 333        return s->ints[1];
 334
 335    case 0x2c:  /* GPIO_IRQENABLE2 */
 336    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 337    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 338        return s->mask[1];
 339
 340    case 0x30:  /* GPIO_CTRL */
 341        return s->config[1];
 342
 343    case 0x34:  /* GPIO_OE */
 344        return s->dir;
 345
 346    case 0x38:  /* GPIO_DATAIN */
 347        return s->inputs;
 348
 349    case 0x3c:  /* GPIO_DATAOUT */
 350    case 0x90:  /* GPIO_CLEARDATAOUT */
 351    case 0x94:  /* GPIO_SETDATAOUT */
 352        return s->outputs;
 353
 354    case 0x40:  /* GPIO_LEVELDETECT0 */
 355        return s->level[0];
 356
 357    case 0x44:  /* GPIO_LEVELDETECT1 */
 358        return s->level[1];
 359
 360    case 0x48:  /* GPIO_RISINGDETECT */
 361        return s->edge[0];
 362
 363    case 0x4c:  /* GPIO_FALLINGDETECT */
 364        return s->edge[1];
 365
 366    case 0x50:  /* GPIO_DEBOUNCENABLE */
 367        return s->debounce;
 368
 369    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 370        return s->delay;
 371    }
 372
 373    OMAP_BAD_REG(addr);
 374    return 0;
 375}
 376
 377static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
 378                uint32_t value)
 379{
 380    struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
 381    uint32_t diff;
 382    int ln;
 383
 384    switch (addr) {
 385    case 0x00:  /* GPIO_REVISION */
 386    case 0x14:  /* GPIO_SYSSTATUS */
 387    case 0x38:  /* GPIO_DATAIN */
 388        OMAP_RO_REG(addr);
 389        break;
 390
 391    case 0x10:  /* GPIO_SYSCONFIG */
 392        if (((value >> 3) & 3) == 3)
 393            fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
 394        if (value & 2)
 395            omap2_gpio_module_reset(s);
 396        s->config[0] = value & 0x1d;
 397        break;
 398
 399    case 0x18:  /* GPIO_IRQSTATUS1 */
 400        if (s->ints[0] & value) {
 401            s->ints[0] &= ~value;
 402            omap2_gpio_module_level_update(s, 0);
 403        }
 404        break;
 405
 406    case 0x1c:  /* GPIO_IRQENABLE1 */
 407        s->mask[0] = value;
 408        omap2_gpio_module_int_update(s, 0);
 409        break;
 410
 411    case 0x20:  /* GPIO_WAKEUPENABLE */
 412        s->wumask = value;
 413        break;
 414
 415    case 0x28:  /* GPIO_IRQSTATUS2 */
 416        if (s->ints[1] & value) {
 417            s->ints[1] &= ~value;
 418            omap2_gpio_module_level_update(s, 1);
 419        }
 420        break;
 421
 422    case 0x2c:  /* GPIO_IRQENABLE2 */
 423        s->mask[1] = value;
 424        omap2_gpio_module_int_update(s, 1);
 425        break;
 426
 427    case 0x30:  /* GPIO_CTRL */
 428        s->config[1] = value & 7;
 429        break;
 430
 431    case 0x34:  /* GPIO_OE */
 432        diff = s->outputs & (s->dir ^ value);
 433        s->dir = value;
 434
 435        value = s->outputs & ~s->dir;
 436        while ((ln = ffs(diff))) {
 437            diff &= ~(1 <<-- ln);
 438            qemu_set_irq(s->handler[ln], (value >> ln) & 1);
 439        }
 440
 441        omap2_gpio_module_level_update(s, 0);
 442        omap2_gpio_module_level_update(s, 1);
 443        break;
 444
 445    case 0x3c:  /* GPIO_DATAOUT */
 446        omap2_gpio_module_out_update(s, s->outputs ^ value);
 447        break;
 448
 449    case 0x40:  /* GPIO_LEVELDETECT0 */
 450        s->level[0] = value;
 451        omap2_gpio_module_level_update(s, 0);
 452        omap2_gpio_module_level_update(s, 1);
 453        break;
 454
 455    case 0x44:  /* GPIO_LEVELDETECT1 */
 456        s->level[1] = value;
 457        omap2_gpio_module_level_update(s, 0);
 458        omap2_gpio_module_level_update(s, 1);
 459        break;
 460
 461    case 0x48:  /* GPIO_RISINGDETECT */
 462        s->edge[0] = value;
 463        break;
 464
 465    case 0x4c:  /* GPIO_FALLINGDETECT */
 466        s->edge[1] = value;
 467        break;
 468
 469    case 0x50:  /* GPIO_DEBOUNCENABLE */
 470        s->debounce = value;
 471        break;
 472
 473    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 474        s->delay = value;
 475        break;
 476
 477    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 478        s->mask[0] &= ~value;
 479        omap2_gpio_module_int_update(s, 0);
 480        break;
 481
 482    case 0x64:  /* GPIO_SETIRQENABLE1 */
 483        s->mask[0] |= value;
 484        omap2_gpio_module_int_update(s, 0);
 485        break;
 486
 487    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 488        s->mask[1] &= ~value;
 489        omap2_gpio_module_int_update(s, 1);
 490        break;
 491
 492    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 493        s->mask[1] |= value;
 494        omap2_gpio_module_int_update(s, 1);
 495        break;
 496
 497    case 0x80:  /* GPIO_CLEARWKUENA */
 498        s->wumask &= ~value;
 499        break;
 500
 501    case 0x84:  /* GPIO_SETWKUENA */
 502        s->wumask |= value;
 503        break;
 504
 505    case 0x90:  /* GPIO_CLEARDATAOUT */
 506        omap2_gpio_module_out_update(s, s->outputs & value);
 507        break;
 508
 509    case 0x94:  /* GPIO_SETDATAOUT */
 510        omap2_gpio_module_out_update(s, ~s->outputs & value);
 511        break;
 512
 513    default:
 514        OMAP_BAD_REG(addr);
 515        return;
 516    }
 517}
 518
 519static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
 520{
 521    return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
 522}
 523
 524static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
 525                uint32_t value)
 526{
 527    uint32_t cur = 0;
 528    uint32_t mask = 0xffff;
 529
 530    switch (addr & ~3) {
 531    case 0x00:  /* GPIO_REVISION */
 532    case 0x14:  /* GPIO_SYSSTATUS */
 533    case 0x38:  /* GPIO_DATAIN */
 534        OMAP_RO_REG(addr);
 535        break;
 536
 537    case 0x10:  /* GPIO_SYSCONFIG */
 538    case 0x1c:  /* GPIO_IRQENABLE1 */
 539    case 0x20:  /* GPIO_WAKEUPENABLE */
 540    case 0x2c:  /* GPIO_IRQENABLE2 */
 541    case 0x30:  /* GPIO_CTRL */
 542    case 0x34:  /* GPIO_OE */
 543    case 0x3c:  /* GPIO_DATAOUT */
 544    case 0x40:  /* GPIO_LEVELDETECT0 */
 545    case 0x44:  /* GPIO_LEVELDETECT1 */
 546    case 0x48:  /* GPIO_RISINGDETECT */
 547    case 0x4c:  /* GPIO_FALLINGDETECT */
 548    case 0x50:  /* GPIO_DEBOUNCENABLE */
 549    case 0x54:  /* GPIO_DEBOUNCINGTIME */
 550        cur = omap2_gpio_module_read(opaque, addr & ~3) &
 551                ~(mask << ((addr & 3) << 3));
 552
 553        /* Fall through.  */
 554    case 0x18:  /* GPIO_IRQSTATUS1 */
 555    case 0x28:  /* GPIO_IRQSTATUS2 */
 556    case 0x60:  /* GPIO_CLEARIRQENABLE1 */
 557    case 0x64:  /* GPIO_SETIRQENABLE1 */
 558    case 0x70:  /* GPIO_CLEARIRQENABLE2 */
 559    case 0x74:  /* GPIO_SETIREQNEABLE2 */
 560    case 0x80:  /* GPIO_CLEARWKUENA */
 561    case 0x84:  /* GPIO_SETWKUENA */
 562    case 0x90:  /* GPIO_CLEARDATAOUT */
 563    case 0x94:  /* GPIO_SETDATAOUT */
 564        value <<= (addr & 3) << 3;
 565        omap2_gpio_module_write(opaque, addr, cur | value);
 566        break;
 567
 568    default:
 569        OMAP_BAD_REG(addr);
 570        return;
 571    }
 572}
 573
 574static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
 575    omap2_gpio_module_readp,
 576    omap2_gpio_module_readp,
 577    omap2_gpio_module_read,
 578};
 579
 580static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
 581    omap2_gpio_module_writep,
 582    omap2_gpio_module_writep,
 583    omap2_gpio_module_write,
 584};
 585
 586static void omap2_gpio_module_init(struct omap2_gpio_s *s,
 587                struct omap_target_agent_s *ta, int region,
 588                qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
 589                omap_clk fclk, omap_clk iclk)
 590{
 591    int iomemtype;
 592
 593    s->irq[0] = mpu;
 594    s->irq[1] = dsp;
 595    s->wkup = wkup;
 596    s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
 597
 598    iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
 599                    omap2_gpio_module_writefn, s);
 600    omap_l4_attach(ta, region, iomemtype);
 601}
 602
 603struct omap_gpif_s {
 604    struct omap2_gpio_s module[5];
 605    int modules;
 606
 607    int autoidle;
 608    int gpo;
 609};
 610
 611void omap_gpif_reset(struct omap_gpif_s *s)
 612{
 613    int i;
 614
 615    for (i = 0; i < s->modules; i ++)
 616        omap2_gpio_module_reset(s->module + i);
 617
 618    s->autoidle = 0;
 619    s->gpo = 0;
 620}
 621
 622static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
 623{
 624    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
 625
 626    switch (addr) {
 627    case 0x00:  /* IPGENERICOCPSPL_REVISION */
 628        return 0x18;
 629
 630    case 0x10:  /* IPGENERICOCPSPL_SYSCONFIG */
 631        return s->autoidle;
 632
 633    case 0x14:  /* IPGENERICOCPSPL_SYSSTATUS */
 634        return 0x01;
 635
 636    case 0x18:  /* IPGENERICOCPSPL_IRQSTATUS */
 637        return 0x00;
 638
 639    case 0x40:  /* IPGENERICOCPSPL_GPO */
 640        return s->gpo;
 641
 642    case 0x50:  /* IPGENERICOCPSPL_GPI */
 643        return 0x00;
 644    }
 645
 646    OMAP_BAD_REG(addr);
 647    return 0;
 648}
 649
 650static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
 651                uint32_t value)
 652{
 653    struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
 654
 655    switch (addr) {
 656    case 0x00:  /* IPGENERICOCPSPL_REVISION */
 657    case 0x14:  /* IPGENERICOCPSPL_SYSSTATUS */
 658    case 0x18:  /* IPGENERICOCPSPL_IRQSTATUS */
 659    case 0x50:  /* IPGENERICOCPSPL_GPI */
 660        OMAP_RO_REG(addr);
 661        break;
 662
 663    case 0x10:  /* IPGENERICOCPSPL_SYSCONFIG */
 664        if (value & (1 << 1))                                   /* SOFTRESET */
 665            omap_gpif_reset(s);
 666        s->autoidle = value & 1;
 667        break;
 668
 669    case 0x40:  /* IPGENERICOCPSPL_GPO */
 670        s->gpo = value & 1;
 671        break;
 672
 673    default:
 674        OMAP_BAD_REG(addr);
 675        return;
 676    }
 677}
 678
 679static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
 680    omap_gpif_top_read,
 681    omap_gpif_top_read,
 682    omap_gpif_top_read,
 683};
 684
 685static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
 686    omap_gpif_top_write,
 687    omap_gpif_top_write,
 688    omap_gpif_top_write,
 689};
 690
 691struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
 692                qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
 693{
 694    int iomemtype, i;
 695    struct omap_gpif_s *s = (struct omap_gpif_s *)
 696            qemu_mallocz(sizeof(struct omap_gpif_s));
 697    int region[4] = { 0, 2, 4, 5 };
 698
 699    s->modules = modules;
 700    for (i = 0; i < modules; i ++)
 701        omap2_gpio_module_init(s->module + i, ta, region[i],
 702                              irq[i], NULL, NULL, fclk[i], iclk);
 703
 704    omap_gpif_reset(s);
 705
 706    iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
 707                    omap_gpif_top_writefn, s);
 708    omap_l4_attach(ta, 1, iomemtype);
 709
 710    return s;
 711}
 712
 713qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
 714{
 715    if (start >= s->modules * 32 || start < 0)
 716        hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
 717    return s->module[start >> 5].in + (start & 31);
 718}
 719
 720void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
 721{
 722    if (line >= s->modules * 32 || line < 0)
 723        hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
 724    s->module[line >> 5].handler[line & 31] = handler;
 725}
 726