/*
 * Copyright (c) 2020 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.
 */

#include "dev/arm/fvp_base_pwr_ctrl.hh"

#include "arch/arm/faults.hh"
#include "arch/arm/system.hh"
#include "arch/arm/utility.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "debug/FVPBasePwrCtrl.hh"
#include "mem/packet_access.hh"
#include "params/FVPBasePwrCtrl.hh"
#include "sim/system.hh"

FVPBasePwrCtrl::FVPBasePwrCtrl(FVPBasePwrCtrlParams *const params)
    : BasicPioDevice(params, 0x1000),
      regs(),
      system(*static_cast<ArmSystem *>(sys))
{
    warn_if(sys->multiThread,
            "Base Power Controller does not support multi-threaded systems\n");
    system.setPowerController(this);
}

void
FVPBasePwrCtrl::init()
{
    // All cores are ON by default (PwrStatus.{l0,l1} = 0b1)
    corePwrStatus.resize(sys->numContexts(), 0x60000000);
    for (const auto &tc : sys->threadContexts)
        poweredCoresPerCluster[tc->socketId()] += 1;
    BasicPioDevice::init();
}

void
FVPBasePwrCtrl::setStandByWfi(ThreadContext *const tc)
{
    PwrStatus *pwrs = getCorePwrStatus(tc);

    if (!pwrs->pwfi)
        DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::setStandByWfi: STANDBYWFI "
                "asserted for core %d\n", tc->contextId());
    pwrs->pwfi = 1;
    if (pwrs->l0 && (pwrs->pp || pwrs->pc))
        powerCoreOff(tc, pwrs);
}

void
FVPBasePwrCtrl::clearStandByWfi(ThreadContext *const tc)
{
    PwrStatus *pwrs = getCorePwrStatus(tc);

    if (pwrs->pwfi)
        DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::clearStandByWfi: STANDBYWFI "
                "deasserted for core %d\n", tc->contextId());
    pwrs->pwfi = 0;
}

Tick
FVPBasePwrCtrl::read(PacketPtr pkt)
{
    const Addr addr = pkt->getAddr() - pioAddr;
    const size_t size = pkt->getSize();
    panic_if(size != 4, "FVPBasePwrCtrl::read: Invalid size %i\n", size);

    uint64_t resp = 0;
    switch (addr) {
      case PPOFFR:
        resp = regs.ppoffr;
        break;
      case PPONR:
        resp = regs.pponr;
        break;
      case PCOFFR:
        resp = regs.pcoffr;
        break;
      case PWKUPR:
        resp = regs.pwkupr;
        break;
      case PSYSR:
        resp = regs.psysr;
        break;
      default:
        warn("FVPBasePwrCtrl::read: Unexpected address (0x%x:%i), "
             "assuming RAZ\n", addr, size);
    }

    DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::read: 0x%x<-0x%x(%i)\n", resp,
            addr, size);

    pkt->setUintX(resp, LittleEndianByteOrder);
    pkt->makeResponse();
    return pioDelay;
}

