qemu/hw/i2c/omap_i2c.c
<<
>>
Prefs
   1/*
   2 * TI OMAP on-chip I2C controller.  Only "new I2C" mode supported.
   3 *
   4 * Copyright (C) 2007 Andrzej Zaborowski  <balrog@zabor.org>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of
   9 * the License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along
  17 * with this program; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "qemu/log.h"
  22#include "qemu/module.h"
  23#include "hw/i2c/i2c.h"
  24#include "hw/irq.h"
  25#include "hw/qdev-properties.h"
  26#include "hw/arm/omap.h"
  27#include "hw/sysbus.h"
  28#include "qemu/error-report.h"
  29#include "qapi/error.h"
  30
  31#define TYPE_OMAP_I2C "omap_i2c"
  32#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
  33
  34typedef struct OMAPI2CState {
  35    SysBusDevice parent_obj;
  36
  37    MemoryRegion iomem;
  38    qemu_irq irq;
  39    qemu_irq drq[2];
  40    I2CBus *bus;
  41
  42    uint8_t revision;
  43    void *iclk;
  44    void *fclk;
  45
  46    uint8_t mask;
  47    uint16_t stat;
  48    uint16_t dma;
  49    uint16_t count;
  50    int count_cur;
  51    uint32_t fifo;
  52    int rxlen;
  53    int txlen;
  54    uint16_t control;
  55    uint16_t addr[2];
  56    uint8_t divider;
  57    uint8_t times[2];
  58    uint16_t test;
  59} OMAPI2CState;
  60
  61#define OMAP2_INTR_REV  0x34
  62#define OMAP2_GC_REV    0x34
  63
  64static void omap_i2c_interrupts_update(OMAPI2CState *s)
  65{
  66    qemu_set_irq(s->irq, s->stat & s->mask);
  67    if ((s->dma >> 15) & 1)                                     /* RDMA_EN */
  68        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);            /* RRDY */
  69    if ((s->dma >> 7) & 1)                                      /* XDMA_EN */
  70        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);            /* XRDY */
  71}
  72
  73static void omap_i2c_fifo_run(OMAPI2CState *s)
  74{
  75    int ack = 1;
  76
  77    if (!i2c_bus_busy(s->bus))
  78        return;
  79
  80    if ((s->control >> 2) & 1) {                                /* RM */
  81        if ((s->control >> 1) & 1) {                            /* STP */
  82            i2c_end_transfer(s->bus);
  83            s->control &= ~(1 << 1);                            /* STP */
  84            s->count_cur = s->count;
  85            s->txlen = 0;
  86        } else if ((s->control >> 9) & 1) {                     /* TRX */
  87            while (ack && s->txlen)
  88                ack = (i2c_send(s->bus,
  89                                        (s->fifo >> ((-- s->txlen) << 3)) &
  90                                        0xff) >= 0);
  91            s->stat |= 1 << 4;                                  /* XRDY */
  92        } else {
  93            while (s->rxlen < 4)
  94                s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
  95            s->stat |= 1 << 3;                                  /* RRDY */
  96        }
  97    } else {
  98        if ((s->control >> 9) & 1) {                            /* TRX */
  99            while (ack && s->count_cur && s->txlen) {
 100                ack = (i2c_send(s->bus,
 101                                        (s->fifo >> ((-- s->txlen) << 3)) &
 102                                        0xff) >= 0);
 103                s->count_cur --;
 104            }
 105            if (ack && s->count_cur)
 106                s->stat |= 1 << 4;                              /* XRDY */
 107            else
 108                s->stat &= ~(1 << 4);                           /* XRDY */
 109            if (!s->count_cur) {
 110                s->stat |= 1 << 2;                              /* ARDY */
 111                s->control &= ~(1 << 10);                       /* MST */
 112            }
 113        } else {
 114            while (s->count_cur && s->rxlen < 4) {
 115                s->fifo |= i2c_recv(s->bus) << ((s->rxlen ++) << 3);
 116                s->count_cur --;
 117            }
 118            if (s->rxlen)
 119                s->stat |= 1 << 3;                              /* RRDY */
 120            else
 121                s->stat &= ~(1 << 3);                           /* RRDY */
 122        }
 123        if (!s->count_cur) {
 124            if ((s->control >> 1) & 1) {                        /* STP */
 125                i2c_end_transfer(s->bus);
 126                s->control &= ~(1 << 1);                        /* STP */
 127                s->count_cur = s->count;
 128                s->txlen = 0;
 129            } else {
 130                s->stat |= 1 << 2;                              /* ARDY */
 131                s->control &= ~(1 << 10);                       /* MST */
 132            }
 133        }
 134    }
 135
 136    s->stat |= (!ack) << 1;                                     /* NACK */
 137    if (!ack)
 138        s->control &= ~(1 << 1);                                /* STP */
 139}
 140
 141static void omap_i2c_reset(DeviceState *dev)
 142{
 143    OMAPI2CState *s = OMAP_I2C(dev);
 144
 145    s->mask = 0;
 146    s->stat = 0;
 147    s->dma = 0;
 148    s->count = 0;
 149    s->count_cur = 0;
 150    s->fifo = 0;
 151    s->rxlen = 0;
 152    s->txlen = 0;
 153    s->control = 0;
 154    s->addr[0] = 0;
 155    s->addr[1] = 0;
 156    s->divider = 0;
 157    s->times[0] = 0;
 158    s->times[1] = 0;
 159    s->test = 0;
 160}
 161
 162static uint32_t omap_i2c_read(void *opaque, hwaddr addr)
 163{
 164    OMAPI2CState *s = opaque;
 165    int offset = addr & OMAP_MPUI_REG_MASK;
 166    uint16_t ret;
 167
 168    switch (offset) {
 169    case 0x00:  /* I2C_REV */
 170        return s->revision;                                     /* REV */
 171
 172    case 0x04:  /* I2C_IE */
 173        return s->mask;
 174
 175    case 0x08:  /* I2C_STAT */
 176        return s->stat | (i2c_bus_busy(s->bus) << 12);
 177
 178    case 0x0c:  /* I2C_IV */
 179        if (s->revision >= OMAP2_INTR_REV)
 180            break;
 181        ret = ctz32(s->stat & s->mask);
 182        if (ret != 32) {
 183            s->stat ^= 1 << ret;
 184            ret++;
 185        } else {
 186            ret = 0;
 187        }
 188        omap_i2c_interrupts_update(s);
 189        return ret;
 190
 191    case 0x10:  /* I2C_SYSS */
 192        return (s->control >> 15) & 1;                          /* I2C_EN */
 193
 194    case 0x14:  /* I2C_BUF */
 195        return s->dma;
 196
 197    case 0x18:  /* I2C_CNT */
 198        return s->count_cur;                                    /* DCOUNT */
 199
 200    case 0x1c:  /* I2C_DATA */
 201        ret = 0;
 202        if (s->control & (1 << 14)) {                           /* BE */
 203            ret |= ((s->fifo >> 0) & 0xff) << 8;
 204            ret |= ((s->fifo >> 8) & 0xff) << 0;
 205        } else {
 206            ret |= ((s->fifo >> 8) & 0xff) << 8;
 207            ret |= ((s->fifo >> 0) & 0xff) << 0;
 208        }
 209        if (s->rxlen == 1) {
 210            s->stat |= 1 << 15;                                 /* SBD */
 211            s->rxlen = 0;
 212        } else if (s->rxlen > 1) {
 213            if (s->rxlen > 2)
 214                s->fifo >>= 16;
 215            s->rxlen -= 2;
 216        } else {
 217            /* XXX: remote access (qualifier) error - what's that?  */
 218        }
 219        if (!s->rxlen) {
 220            s->stat &= ~(1 << 3);                               /* RRDY */
 221            if (((s->control >> 10) & 1) &&                     /* MST */
 222                            ((~s->control >> 9) & 1)) {         /* TRX */
 223                s->stat |= 1 << 2;                              /* ARDY */
 224                s->control &= ~(1 << 10);                       /* MST */
 225            }
 226        }
 227        s->stat &= ~(1 << 11);                                  /* ROVR */
 228        omap_i2c_fifo_run(s);
 229        omap_i2c_interrupts_update(s);
 230        return ret;
 231
 232    case 0x20:  /* I2C_SYSC */
 233        return 0;
 234
 235    case 0x24:  /* I2C_CON */
 236        return s->control;
 237
 238    case 0x28:  /* I2C_OA */
 239        return s->addr[0];
 240
 241    case 0x2c:  /* I2C_SA */
 242        return s->addr[1];
 243
 244    case 0x30:  /* I2C_PSC */
 245        return s->divider;
 246
 247    case 0x34:  /* I2C_SCLL */
 248        return s->times[0];
 249
 250    case 0x38:  /* I2C_SCLH */
 251        return s->times[1];
 252
 253    case 0x3c:  /* I2C_SYSTEST */
 254        if (s->test & (1 << 15)) {                              /* ST_EN */
 255            s->test ^= 0xa;
 256            return s->test;
 257        } else
 258            return s->test & ~0x300f;
 259    }
 260
 261    OMAP_BAD_REG(addr);
 262    return 0;
 263}
 264
 265static void omap_i2c_write(void *opaque, hwaddr addr,
 266                uint32_t value)
 267{
 268    OMAPI2CState *s = opaque;
 269    int offset = addr & OMAP_MPUI_REG_MASK;
 270    int nack;
 271
 272    switch (offset) {
 273    case 0x00:  /* I2C_REV */
 274    case 0x0c:  /* I2C_IV */
 275    case 0x10:  /* I2C_SYSS */
 276        OMAP_RO_REG(addr);
 277        return;
 278
 279    case 0x04:  /* I2C_IE */
 280        s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
 281        break;
 282
 283    case 0x08:  /* I2C_STAT */
 284        if (s->revision < OMAP2_INTR_REV) {
 285            OMAP_RO_REG(addr);
 286            return;
 287        }
 288
 289        /* RRDY and XRDY are reset by hardware. (in all versions???) */
 290        s->stat &= ~(value & 0x27);
 291        omap_i2c_interrupts_update(s);
 292        break;
 293
 294    case 0x14:  /* I2C_BUF */
 295        s->dma = value & 0x8080;
 296        if (value & (1 << 15))                                  /* RDMA_EN */
 297            s->mask &= ~(1 << 3);                               /* RRDY_IE */
 298        if (value & (1 << 7))                                   /* XDMA_EN */
 299            s->mask &= ~(1 << 4);                               /* XRDY_IE */
 300        break;
 301
 302    case 0x18:  /* I2C_CNT */
 303        s->count = value;                                       /* DCOUNT */
 304        break;
 305
 306    case 0x1c:  /* I2C_DATA */
 307        if (s->txlen > 2) {
 308            /* XXX: remote access (qualifier) error - what's that?  */
 309            break;
 310        }
 311        s->fifo <<= 16;
 312        s->txlen += 2;
 313        if (s->control & (1 << 14)) {                           /* BE */
 314            s->fifo |= ((value >> 8) & 0xff) << 8;
 315            s->fifo |= ((value >> 0) & 0xff) << 0;
 316        } else {
 317            s->fifo |= ((value >> 0) & 0xff) << 8;
 318            s->fifo |= ((value >> 8) & 0xff) << 0;
 319        }
 320        s->stat &= ~(1 << 10);                                  /* XUDF */
 321        if (s->txlen > 2)
 322            s->stat &= ~(1 << 4);                               /* XRDY */
 323        omap_i2c_fifo_run(s);
 324        omap_i2c_interrupts_update(s);
 325        break;
 326
 327    case 0x20:  /* I2C_SYSC */
 328        if (s->revision < OMAP2_INTR_REV) {
 329            OMAP_BAD_REG(addr);
 330            return;
 331        }
 332
 333        if (value & 2) {
 334            omap_i2c_reset(DEVICE(s));
 335        }
 336        break;
 337
 338    case 0x24:  /* I2C_CON */
 339        s->control = value & 0xcf87;
 340        if (~value & (1 << 15)) {                               /* I2C_EN */
 341            if (s->revision < OMAP2_INTR_REV) {
 342                omap_i2c_reset(DEVICE(s));
 343            }
 344            break;
 345        }
 346        if ((value & (1 << 15)) && !(value & (1 << 10))) {    /* MST */
 347            qemu_log_mask(LOG_UNIMP, "%s: I^2C slave mode not supported\n",
 348                          __func__);
 349            break;
 350        }
 351        if ((value & (1 << 15)) && value & (1 << 8)) {        /* XA */
 352            qemu_log_mask(LOG_UNIMP,
 353                          "%s: 10-bit addressing mode not supported\n",
 354                          __func__);
 355            break;
 356        }
 357        if ((value & (1 << 15)) && value & (1 << 0)) {          /* STT */
 358            nack = !!i2c_start_transfer(s->bus, s->addr[1],     /* SA */
 359                            (~value >> 9) & 1);                 /* TRX */
 360            s->stat |= nack << 1;                               /* NACK */
 361            s->control &= ~(1 << 0);                            /* STT */
 362            s->fifo = 0;
 363            if (nack)
 364                s->control &= ~(1 << 1);                        /* STP */
 365            else {
 366                s->count_cur = s->count;
 367                omap_i2c_fifo_run(s);
 368            }
 369            omap_i2c_interrupts_update(s);
 370        }
 371        break;
 372
 373    case 0x28:  /* I2C_OA */
 374        s->addr[0] = value & 0x3ff;
 375        break;
 376
 377    case 0x2c:  /* I2C_SA */
 378        s->addr[1] = value & 0x3ff;
 379        break;
 380
 381    case 0x30:  /* I2C_PSC */
 382        s->divider = value;
 383        break;
 384
 385    case 0x34:  /* I2C_SCLL */
 386        s->times[0] = value;
 387        break;
 388
 389    case 0x38:  /* I2C_SCLH */
 390        s->times[1] = value;
 391        break;
 392
 393    case 0x3c:  /* I2C_SYSTEST */
 394        s->test = value & 0xf80f;
 395        if (value & (1 << 11))                                  /* SBB */
 396            if (s->revision >= OMAP2_INTR_REV) {
 397                s->stat |= 0x3f;
 398                omap_i2c_interrupts_update(s);
 399            }
 400        if (value & (1 << 15)) {                    /* ST_EN */
 401            qemu_log_mask(LOG_UNIMP,
 402                          "%s: System Test not supported\n", __func__);
 403        }
 404        break;
 405
 406    default:
 407        OMAP_BAD_REG(addr);
 408        return;
 409    }
 410}
 411
 412static void omap_i2c_writeb(void *opaque, hwaddr addr,
 413                uint32_t value)
 414{
 415    OMAPI2CState *s = opaque;
 416    int offset = addr & OMAP_MPUI_REG_MASK;
 417
 418    switch (offset) {
 419    case 0x1c:  /* I2C_DATA */
 420        if (s->txlen > 2) {
 421            /* XXX: remote access (qualifier) error - what's that?  */
 422            break;
 423        }
 424        s->fifo <<= 8;
 425        s->txlen += 1;
 426        s->fifo |= value & 0xff;
 427        s->stat &= ~(1 << 10);                                  /* XUDF */
 428        if (s->txlen > 2)
 429            s->stat &= ~(1 << 4);                               /* XRDY */
 430        omap_i2c_fifo_run(s);
 431        omap_i2c_interrupts_update(s);
 432        break;
 433
 434    default:
 435        OMAP_BAD_REG(addr);
 436        return;
 437    }
 438}
 439
 440static uint64_t omap_i2c_readfn(void *opaque, hwaddr addr,
 441                                unsigned size)
 442{
 443    switch (size) {
 444    case 2:
 445        return omap_i2c_read(opaque, addr);
 446    default:
 447        return omap_badwidth_read16(opaque, addr);
 448    }
 449}
 450
 451static void omap_i2c_writefn(void *opaque, hwaddr addr,
 452                             uint64_t value, unsigned size)
 453{
 454    switch (size) {
 455    case 1:
 456        /* Only the last fifo write can be 8 bit. */
 457        omap_i2c_writeb(opaque, addr, value);
 458        break;
 459    case 2:
 460        omap_i2c_write(opaque, addr, value);
 461        break;
 462    default:
 463        omap_badwidth_write16(opaque, addr, value);
 464        break;
 465    }
 466}
 467
 468static const MemoryRegionOps omap_i2c_ops = {
 469    .read = omap_i2c_readfn,
 470    .write = omap_i2c_writefn,
 471    .valid.min_access_size = 1,
 472    .valid.max_access_size = 4,
 473    .endianness = DEVICE_NATIVE_ENDIAN,
 474};
 475
 476static void omap_i2c_init(Object *obj)
 477{
 478    DeviceState *dev = DEVICE(obj);
 479    OMAPI2CState *s = OMAP_I2C(obj);
 480    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 481
 482    sysbus_init_irq(sbd, &s->irq);
 483    sysbus_init_irq(sbd, &s->drq[0]);
 484    sysbus_init_irq(sbd, &s->drq[1]);
 485    sysbus_init_mmio(sbd, &s->iomem);
 486    s->bus = i2c_init_bus(dev, NULL);
 487}
 488
 489static void omap_i2c_realize(DeviceState *dev, Error **errp)
 490{
 491    OMAPI2CState *s = OMAP_I2C(dev);
 492
 493    memory_region_init_io(&s->iomem, OBJECT(dev), &omap_i2c_ops, s, "omap.i2c",
 494                          (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
 495
 496    if (!s->fclk) {
 497        error_setg(errp, "omap_i2c: fclk not connected");
 498        return;
 499    }
 500    if (s->revision >= OMAP2_INTR_REV && !s->iclk) {
 501        /* Note that OMAP1 doesn't have a separate interface clock */
 502        error_setg(errp, "omap_i2c: iclk not connected");
 503        return;
 504    }
 505}
 506
 507static Property omap_i2c_properties[] = {
 508    DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0),
 509    DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk),
 510    DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk),
 511    DEFINE_PROP_END_OF_LIST(),
 512};
 513
 514static void omap_i2c_class_init(ObjectClass *klass, void *data)
 515{
 516    DeviceClass *dc = DEVICE_CLASS(klass);
 517
 518    dc->props = omap_i2c_properties;
 519    dc->reset = omap_i2c_reset;
 520    /* Reason: pointer properties "iclk", "fclk" */
 521    dc->user_creatable = false;
 522    dc->realize = omap_i2c_realize;
 523}
 524
 525static const TypeInfo omap_i2c_info = {
 526    .name = TYPE_OMAP_I2C,
 527    .parent = TYPE_SYS_BUS_DEVICE,
 528    .instance_size = sizeof(OMAPI2CState),
 529    .instance_init = omap_i2c_init,
 530    .class_init = omap_i2c_class_init,
 531};
 532
 533static void omap_i2c_register_types(void)
 534{
 535    type_register_static(&omap_i2c_info);
 536}
 537
 538I2CBus *omap_i2c_bus(DeviceState *omap_i2c)
 539{
 540    OMAPI2CState *s = OMAP_I2C(omap_i2c);
 541    return s->bus;
 542}
 543
 544type_init(omap_i2c_register_types)
 545