qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

omap_i2c.c (15005B)


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