Tick
FVPBasePwrCtrl::write(PacketPtr pkt)
{
    const Addr addr = pkt->getAddr() - pioAddr;
    const size_t size = pkt->getSize();
    panic_if(size != 4, "FVPBasePwrCtrl::write: Invalid size %i\n", size);

    uint64_t data = pkt->getUintX(LittleEndianByteOrder);

    // Software may use the power controller to check for core presence
    // If core is not present, return an invalid MPID as notification
    ThreadContext *tc = getThreadContextByMPID(data & MPID_MSK);
    PwrStatus *pwrs = tc ? getCorePwrStatus(tc) : nullptr;
    switch (addr) {
      case PPOFFR:
        if (!tc) {
            regs.ppoffr = ~0;
        } else if (pwrs->l0) {
            // Set pending power off
            pwrs->pp = 1;
            regs.ppoffr = data & MPID_MSK;
        } else {
            regs.ppoffr = ~0 & MPID_MSK;
        }
        break;
      case PPONR:
        if (!tc) {
            regs.pponr = ~0;
        } else {
            if (!pwrs->l0) {
                pwrs->wk = WK_PPONR;
                powerCoreOn(tc, pwrs);
                startCoreUp(tc);
                regs.pponr = data & MPID_MSK;
            } else {
                regs.pponr = ~0 & MPID_MSK;
            }
        }
        break;
      case PCOFFR:
        if (!tc) {
            regs.pcoffr = ~0;
        } else if (pwrs->l0) {
            // Power off all cores in the cluster
            for (const auto &tco : sys->threadContexts) {
                if (tc->socketId() == tco->socketId()) {
                    PwrStatus *npwrs = getCorePwrStatus(tco);
                    // Set pending cluster power off
                    npwrs->pc = 1;
                    if (npwrs->l0 && npwrs->pwfi)
                        powerCoreOff(tco, npwrs);
                }
            }
        } else {
            regs.pcoffr = ~0 & MPID_MSK;
        }
        break;
      case PWKUPR:
        if (!tc) {
            regs.pwkupr = ~0;
        } else {
            // Update WEN value
            pwrs->wen = bits(data, 31);
            // Power-on if there is any pending Wakeup Requests
            if (!pwrs->l0 && pwrs->wen && pwrs->pwk) {
                pwrs->wk = WK_GICWR;
                powerCoreOn(tc, pwrs);
                startCoreUp(tc);
            }
            regs.pwkupr = data & (MPID_MSK | (1 << 31));
        }
        break;
      case PSYSR:
        if (!tc)
            regs.psysr = ~0;
        else
            regs.psysr = (data & MPID_MSK) | (((uint32_t) *pwrs) & ~MPID_MSK);
        break;
      default:
        warn("FVPBasePwrCtrl::write: Unexpected address (0x%x:%i), "
             "assuming WI\n", addr, size);
    }

    DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::write: 0x%x->0x%x(%i)\n", data,
            addr, size);

    pkt->makeResponse();
    return pioDelay;
}

FVPBasePwrCtrl::PwrStatus *
FVPBasePwrCtrl::getCorePwrStatus(ThreadContext *const tc)
{
    PwrStatus *pwrs = &corePwrStatus[tc->contextId()];
    pwrs->l1 = poweredCoresPerCluster[tc->socketId()] > 0;
    return pwrs;
}

ThreadContext *
FVPBasePwrCtrl::getThreadContextByMPID(uint32_t mpid) const
{
    for (auto &tc : sys->threadContexts) {
        if (mpid == ArmISA::getAffinity(&system, tc))
            return tc;
    }
    return nullptr;
}

void
FVPBasePwrCtrl::powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs)
{
    DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::powerCoreOn: Powering ON "
            "core %d\n", tc->contextId());
    pwrs->l0 = 1;
    poweredCoresPerCluster[tc->socketId()]++;
    // Clear pending power-offs to the core
    pwrs->pp = 0;
    // Clear pending power-offs to the core's cluster
    for (const auto &tco : sys->threadContexts) {
        if (tc->socketId() == tco->socketId()) {
            PwrStatus *npwrs = getCorePwrStatus(tco);
            npwrs->pc = 0;
        }
    }
    tc->getCpuPtr()->pwrState(Enums::PwrState::ON);
}

void
FVPBasePwrCtrl::powerCoreOff(ThreadContext *const tc, PwrStatus *const pwrs)
{
    DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::powerCoreOff: Powering OFF "
            "core %d\n", tc->contextId());
    pwrs->l0 = 0;
    poweredCoresPerCluster[tc->socketId()]--;
    // Clear pending power-offs to the core
    pwrs->pp = 0;
    pwrs->pc = 0;
    // Clear power-on reason
    pwrs->wk = 0;
    tc->getCpuPtr()->pwrState(Enums::PwrState::OFF);
}

void
FVPBasePwrCtrl::startCoreUp(ThreadContext *const tc)
{
    DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::startCoreUp: Starting core %d "
            "from the power controller\n", tc->contextId());
    clearStandByWfi(tc);

    // InitCPU
    Reset().invoke(tc);
    tc->activate();
}

FVPBasePwrCtrl *
FVPBasePwrCtrlParams::create()
{
    return new FVPBasePwrCtrl(this);
}
