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