qemu/hw/i2c/cadence_i2c.c
<<
>>
Prefs
   1/*
   2 *  Cadence I2C controller
   3 *
   4 *  Copyright (C) 2012 Xilinx Inc.
   5 *  Copyright (C) 2012 Peter Crosthwaite <peter.crosthwaite@xilinx.com>
   6 *
   7 *  This program is free software; you can redistribute it and/or modify it
   8 *  under the terms of the GNU General Public License as published by the
   9 *  Free Software Foundation; either version 2 of the License, or
  10 *  (at your option) any later version.
  11 *
  12 *  This program is distributed in the hope that it will be useful, but WITHOUT
  13 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  15 *  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 "qemu/bitops.h"
  23#include "qemu/timer.h"
  24#include "hw/sysbus.h"
  25#include "hw/irq.h"
  26#include "hw/i2c/i2c.h"
  27#include "qemu/fifo.h"
  28#include "qemu/log.h"
  29#include "migration/vmstate.h"
  30#include "hw/qdev-properties.h"
  31
  32#define TYPE_CADENCE_I2C                  "cdns.i2c-r1p10"
  33#define CADENCE_I2C(obj)                  \
  34    OBJECT_CHECK(CadenceI2CState, (obj), TYPE_CADENCE_I2C)
  35
  36/* Cadence I2C memory map */
  37#define R_CONTROL                            (0x00 / 4)
  38#define CONTROL_DIV_A_SHIFT                  14
  39#define CONTROL_DIV_A_WIDTH                  2
  40#define CONTROL_DIV_B_SHIFT                  8
  41#define CONTROL_DIV_B_WIDTH                  6
  42#define CONTROL_CLR_FIFO                     (1 << 6)
  43#define CONTROL_SLVMON                       (1 << 5)
  44#define CONTROL_HOLD                         (1 << 4)
  45#define CONTROL_ACKEN                        (1 << 3)
  46#define CONTROL_NEA                          (1 << 2)
  47#define CONTROL_MS                           (1 << 1)
  48#define CONTROL_RW                           (1 << 0)
  49#define R_STATUS                             (0x04 / 4)
  50#define STATUS_BA                            (1 << 8)
  51#define STATUS_RXOVF                         (1 << 7)
  52#define STATUS_TXDV                          (1 << 6)
  53#define STATUS_RXDV                          (1 << 5)
  54#define STATUS_RXRW                          (1 << 3)
  55#define R_ADDRESS                            (0x08 / 4)
  56#define R_DATA                               (0x0C / 4)
  57#define R_ISR                                (0x10 / 4)
  58#define ISR_RX_UNF                           (1 << 7)
  59#define ISR_TX_OVF                           (1 << 6)
  60#define ISR_RX_OVF                           (1 << 5)
  61#define ISR_SLV_RDY                          (1 << 4)
  62#define ISR_TO                               (1 << 3)
  63#define ISR_NACK                             (1 << 2)
  64#define ISR_DATA                             (1 << 1)
  65#define ISR_COMP                             (1 << 0)
  66#define R_TRANSFER_SIZE                      (0x14 / 4)
  67#define R_SLAVE_MON_PAUSE                    (0x18 / 4)
  68#define R_TIME_OUT                           (0x1c / 4)
  69#define R_INTRPT_MASK                        (0x20 / 4)
  70#define R_INTRPT_ENABLE                      (0x24 / 4)
  71#define R_INTRPT_DISABLE                     (0x28 / 4)
  72#define R_MAX                                (R_INTRPT_DISABLE + 1)
  73
  74/* Just approximate for the moment */
  75
  76#define NS_PER_PCLK 10ull
  77
  78/* FIXME: this struct defintion is generic, may belong in bitops or somewhere
  79 * like that
  80 */
  81
  82typedef struct CadenceI2CRegInfo {
  83    const char *name;
  84    uint32_t ro;
  85    uint32_t wtc;
  86    uint32_t reset;
  87    int width;
  88}  CadenceI2CRegInfo;
  89
  90static const CadenceI2CRegInfo cadence_i2c_reg_info[] = {
  91    [R_CONTROL]        = {.name = "CONTROL", .width = 16,
  92                          .ro = CONTROL_CLR_FIFO | (1 << 7) },
  93    [R_STATUS]         = {.name = "STATUS", .width = 9, .ro = ~0 },
  94    [R_ADDRESS]        = {.name = "ADDRESS", .width = 10 },
  95    [R_DATA]           = {.name = "DATA", .width = 8 },
  96    [R_ISR]            = {.name = "ISR", .width = 10, .wtc = 0x2FF,
  97                          .ro = 0x100 },
  98    [R_TRANSFER_SIZE]  = {.name = "TRANSFER_SIZE", .width = 8 },
  99    [R_SLAVE_MON_PAUSE] = {.name = "SLAVE_MON_PAUSE", .width = 8 },
 100    [R_TIME_OUT]        = {.name = "TIME_OUT", .width = 8},
 101    [R_INTRPT_MASK]    = {.name = "INTRPT_MASK", .width = 10, .ro = ~0,
 102                          .reset = 0x2FF },
 103    [R_INTRPT_ENABLE]  = {.name = "INTRPT_ENABLE", .width = 10, .wtc = ~0 },
 104    [R_INTRPT_DISABLE] = {.name = "INTRPT_DISABLE", .width = 10, .wtc = ~0 },
 105};
 106
 107#ifndef CADENCE_I2C_DEBUG
 108#define CADENCE_I2C_DEBUG 0
 109#endif
 110#define DB_PRINT(fmt, args...) do {\
 111    if (CADENCE_I2C_DEBUG) {\
 112        fprintf(stderr, "CADENCE_I2C: %s:" fmt, __func__, ## args);\
 113    } \
 114} while (0);
 115
 116#define FIFO_WIDTH 16
 117
 118typedef struct CadenceI2CState {
 119    SysBusDevice busdev;
 120    MemoryRegion iomem;
 121    I2CBus *bus;
 122    qemu_irq irq;
 123
 124    QEMUTimer *transfer_timer;
 125
 126    bool rw;
 127
 128    Fifo fifo;
 129    uint32_t regs[R_MAX];
 130} CadenceI2CState;
 131
 132static inline bool cadence_i2c_has_work(CadenceI2CState *s)
 133{
 134    if (!(s->regs[R_STATUS] & STATUS_BA)) {
 135        return false;
 136    }
 137
 138    if (!(s->regs[R_CONTROL] & CONTROL_RW)) { /* write */
 139        if (!(s->regs[R_CONTROL] & CONTROL_HOLD)) {
 140            return true;
 141        }
 142        return !fifo_is_empty(&s->fifo);
 143    } else {
 144        if ((s->regs[R_CONTROL] & CONTROL_HOLD)) {
 145            return !fifo_is_full(&s->fifo) && s->regs[R_TRANSFER_SIZE];
 146        }
 147        return true;
 148    }
 149}
 150
 151static void cadence_i2c_do_txrx(void *opaque);
 152
 153static inline void cadence_i2c_update_status(CadenceI2CState *s)
 154{
 155    if (cadence_i2c_has_work(s)) {
 156        uint64_t delay = NS_PER_PCLK;
 157        delay *= extract32(s->regs[R_CONTROL], CONTROL_DIV_A_SHIFT,
 158                           CONTROL_DIV_A_WIDTH) + 1;
 159        delay *= extract32(s->regs[R_CONTROL], CONTROL_DIV_B_SHIFT,
 160                           CONTROL_DIV_B_WIDTH) + 1;
 161        delay *= 10; /* 8 bits + ACK/NACK, approximate as 10 cycles/op */
 162        DB_PRINT("scheduling transfer operation with delay of %lldns\n",
 163                 (unsigned long long)delay);
 164        if (timer_pending(s->transfer_timer)) {
 165                timer_del(s->transfer_timer);
 166                cadence_i2c_do_txrx(s);
 167        }
 168        timer_mod(s->transfer_timer,
 169                  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + delay);
 170    }
 171
 172    DB_PRINT("irq state: %d\n", !!(s->regs[R_ISR] & ~s->regs[R_INTRPT_MASK]));
 173    qemu_set_irq(s->irq, !!(s->regs[R_ISR] & ~s->regs[R_INTRPT_MASK]));
 174}
 175
 176static void cadence_i2c_do_stop(CadenceI2CState *s)
 177{
 178        if (!(s->regs[R_CONTROL] & CONTROL_HOLD) &&
 179                (s->regs[R_STATUS] & STATUS_BA)) {
 180            DB_PRINT("sending stop condition\n");
 181            i2c_end_transfer(s->bus);
 182            s->regs[R_STATUS] &= ~STATUS_BA;
 183        }
 184}
 185
 186static void cadence_i2c_do_txrx(void *opaque)
 187{
 188    CadenceI2CState *s = opaque;
 189
 190    if (!!(s->regs[R_CONTROL] & CONTROL_RW) != s->rw) {
 191        return;
 192    }
 193
 194    DB_PRINT("doing transfer at time %llx\n",
 195             (unsigned long long)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
 196    if (!(s->regs[R_CONTROL] & CONTROL_RW)) { /* write */
 197        if (fifo_is_empty(&s->fifo)) {
 198            cadence_i2c_do_stop(s);
 199        } else {
 200            uint8_t t = fifo_pop8(&s->fifo);
 201            if (i2c_send(s->bus, t)) {
 202                s->regs[R_ISR] |= ISR_NACK;
 203            }
 204            if (fifo_is_empty(&s->fifo)) {
 205                s->regs[R_ISR] |= ISR_COMP;
 206            }
 207            if (s->regs[R_TRANSFER_SIZE]) {
 208                s->regs[R_TRANSFER_SIZE]--;
 209            }
 210            if (s->fifo.num <= 2) {
 211                s->regs[R_ISR] |= ISR_DATA;
 212            }
 213        }
 214    } else { /* read */
 215        /* noting to transfer? - stop */
 216        if (!s->regs[R_TRANSFER_SIZE]) {
 217            cadence_i2c_do_stop(s);
 218            DB_PRINT("stopping read transfer\n");
 219        /* fifo full without hold - overflow */
 220        } else if (fifo_is_full(&s->fifo) &&
 221                   !(s->regs[R_CONTROL] & CONTROL_HOLD)) {
 222            i2c_recv(s->bus);
 223            s->regs[R_ISR] |= ISR_RX_OVF;
 224            s->regs[R_STATUS] |= STATUS_RXOVF;
 225            DB_PRINT("nacking becuase the fifo is full!\n");
 226            i2c_nack(s->bus);
 227            cadence_i2c_do_stop(s);
 228        /* fifo not full - do a byte sucessfully */
 229        } else if (!fifo_is_full(&s->fifo)) {
 230            uint8_t r = i2c_recv(s->bus);
 231            DB_PRINT("receiving from I2C bus: %02x\n", r);
 232            fifo_push8(&s->fifo, r);
 233            s->regs[R_STATUS] |= STATUS_RXDV;
 234            if (s->fifo.num >= FIFO_WIDTH - 2) {
 235                s->regs[R_ISR] |= ISR_DATA;
 236            }
 237            if (!(s->regs[R_CONTROL] & CONTROL_ACKEN)) {
 238                i2c_nack(s->bus);
 239            }
 240            s->regs[R_TRANSFER_SIZE]--;
 241            if (!s->regs[R_TRANSFER_SIZE]) {
 242                DB_PRINT("Nacking last byte of read transaction\n");
 243                i2c_nack(s->bus);
 244                s->regs[R_ISR] |= ISR_COMP;
 245                if (s->regs[R_CONTROL] & CONTROL_HOLD) {
 246                    i2c_end_transfer(s->bus);
 247                }
 248            }
 249        }
 250        /* fallthrough with no action if fifo full with HOLD==1 */
 251    }
 252
 253    cadence_i2c_update_status(s);
 254}
 255
 256static inline void cadence_i2c_check_reg_access(hwaddr offset, uint32_t val,
 257                                                bool rnw)
 258{
 259    if (!cadence_i2c_reg_info[offset >> 2].name) {
 260        qemu_log_mask(LOG_UNIMP, "cadence i2c: %s offset %x\n",
 261                      rnw ? "read from" : "write to", (unsigned)offset);
 262        DB_PRINT("%s offset %x\n",
 263                      rnw ? "read from" : "write to", (unsigned)offset);
 264    } else {
 265        DB_PRINT("%s %s [%#02x] %s %#08x\n", rnw ? "read" : "write",
 266                 cadence_i2c_reg_info[offset >> 2].name, (unsigned) offset,
 267                 rnw ? "->" : "<-", val);
 268    }
 269}
 270
 271static uint64_t cadence_i2c_read(void *opaque, hwaddr offset,
 272                                 unsigned size)
 273{
 274    CadenceI2CState *s = (CadenceI2CState *)opaque;
 275    const CadenceI2CRegInfo *info = &cadence_i2c_reg_info[offset >> 2];
 276    uint32_t ret = s->regs[offset >> 2];
 277
 278    cadence_i2c_check_reg_access(offset, ret, true);
 279    if (!info->name) {
 280        return 0;
 281    }
 282    ret &= (1ull << info->width) - 1;
 283
 284    if (offset >> 2 == R_DATA) {
 285        if (fifo_is_empty(&s->fifo)) {
 286            s->regs[R_ISR] |= ISR_RX_UNF;
 287        } else {
 288            s->regs[R_STATUS] &= ~STATUS_RXOVF;
 289            ret = fifo_pop8(&s->fifo);
 290            if (fifo_is_empty(&s->fifo)) {
 291                s->regs[R_STATUS] &= ~STATUS_RXDV;
 292            }
 293        }
 294        cadence_i2c_update_status(s);
 295    }
 296    return ret;
 297}
 298
 299static void cadence_i2c_write(void *opaque, hwaddr offset,
 300                              uint64_t value, unsigned size)
 301{
 302    CadenceI2CState *s = (CadenceI2CState *)opaque;
 303    const CadenceI2CRegInfo *info = &cadence_i2c_reg_info[offset >> 2];
 304    uint32_t new_value = value;
 305    uint32_t ro_mask;
 306
 307    cadence_i2c_check_reg_access(offset, value, false);
 308    if (!info->name) {
 309        return;
 310    }
 311    offset >>= 2;
 312    assert(!(info->wtc & info->ro));
 313    /* preserve read-only and write to clear bits */
 314    ro_mask = info->ro | info->wtc | ~((1ull << info->width) - 1);
 315    new_value &= ~ro_mask;
 316    new_value |= ro_mask & s->regs[offset];
 317    /* do write to clear */
 318    new_value &= ~(value & info->wtc);
 319    s->regs[offset] = new_value;
 320
 321    switch (offset) {
 322    case R_CONTROL:
 323        if (value & CONTROL_CLR_FIFO) {
 324            DB_PRINT("clearing fifo\n");
 325            s->regs[R_TRANSFER_SIZE] = 0;
 326            s->regs[R_STATUS] &= ~STATUS_RXOVF;
 327            fifo_reset(&s->fifo);
 328        }
 329        if (!(value & CONTROL_HOLD)) {
 330            bool idle = s->regs[R_CONTROL] & CONTROL_RW ?
 331                        !s->regs[R_TRANSFER_SIZE] : fifo_is_empty(&s->fifo);
 332            if (idle) {
 333                cadence_i2c_do_stop(s);
 334            }
 335        }
 336        break;
 337    case R_ADDRESS:
 338        s->rw = s->regs[R_CONTROL] & CONTROL_RW;
 339        if (!(s->regs[R_CONTROL] & CONTROL_NEA)) {
 340            qemu_log_mask(LOG_UNIMP, "cadence i2c: 10 bit addressing selected "
 341                          "(unimplmented)");
 342        }
 343        if (i2c_start_transfer(s->bus, new_value & 0x7f,
 344                               s->regs[R_CONTROL] & CONTROL_RW)) {
 345            const char *path = object_get_canonical_path_component(OBJECT(s));
 346
 347            i2c_end_transfer(s->bus);
 348            qemu_log_mask(LOG_GUEST_ERROR,
 349                          "%s: No match for device 0x%x\n", path, new_value);
 350            s->regs[R_ISR] |= ISR_NACK;
 351        } else {
 352            DB_PRINT("device 0x%x probe success\n", new_value);
 353            if (s->regs[R_CONTROL] & CONTROL_SLVMON) {
 354                /* Set "device found" in slave monitor mode */
 355                s->regs[R_ISR] |= ISR_SLV_RDY;
 356            } else {
 357                if (fifo_is_empty(&s->fifo) &&
 358                    !(s->regs[R_CONTROL] & CONTROL_RW)) {
 359                    s->regs[R_ISR] |= ISR_COMP;
 360                }
 361                s->regs[R_STATUS] |= STATUS_BA;
 362            }
 363        }
 364        break;
 365    case R_DATA:
 366        if (fifo_is_full(&s->fifo)) {
 367            s->regs[R_ISR] |= ISR_TX_OVF;
 368        } else {
 369            s->regs[R_TRANSFER_SIZE]++;
 370            fifo_push8(&s->fifo, new_value);
 371        }
 372        break;
 373    case R_INTRPT_ENABLE:
 374        s->regs[R_INTRPT_MASK] &= ~value;
 375        break;
 376    case R_INTRPT_DISABLE:
 377        s->regs[R_INTRPT_MASK] |= value;
 378        break;
 379    }
 380    cadence_i2c_update_status(s);
 381}
 382
 383static const MemoryRegionOps cadence_i2c_ops = {
 384    .read = cadence_i2c_read,
 385    .write = cadence_i2c_write,
 386    .endianness = DEVICE_NATIVE_ENDIAN,
 387};
 388
 389static const VMStateDescription cadence_i2c_vmstate = {
 390    .name = TYPE_CADENCE_I2C,
 391    .version_id = 1,
 392    .minimum_version_id = 1,
 393    .fields = (VMStateField[]) {
 394        VMSTATE_FIFO(fifo, CadenceI2CState),
 395        VMSTATE_UINT32_ARRAY(regs, CadenceI2CState, R_MAX),
 396        VMSTATE_TIMER_PTR(transfer_timer, CadenceI2CState),
 397        VMSTATE_END_OF_LIST()
 398    }
 399};
 400
 401static void cadence_i2c_reset(DeviceState *d)
 402{
 403    CadenceI2CState *s = CADENCE_I2C(d);
 404    int i;
 405
 406    timer_del(s->transfer_timer);
 407    for (i = 0; i < R_MAX; ++i) {
 408        s->regs[i] = cadence_i2c_reg_info[i].name ?
 409                cadence_i2c_reg_info[i].reset : 0;
 410    }
 411    fifo_reset(&s->fifo);
 412}
 413
 414static void cadence_i2c_realize(DeviceState *dev, Error **errp)
 415{
 416    CadenceI2CState *s = CADENCE_I2C(dev);
 417    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 418
 419    memory_region_init_io(&s->iomem, OBJECT(dev), &cadence_i2c_ops, s,
 420                          TYPE_CADENCE_I2C, R_MAX * 4);
 421    sysbus_init_mmio(sbd, &s->iomem);
 422    sysbus_init_irq(sbd, &s->irq);
 423
 424    s->bus = i2c_init_bus(dev, "i2c");
 425
 426    s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_i2c_do_txrx,
 427                                     s);
 428
 429    fifo_create8(&s->fifo, FIFO_WIDTH);
 430}
 431
 432static void cadence_i2c_class_init(ObjectClass *klass, void *data)
 433{
 434    DeviceClass *dc = DEVICE_CLASS(klass);
 435
 436    dc->vmsd = &cadence_i2c_vmstate;
 437    dc->reset = cadence_i2c_reset;
 438    dc->realize = cadence_i2c_realize;
 439}
 440
 441static const TypeInfo cadence_i2c_type_info = {
 442    .name = TYPE_CADENCE_I2C,
 443    .parent = TYPE_SYS_BUS_DEVICE,
 444    .instance_size = sizeof(CadenceI2CState),
 445    .class_init = cadence_i2c_class_init,
 446};
 447
 448static void cadence_i2c_register_types(void)
 449{
 450    type_register_static(&cadence_i2c_type_info);
 451}
 452
 453type_init(cadence_i2c_register_types)
 454