/*
 * Copyright (c) 2012 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Peter Enns
 */

#include "dev/i2c/bus.hh"

#include "debug/Checkpoint.hh"
#include "dev/i2c/device.hh"
#include "mem/packet_access.hh"

// clang complains about std::set being overloaded with Packet::set if
// we open up the entire namespace std
using std::vector;
using std::map;

/**
 * 4KB - see e.g.
 * http://infocenter.arm.com/help/topic/com.arm.doc.dui0440b/Bbajihec.html
 */
I2CBus::I2CBus(const I2CBusParams *p)
    : BasicPioDevice(p, 0x1000), scl(1), sda(1), state(IDLE), currBit(7),
      i2cAddr(0x00), message(0x00)
{
    vector<I2CDevice*> devs = p->devices;

    for (auto d : p->devices) {
        devices[d->i2cAddr()] = d;
    }
}

/**
 * Reads will always be to SB_CONTROLS. The kernel wants to know the state
 * of sda and scl.
 */
Tick
I2CBus::read(PacketPtr pkt)
{
    assert(pkt->getAddr() == pioAddr + SB_CONTROLS);

    pkt->setRaw<uint8_t>((sda << 1) | scl);
    pkt->makeAtomicResponse();
    return pioDelay;
}

/**
 * The default i2c bus driver used by the realview pbx board writes to
 * this device one bit at a time. To facilitate making new i2c devices,
 * i2cBus::write takes care of the low-level details of the i2c protocol.
 * See the I2C Specification [1] for a detailed description of the
 * protocol.
 *
 * [1] - http://www.nxp.com/documents/user_manual/UM10204.pdf
 */
Tick
I2CBus::write(PacketPtr pkt)
{
    assert(pkt->getAddr() == pioAddr + SB_CONTROLS ||
           pkt->getAddr() == pioAddr + SB_CONTROLC);

    updateSignals(pkt);

    // Check if the bus master is starting a new transmission.
    if (isStart(pkt)) {
        state = RECEIVING_ADDR;
        message = 0x00;
        currBit = 7;
        /* Most i2c devices expect something special (e.g., command,
         * register address) in the first byte they receive so they
         * must be notified somehow that this is a new transmission.
         */
        for (auto& d : devices) {
            d.second->i2cStart();
        }
        return pioDelay;
    }

    // Check if the bus master is ending a transmission.
    if (isEnd(pkt)) {
        state = IDLE;
        return pioDelay;
    }

    // Only change state when the clock is transitioning from low to high.
    // This may not perfectly mimic physical i2c devices but the important
    // part is to only do the following once per clock cycle.
    if (isClockSet(pkt)) {
        switch (state) {
          case RECEIVING_ADDR:
            if (currBit >= 0) {
                message |= sda << currBit;
                currBit--;
            } else {
                i2cAddr = message >> 1;
                assert(devices.find(i2cAddr) != devices.end());
                if (message & 0x01) {
                    state = SENDING_DATA;
                    message = devices[i2cAddr]->read();
                } else {
                    state = RECEIVING_DATA;
                    message = 0x00;
                }
                currBit = 7;
                sda = 0; /* Ack */
            }
            break;
          case RECEIVING_DATA:
            if (currBit >= 0) {
                message |= sda << currBit;
                currBit--;
            } else {
                devices[i2cAddr]->write(message);
                message = 0x00;
                currBit = 7;
                sda = 0; /* Ack */
            }
            break;
          case SENDING_DATA:
            if (currBit >= 0) {
                sda = (message >> currBit) & 0x01;
                currBit--;
            } else {
                if (!sda) /* Check for ack from the bus master. */
                    message = devices[i2cAddr]->read();
                currBit = 7;
            }
            break;
          case IDLE:
          default:
            panic("Invalid state on posedge of clock in I2CBus::write.\n");
            break;
        }
    }

    return pioDelay;
}

void
I2CBus::updateSignals(PacketPtr pkt)
{
    uint8_t msg = pkt->getRaw<uint8_t>();
    Addr daddr = pkt->getAddr() - pioAddr;

    switch (daddr) {
      case SB_CONTROLS:
        scl = (msg & 1) ? 1 : scl;
        sda = (msg & 2) ? 1 : sda;
        break;
      case SB_CONTROLC:
        scl = (msg & 1) ? 0 : scl;
        sda = (msg & 2) ? 0 : sda;
        break;
      default:
        break;
    }
}

bool
I2CBus::isClockSet(PacketPtr pkt) const
{
    uint8_t msg = pkt->getRaw<uint8_t>();
    Addr daddr = pkt->getAddr() - pioAddr;
    return daddr == SB_CONTROLS && (msg & 1);
}

bool
I2CBus::isStart(PacketPtr pkt) const
{
    uint8_t msg = pkt->getRaw<uint8_t>();
    Addr daddr = pkt->getAddr() - pioAddr;
    return scl && (msg & 2) && daddr == SB_CONTROLC;
}

bool
I2CBus::isEnd(PacketPtr pkt) const
{
    uint8_t msg = pkt->getRaw<uint8_t>();
    Addr daddr = pkt->getAddr() - pioAddr;
    return scl && (msg & 2) && daddr == SB_CONTROLS;
}
void
I2CBus::serialize(CheckpointOut &cp) const
{
    DPRINTF(Checkpoint, "Serializing I2C bus.\n");
    SERIALIZE_SCALAR(scl);
    SERIALIZE_SCALAR(sda);
    SERIALIZE_ENUM(state);
    SERIALIZE_SCALAR(currBit);
    SERIALIZE_SCALAR(i2cAddr);
    SERIALIZE_SCALAR(message);
}

void
I2CBus::unserialize(CheckpointIn &cp)
{
    DPRINTF(Checkpoint, "Unserializing I2C bus.\n");
    UNSERIALIZE_SCALAR(scl);
    UNSERIALIZE_SCALAR(sda);
    UNSERIALIZE_ENUM(state);
    UNSERIALIZE_SCALAR(currBit);
    UNSERIALIZE_SCALAR(i2cAddr);
    UNSERIALIZE_SCALAR(message);
}

I2CBus*
I2CBusParams::create()
{
    return new I2CBus(this);
}
