cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

ppc4xx_i2c.c (11407B)


      1/*
      2 * PPC4xx I2C controller emulation
      3 *
      4 * Documentation: PPC405GP User's Manual, Chapter 22. IIC Bus Interface
      5 *
      6 * Copyright (c) 2007 Jocelyn Mayer
      7 * Copyright (c) 2012 François Revol
      8 * Copyright (c) 2016-2018 BALATON Zoltan
      9 *
     10 * Permission is hereby granted, free of charge, to any person obtaining a copy
     11 * of this software and associated documentation files (the "Software"), to deal
     12 * in the Software without restriction, including without limitation the rights
     13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     14 * copies of the Software, and to permit persons to whom the Software is
     15 * furnished to do so, subject to the following conditions:
     16 *
     17 * The above copyright notice and this permission notice shall be included in
     18 * all copies or substantial portions of the Software.
     19 *
     20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     26 * THE SOFTWARE.
     27 */
     28
     29#include "qemu/osdep.h"
     30#include "qemu/log.h"
     31#include "qemu/module.h"
     32#include "hw/i2c/ppc4xx_i2c.h"
     33#include "hw/irq.h"
     34
     35#define PPC4xx_I2C_MEM_SIZE 18
     36
     37enum {
     38    IIC_MDBUF = 0,
     39    /* IIC_SDBUF = 2, */
     40    IIC_LMADR = 4,
     41    IIC_HMADR,
     42    IIC_CNTL,
     43    IIC_MDCNTL,
     44    IIC_STS,
     45    IIC_EXTSTS,
     46    IIC_LSADR,
     47    IIC_HSADR,
     48    IIC_CLKDIV,
     49    IIC_INTRMSK,
     50    IIC_XFRCNT,
     51    IIC_XTCNTLSS,
     52    IIC_DIRECTCNTL
     53    /* IIC_INTR */
     54};
     55
     56#define IIC_CNTL_PT         (1 << 0)
     57#define IIC_CNTL_READ       (1 << 1)
     58#define IIC_CNTL_CHT        (1 << 2)
     59#define IIC_CNTL_RPST       (1 << 3)
     60#define IIC_CNTL_AMD        (1 << 6)
     61#define IIC_CNTL_HMT        (1 << 7)
     62
     63#define IIC_MDCNTL_EINT     (1 << 2)
     64#define IIC_MDCNTL_ESM      (1 << 3)
     65#define IIC_MDCNTL_FMDB     (1 << 6)
     66
     67#define IIC_STS_PT          (1 << 0)
     68#define IIC_STS_IRQA        (1 << 1)
     69#define IIC_STS_ERR         (1 << 2)
     70#define IIC_STS_MDBF        (1 << 4)
     71#define IIC_STS_MDBS        (1 << 5)
     72
     73#define IIC_EXTSTS_XFRA     (1 << 0)
     74#define IIC_EXTSTS_BCS_FREE (4 << 4)
     75#define IIC_EXTSTS_BCS_BUSY (5 << 4)
     76
     77#define IIC_INTRMSK_EIMTC   (1 << 0)
     78#define IIC_INTRMSK_EITA    (1 << 1)
     79#define IIC_INTRMSK_EIIC    (1 << 2)
     80#define IIC_INTRMSK_EIHE    (1 << 3)
     81
     82#define IIC_XTCNTLSS_SRST   (1 << 0)
     83
     84#define IIC_DIRECTCNTL_SDAC (1 << 3)
     85#define IIC_DIRECTCNTL_SCLC (1 << 2)
     86#define IIC_DIRECTCNTL_MSDA (1 << 1)
     87#define IIC_DIRECTCNTL_MSCL (1 << 0)
     88
     89static void ppc4xx_i2c_reset(DeviceState *s)
     90{
     91    PPC4xxI2CState *i2c = PPC4xx_I2C(s);
     92
     93    i2c->mdidx = -1;
     94    memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata));
     95    /* [hl][ms]addr are not affected by reset */
     96    i2c->cntl = 0;
     97    i2c->mdcntl = 0;
     98    i2c->sts = 0;
     99    i2c->extsts = IIC_EXTSTS_BCS_FREE;
    100    i2c->clkdiv = 0;
    101    i2c->intrmsk = 0;
    102    i2c->xfrcnt = 0;
    103    i2c->xtcntlss = 0;
    104    i2c->directcntl = 0xf; /* all non-reserved bits set */
    105}
    106
    107static uint64_t ppc4xx_i2c_readb(void *opaque, hwaddr addr, unsigned int size)
    108{
    109    PPC4xxI2CState *i2c = PPC4xx_I2C(opaque);
    110    uint64_t ret;
    111    int i;
    112
    113    switch (addr) {
    114    case IIC_MDBUF:
    115        if (i2c->mdidx < 0) {
    116            ret = 0xff;
    117            break;
    118        }
    119        ret = i2c->mdata[0];
    120        if (i2c->mdidx == 3) {
    121            i2c->sts &= ~IIC_STS_MDBF;
    122        } else if (i2c->mdidx == 0) {
    123            i2c->sts &= ~IIC_STS_MDBS;
    124        }
    125        for (i = 0; i < i2c->mdidx; i++) {
    126            i2c->mdata[i] = i2c->mdata[i + 1];
    127        }
    128        if (i2c->mdidx >= 0) {
    129            i2c->mdidx--;
    130        }
    131        break;
    132    case IIC_LMADR:
    133        ret = i2c->lmadr;
    134        break;
    135    case IIC_HMADR:
    136        ret = i2c->hmadr;
    137        break;
    138    case IIC_CNTL:
    139        ret = i2c->cntl;
    140        break;
    141    case IIC_MDCNTL:
    142        ret = i2c->mdcntl;
    143        break;
    144    case IIC_STS:
    145        ret = i2c->sts;
    146        break;
    147    case IIC_EXTSTS:
    148        ret = i2c_bus_busy(i2c->bus) ?
    149              IIC_EXTSTS_BCS_BUSY : IIC_EXTSTS_BCS_FREE;
    150        break;
    151    case IIC_LSADR:
    152        ret = i2c->lsadr;
    153        break;
    154    case IIC_HSADR:
    155        ret = i2c->hsadr;
    156        break;
    157    case IIC_CLKDIV:
    158        ret = i2c->clkdiv;
    159        break;
    160    case IIC_INTRMSK:
    161        ret = i2c->intrmsk;
    162        break;
    163    case IIC_XFRCNT:
    164        ret = i2c->xfrcnt;
    165        break;
    166    case IIC_XTCNTLSS:
    167        ret = i2c->xtcntlss;
    168        break;
    169    case IIC_DIRECTCNTL:
    170        ret = i2c->directcntl;
    171        break;
    172    default:
    173        if (addr < PPC4xx_I2C_MEM_SIZE) {
    174            qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%"
    175                          HWADDR_PRIx "\n", __func__, addr);
    176        } else {
    177            qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%"
    178                          HWADDR_PRIx "\n", __func__, addr);
    179        }
    180        ret = 0;
    181        break;
    182    }
    183    return ret;
    184}
    185
    186static void ppc4xx_i2c_writeb(void *opaque, hwaddr addr, uint64_t value,
    187                              unsigned int size)
    188{
    189    PPC4xxI2CState *i2c = opaque;
    190
    191    switch (addr) {
    192    case IIC_MDBUF:
    193        if (i2c->mdidx >= 3) {
    194            break;
    195        }
    196        i2c->mdata[++i2c->mdidx] = value;
    197        if (i2c->mdidx == 3) {
    198            i2c->sts |= IIC_STS_MDBF;
    199        } else if (i2c->mdidx == 0) {
    200            i2c->sts |= IIC_STS_MDBS;
    201        }
    202        break;
    203    case IIC_LMADR:
    204        i2c->lmadr = value;
    205        break;
    206    case IIC_HMADR:
    207        i2c->hmadr = value;
    208        break;
    209    case IIC_CNTL:
    210        i2c->cntl = value & ~IIC_CNTL_PT;
    211        if (value & IIC_CNTL_AMD) {
    212            qemu_log_mask(LOG_UNIMP, "%s: only 7 bit addresses supported\n",
    213                          __func__);
    214        }
    215        if (value & IIC_CNTL_HMT && i2c_bus_busy(i2c->bus)) {
    216            i2c_end_transfer(i2c->bus);
    217            if (i2c->mdcntl & IIC_MDCNTL_EINT &&
    218                i2c->intrmsk & IIC_INTRMSK_EIHE) {
    219                i2c->sts |= IIC_STS_IRQA;
    220                qemu_irq_raise(i2c->irq);
    221            }
    222        } else if (value & IIC_CNTL_PT) {
    223            int recv = (value & IIC_CNTL_READ) >> 1;
    224            int tct = value >> 4 & 3;
    225            int i;
    226
    227            if (recv && (i2c->lmadr >> 1) >= 0x50 && (i2c->lmadr >> 1) < 0x58) {
    228                /* smbus emulation does not like multi byte reads w/o restart */
    229                value |= IIC_CNTL_RPST;
    230            }
    231
    232            for (i = 0; i <= tct; i++) {
    233                if (!i2c_bus_busy(i2c->bus)) {
    234                    i2c->extsts = IIC_EXTSTS_BCS_FREE;
    235                    if (i2c_start_transfer(i2c->bus, i2c->lmadr >> 1, recv)) {
    236                        i2c->sts |= IIC_STS_ERR;
    237                        i2c->extsts |= IIC_EXTSTS_XFRA;
    238                        break;
    239                    } else {
    240                        i2c->sts &= ~IIC_STS_ERR;
    241                    }
    242                }
    243                if (!(i2c->sts & IIC_STS_ERR)) {
    244                    if (recv) {
    245                        i2c->mdata[i] = i2c_recv(i2c->bus);
    246                    } else if (i2c_send(i2c->bus, i2c->mdata[i]) < 0) {
    247                        i2c->sts |= IIC_STS_ERR;
    248                        i2c->extsts |= IIC_EXTSTS_XFRA;
    249                        break;
    250                    }
    251                }
    252                if (value & IIC_CNTL_RPST || !(value & IIC_CNTL_CHT)) {
    253                    i2c_end_transfer(i2c->bus);
    254                }
    255            }
    256            i2c->xfrcnt = i;
    257            i2c->mdidx = i - 1;
    258            if (recv && i2c->mdidx >= 0) {
    259                i2c->sts |= IIC_STS_MDBS;
    260            }
    261            if (recv && i2c->mdidx == 3) {
    262                i2c->sts |= IIC_STS_MDBF;
    263            }
    264            if (i && i2c->mdcntl & IIC_MDCNTL_EINT &&
    265                i2c->intrmsk & IIC_INTRMSK_EIMTC) {
    266                i2c->sts |= IIC_STS_IRQA;
    267                qemu_irq_raise(i2c->irq);
    268            }
    269        }
    270        break;
    271    case IIC_MDCNTL:
    272        i2c->mdcntl = value & 0x3d;
    273        if (value & IIC_MDCNTL_ESM) {
    274            qemu_log_mask(LOG_UNIMP, "%s: slave mode not implemented\n",
    275                          __func__);
    276        }
    277        if (value & IIC_MDCNTL_FMDB) {
    278            i2c->mdidx = -1;
    279            memset(i2c->mdata, 0, ARRAY_SIZE(i2c->mdata));
    280            i2c->sts &= ~(IIC_STS_MDBF | IIC_STS_MDBS);
    281        }
    282        break;
    283    case IIC_STS:
    284        i2c->sts &= ~(value & 0x0a);
    285        if (value & IIC_STS_IRQA && i2c->mdcntl & IIC_MDCNTL_EINT) {
    286            qemu_irq_lower(i2c->irq);
    287        }
    288        break;
    289    case IIC_EXTSTS:
    290        i2c->extsts &= ~(value & 0x8f);
    291        break;
    292    case IIC_LSADR:
    293        i2c->lsadr = value;
    294        break;
    295    case IIC_HSADR:
    296        i2c->hsadr = value;
    297        break;
    298    case IIC_CLKDIV:
    299        i2c->clkdiv = value;
    300        break;
    301    case IIC_INTRMSK:
    302        i2c->intrmsk = value;
    303        break;
    304    case IIC_XFRCNT:
    305        i2c->xfrcnt = value & 0x77;
    306        break;
    307    case IIC_XTCNTLSS:
    308        i2c->xtcntlss &= ~(value & 0xf0);
    309        if (value & IIC_XTCNTLSS_SRST) {
    310            /* Is it actually a full reset? U-Boot sets some regs before */
    311            ppc4xx_i2c_reset(DEVICE(i2c));
    312            break;
    313        }
    314        break;
    315    case IIC_DIRECTCNTL:
    316        i2c->directcntl = value & (IIC_DIRECTCNTL_SDAC & IIC_DIRECTCNTL_SCLC);
    317        i2c->directcntl |= (value & IIC_DIRECTCNTL_SCLC ? 1 : 0);
    318        bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SCL,
    319                        i2c->directcntl & IIC_DIRECTCNTL_MSCL);
    320        i2c->directcntl |= bitbang_i2c_set(&i2c->bitbang, BITBANG_I2C_SDA,
    321                               (value & IIC_DIRECTCNTL_SDAC) != 0) << 1;
    322        break;
    323    default:
    324        if (addr < PPC4xx_I2C_MEM_SIZE) {
    325            qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register 0x%"
    326                          HWADDR_PRIx "\n", __func__, addr);
    327        } else {
    328            qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%"
    329                          HWADDR_PRIx "\n", __func__, addr);
    330        }
    331        break;
    332    }
    333}
    334
    335static const MemoryRegionOps ppc4xx_i2c_ops = {
    336    .read = ppc4xx_i2c_readb,
    337    .write = ppc4xx_i2c_writeb,
    338    .valid.min_access_size = 1,
    339    .valid.max_access_size = 4,
    340    .impl.min_access_size = 1,
    341    .impl.max_access_size = 1,
    342    .endianness = DEVICE_NATIVE_ENDIAN,
    343};
    344
    345static void ppc4xx_i2c_init(Object *o)
    346{
    347    PPC4xxI2CState *s = PPC4xx_I2C(o);
    348
    349    memory_region_init_io(&s->iomem, OBJECT(s), &ppc4xx_i2c_ops, s,
    350                          TYPE_PPC4xx_I2C, PPC4xx_I2C_MEM_SIZE);
    351    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
    352    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
    353    s->bus = i2c_init_bus(DEVICE(s), "i2c");
    354    bitbang_i2c_init(&s->bitbang, s->bus);
    355}
    356
    357static void ppc4xx_i2c_class_init(ObjectClass *klass, void *data)
    358{
    359    DeviceClass *dc = DEVICE_CLASS(klass);
    360
    361    dc->reset = ppc4xx_i2c_reset;
    362}
    363
    364static const TypeInfo ppc4xx_i2c_type_info = {
    365    .name = TYPE_PPC4xx_I2C,
    366    .parent = TYPE_SYS_BUS_DEVICE,
    367    .instance_size = sizeof(PPC4xxI2CState),
    368    .instance_init = ppc4xx_i2c_init,
    369    .class_init = ppc4xx_i2c_class_init,
    370};
    371
    372static void ppc4xx_i2c_register_types(void)
    373{
    374    type_register_static(&ppc4xx_i2c_type_info);
    375}
    376
    377type_init(ppc4xx_i2c_register_types)