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

mpc_i2c.c (9187B)


      1/*
      2 * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved.
      3 *
      4 * Author: Amit Tomar, <Amit.Tomar@freescale.com>
      5 *
      6 * Description:
      7 * This file is derived from IMX I2C controller,
      8 * by Jean-Christophe DUBOIS .
      9 *
     10 * Thanks to Scott Wood and Alexander Graf for their kind help on this.
     11 *
     12 * This program is free software; you can redistribute it and/or modify
     13 * it under the terms of the GNU General Public License, version 2 or later,
     14 * as published by the Free Software Foundation.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "hw/i2c/i2c.h"
     22#include "hw/irq.h"
     23#include "qemu/module.h"
     24#include "hw/sysbus.h"
     25#include "migration/vmstate.h"
     26#include "qom/object.h"
     27
     28/* #define DEBUG_I2C */
     29
     30#ifdef DEBUG_I2C
     31#define DPRINTF(fmt, ...)              \
     32    do { fprintf(stderr, "mpc_i2c[%s]: " fmt, __func__, ## __VA_ARGS__); \
     33    } while (0)
     34#else
     35#define DPRINTF(fmt, ...) do {} while (0)
     36#endif
     37
     38#define TYPE_MPC_I2C "mpc-i2c"
     39OBJECT_DECLARE_SIMPLE_TYPE(MPCI2CState, MPC_I2C)
     40
     41#define MPC_I2C_ADR   0x00
     42#define MPC_I2C_FDR   0x04
     43#define MPC_I2C_CR    0x08
     44#define MPC_I2C_SR    0x0c
     45#define MPC_I2C_DR    0x10
     46#define MPC_I2C_DFSRR 0x14
     47
     48#define CCR_MEN  (1 << 7)
     49#define CCR_MIEN (1 << 6)
     50#define CCR_MSTA (1 << 5)
     51#define CCR_MTX  (1 << 4)
     52#define CCR_TXAK (1 << 3)
     53#define CCR_RSTA (1 << 2)
     54#define CCR_BCST (1 << 0)
     55
     56#define CSR_MCF  (1 << 7)
     57#define CSR_MAAS (1 << 6)
     58#define CSR_MBB  (1 << 5)
     59#define CSR_MAL  (1 << 4)
     60#define CSR_SRW  (1 << 2)
     61#define CSR_MIF  (1 << 1)
     62#define CSR_RXAK (1 << 0)
     63
     64#define CADR_MASK 0xFE
     65#define CFDR_MASK 0x3F
     66#define CCR_MASK  0xFC
     67#define CSR_MASK  0xED
     68#define CDR_MASK  0xFF
     69
     70#define CYCLE_RESET 0xFF
     71
     72struct MPCI2CState {
     73    SysBusDevice parent_obj;
     74
     75    I2CBus *bus;
     76    qemu_irq irq;
     77    MemoryRegion iomem;
     78
     79    uint8_t address;
     80    uint8_t adr;
     81    uint8_t fdr;
     82    uint8_t cr;
     83    uint8_t sr;
     84    uint8_t dr;
     85    uint8_t dfssr;
     86};
     87
     88static bool mpc_i2c_is_enabled(MPCI2CState *s)
     89{
     90    return s->cr & CCR_MEN;
     91}
     92
     93static bool mpc_i2c_is_master(MPCI2CState *s)
     94{
     95    return s->cr & CCR_MSTA;
     96}
     97
     98static bool mpc_i2c_direction_is_tx(MPCI2CState *s)
     99{
    100    return s->cr & CCR_MTX;
    101}
    102
    103static bool mpc_i2c_irq_pending(MPCI2CState *s)
    104{
    105    return s->sr & CSR_MIF;
    106}
    107
    108static bool mpc_i2c_irq_is_enabled(MPCI2CState *s)
    109{
    110    return s->cr & CCR_MIEN;
    111}
    112
    113static void mpc_i2c_reset(DeviceState *dev)
    114{
    115    MPCI2CState *i2c = MPC_I2C(dev);
    116
    117    i2c->address = 0xFF;
    118    i2c->adr = 0x00;
    119    i2c->fdr = 0x00;
    120    i2c->cr =  0x00;
    121    i2c->sr =  0x81;
    122    i2c->dr =  0x00;
    123}
    124
    125static void mpc_i2c_irq(MPCI2CState *s)
    126{
    127    bool irq_active = false;
    128
    129    if (mpc_i2c_is_enabled(s) && mpc_i2c_irq_is_enabled(s)
    130                              && mpc_i2c_irq_pending(s)) {
    131        irq_active = true;
    132    }
    133
    134    if (irq_active) {
    135        qemu_irq_raise(s->irq);
    136    } else {
    137        qemu_irq_lower(s->irq);
    138    }
    139}
    140
    141static void mpc_i2c_soft_reset(MPCI2CState *s)
    142{
    143    /* This is a soft reset. ADR is preserved during soft resets */
    144    uint8_t adr = s->adr;
    145    mpc_i2c_reset(DEVICE(s));
    146    s->adr = adr;
    147}
    148
    149static void  mpc_i2c_address_send(MPCI2CState *s)
    150{
    151    /* if returns non zero slave address is not right */
    152    if (i2c_start_transfer(s->bus, s->dr >> 1, s->dr & (0x01))) {
    153        s->sr |= CSR_RXAK;
    154    } else {
    155        s->address = s->dr;
    156        s->sr &= ~CSR_RXAK;
    157        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
    158        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
    159        mpc_i2c_irq(s);
    160    }
    161}
    162
    163static void  mpc_i2c_data_send(MPCI2CState *s)
    164{
    165    if (i2c_send(s->bus, s->dr)) {
    166        /* End of transfer */
    167        s->sr |= CSR_RXAK;
    168        i2c_end_transfer(s->bus);
    169    } else {
    170        s->sr &= ~CSR_RXAK;
    171        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
    172        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
    173        mpc_i2c_irq(s);
    174    }
    175}
    176
    177static void  mpc_i2c_data_recive(MPCI2CState *s)
    178{
    179    int ret;
    180    /* get the next byte */
    181    ret = i2c_recv(s->bus);
    182    if (ret >= 0) {
    183        s->sr |= CSR_MCF; /* Set after Byte Transfer is completed */
    184        s->sr |= CSR_MIF; /* Set after Byte Transfer is completed */
    185        mpc_i2c_irq(s);
    186    } else {
    187        DPRINTF("read failed for device");
    188        ret = 0xff;
    189    }
    190    s->dr = ret;
    191}
    192
    193static uint64_t mpc_i2c_read(void *opaque, hwaddr addr, unsigned size)
    194{
    195    MPCI2CState *s = opaque;
    196    uint8_t value;
    197
    198    switch (addr) {
    199    case MPC_I2C_ADR:
    200        value = s->adr;
    201        break;
    202    case MPC_I2C_FDR:
    203        value = s->fdr;
    204        break;
    205    case MPC_I2C_CR:
    206        value = s->cr;
    207        break;
    208    case MPC_I2C_SR:
    209        value = s->sr;
    210        break;
    211    case MPC_I2C_DR:
    212        value = s->dr;
    213        if (mpc_i2c_is_master(s)) { /* master mode */
    214            if (mpc_i2c_direction_is_tx(s)) {
    215                DPRINTF("MTX is set not in recv mode\n");
    216            } else {
    217                mpc_i2c_data_recive(s);
    218            }
    219        }
    220        break;
    221    default:
    222        value = 0;
    223        DPRINTF("ERROR: Bad read addr 0x%x\n", (unsigned int)addr);
    224        break;
    225    }
    226
    227    DPRINTF("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__,
    228                                         addr, value);
    229    return (uint64_t)value;
    230}
    231
    232static void mpc_i2c_write(void *opaque, hwaddr addr,
    233                            uint64_t value, unsigned size)
    234{
    235    MPCI2CState *s = opaque;
    236
    237    DPRINTF("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", __func__,
    238                                             addr, value);
    239    switch (addr) {
    240    case MPC_I2C_ADR:
    241        s->adr = value & CADR_MASK;
    242        break;
    243    case MPC_I2C_FDR:
    244        s->fdr = value & CFDR_MASK;
    245        break;
    246    case MPC_I2C_CR:
    247        if (mpc_i2c_is_enabled(s) && ((value & CCR_MEN) == 0)) {
    248            mpc_i2c_soft_reset(s);
    249            break;
    250        }
    251        /* normal write */
    252        s->cr = value & CCR_MASK;
    253        if (mpc_i2c_is_master(s)) { /* master mode */
    254            /* set the bus to busy after master is set as per RM */
    255            s->sr |= CSR_MBB;
    256        } else {
    257            /* bus is not busy anymore */
    258            s->sr &= ~CSR_MBB;
    259            /* Reset the address for fresh write/read cycle */
    260        if (s->address != CYCLE_RESET) {
    261            i2c_end_transfer(s->bus);
    262            s->address = CYCLE_RESET;
    263            }
    264        }
    265        /* For restart end the onging transfer */
    266        if (s->cr & CCR_RSTA) {
    267            if (s->address != CYCLE_RESET) {
    268                s->address = CYCLE_RESET;
    269                i2c_end_transfer(s->bus);
    270                s->cr &= ~CCR_RSTA;
    271            }
    272        }
    273        break;
    274    case MPC_I2C_SR:
    275        s->sr = value & CSR_MASK;
    276        /* Lower the interrupt */
    277        if (!(s->sr & CSR_MIF) || !(s->sr & CSR_MAL)) {
    278            mpc_i2c_irq(s);
    279        }
    280        break;
    281    case MPC_I2C_DR:
    282        /* if the device is not enabled, nothing to do */
    283        if (!mpc_i2c_is_enabled(s)) {
    284            break;
    285        }
    286        s->dr = value & CDR_MASK;
    287        if (mpc_i2c_is_master(s)) { /* master mode */
    288            if (s->address == CYCLE_RESET) {
    289                mpc_i2c_address_send(s);
    290            } else {
    291                mpc_i2c_data_send(s);
    292            }
    293        }
    294        break;
    295    case MPC_I2C_DFSRR:
    296        s->dfssr = value;
    297        break;
    298    default:
    299        DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr);
    300        break;
    301    }
    302}
    303
    304static const MemoryRegionOps i2c_ops = {
    305    .read =  mpc_i2c_read,
    306    .write =  mpc_i2c_write,
    307    .valid.max_access_size = 1,
    308    .endianness = DEVICE_NATIVE_ENDIAN,
    309};
    310
    311static const VMStateDescription mpc_i2c_vmstate = {
    312    .name = TYPE_MPC_I2C,
    313    .version_id = 1,
    314    .minimum_version_id = 1,
    315    .fields = (VMStateField[]) {
    316        VMSTATE_UINT8(address, MPCI2CState),
    317        VMSTATE_UINT8(adr, MPCI2CState),
    318        VMSTATE_UINT8(fdr, MPCI2CState),
    319        VMSTATE_UINT8(cr, MPCI2CState),
    320        VMSTATE_UINT8(sr, MPCI2CState),
    321        VMSTATE_UINT8(dr, MPCI2CState),
    322        VMSTATE_UINT8(dfssr, MPCI2CState),
    323        VMSTATE_END_OF_LIST()
    324    }
    325};
    326
    327static void mpc_i2c_realize(DeviceState *dev, Error **errp)
    328{
    329    MPCI2CState  *i2c = MPC_I2C(dev);
    330    sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq);
    331    memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
    332                          "mpc-i2c", 0x14);
    333    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
    334    i2c->bus = i2c_init_bus(dev, "i2c");
    335}
    336
    337static void mpc_i2c_class_init(ObjectClass *klass, void *data)
    338{
    339    DeviceClass *dc = DEVICE_CLASS(klass);
    340
    341    dc->vmsd  = &mpc_i2c_vmstate ;
    342    dc->reset = mpc_i2c_reset;
    343    dc->realize = mpc_i2c_realize;
    344    dc->desc = "MPC I2C Controller";
    345}
    346
    347static const TypeInfo mpc_i2c_type_info = {
    348    .name          = TYPE_MPC_I2C,
    349    .parent        = TYPE_SYS_BUS_DEVICE,
    350    .instance_size = sizeof(MPCI2CState),
    351    .class_init    = mpc_i2c_class_init,
    352};
    353
    354static void mpc_i2c_register_types(void)
    355{
    356    type_register_static(&mpc_i2c_type_info);
    357}
    358
    359type_init(mpc_i2c_register_types)