/*
 * cpu_control.c
 * Functions to toggle the state of a cpu
 *
 *  Created on: Jan 4, 2016
 *      Author: shaunc
 *
 *      Versions:
 *      2017.1 - V0.7       WK      Whitespace cleanup for alignment with DED script (8/25/2017)
 *      2016.1 - V0.6       SC      Modifications for the new XilPM library (V2.0)
 *      2015.4 - V0.5       SC      Modified init function to only have it power on the Processing Units
 *                                  Filled in the Power Down Function
 *      2015.4 - V0.4       SC      Added init function
 *      2015.4 - V0.3       WK      Added Debug Output
 *      2015.4 - V0.2       1/12/2016   Removed dead code and removed APU Wake and powerdown functions (students fill these in)
 *      2015.4 - V0.1       1 Jan 2015  First Working Draft Implementation
 *
 */

#include "platform.h"
#include <xparameters.h>
#include <xil_types.h>
#include <xil_printf.h>
#include <pm_common.h>
#include <pm_api_sys.h>
#include <pm_defs.h>
#include <sleep.h>

//Set the initial state of each processor.
//Only RPU0 is accurate initially as the other processors may
//be in an indeterminate state (due to previous debug sessions etc...)
struct psStatus allCpus = { .rpu_0 = running, .rpu_1 = running,
                            .apu_0 = running, .apu_2 = running,
                            .apu_3 = running, .apu_1 = running };
/*
 * ccPowerStatus()
 *
 * Returns a string corresponding to the system's perception of which
 * processors are powered on ('+') and which are off ('_')
 *
 * History
 *    0.1 - WK - initial coding
 */
char *ccPowerStatus() {
    static char s[39] = {'R',' ','R',' ','A',' ','A',' ','A',' ','A','\n','\r',
                         '0',' ','1',' ','0',' ','1',' ','2',' ','3','\n','\r',
                         '?',' ','?',' ','?',' ','?',' ','?',' ','?','\n','\r'};
    // fill in the status for each processor
    if (allCpus.rpu_0 == running) { s[26] = '+'; } else { s[26] = '_'; }
    if (allCpus.rpu_1 == running) { s[28] = '+'; } else { s[28] = '_'; }
    if (allCpus.apu_0 == running) { s[30] = '+'; } else { s[30] = '_'; }
    if (allCpus.apu_1 == running) { s[32] = '+'; } else { s[32] = '_'; }
    if (allCpus.apu_2 == running) { s[34] = '+'; } else { s[34] = '_'; }
    if (allCpus.apu_3 == running) { s[36] = '+'; } else { s[36] = '_'; }
    return s;
}

void ccToggleRpu1() {
    if (allCpus.rpu_1 == noPower) {
        //Request Power Up Here
        XPm_RequestWakeUp(NODE_RPU_1,FALSE,0x00, REQUEST_ACK_NO);
        allCpus.rpu_1 = running;
    } else {
        //Force a power down here
        XPm_ForcePowerDown(NODE_RPU_1, REQUEST_ACK_NO);
        allCpus.rpu_1 = noPower;
    }
}

void ccToggleApu0() {
    if (allCpus.apu_0 == noPower) {
        //Request Power Up Here
        XPm_RequestWakeUp(NODE_APU_0, FALSE, 0x00, REQUEST_ACK_NO);
        allCpus.apu_0 = running;
    } else {
        //Force a power down here
        XPm_ForcePowerDown(NODE_APU_0, REQUEST_ACK_NO);
        allCpus.apu_0 = noPower;
    }
}

void ccToggleApu1() {
    if (allCpus.apu_1 == noPower) {
        //Request Power Up Here
        XPm_RequestWakeUp(NODE_APU_1, FALSE, 0x00, REQUEST_ACK_NO);
        allCpus.apu_1 = running;
    } else {
        //Force a power down here
        XPm_ForcePowerDown(NODE_APU_1, REQUEST_ACK_NO);
        allCpus.apu_1 = noPower;
    }
}

void ccToggleApu2() {
    if (allCpus.apu_2 == noPower) {
        //Request Power Up Here
        XPm_RequestWakeUp(NODE_APU_2, FALSE, 0x00, REQUEST_ACK_NO);
        allCpus.apu_2 = running;
    } else {
        //Force a power down here
        XPm_ForcePowerDown(NODE_APU_2, REQUEST_ACK_NO);
        allCpus.apu_2 = noPower;
    }
}

void ccToggleApu3() {
    if (allCpus.apu_3 == noPower) {
        //Request Power Up Here
        XPm_RequestWakeUp(NODE_APU_3,FALSE,0x00, REQUEST_ACK_NO);
        allCpus.apu_3 = running;
    } else {
        //Force a power down here
        XPm_ForcePowerDown(NODE_APU_3, REQUEST_ACK_NO);
        allCpus.apu_3 = noPower;
    }
}

void ccPowerDownAll() {
    xil_printf("Force Powering Down all APUs\r\n");
    //Force a power down of the RPU_1 and APU_1-3
    XPm_ForcePowerDown(NODE_APU_1, REQUEST_ACK_NO);
    XPm_ForcePowerDown(NODE_APU_2, REQUEST_ACK_NO);
    XPm_ForcePowerDown(NODE_APU_3, REQUEST_ACK_NO);

    //Request Power Down for all APUs here
    xil_printf("Force Powering Down  RPU_1\r\n");
    XPm_ForcePowerDown(NODE_RPU_1, REQUEST_ACK_NO);
}

void ccInit(){
    //Request a wake up of the RPU_1 and APU_0-3
    XPm_ForcePowerDown(NODE_RPU_1, REQUEST_ACK_NO);
    XPm_RequestWakeUp(NODE_RPU_1,FALSE,0x00, REQUEST_ACK_NO);
    XPm_RequestWakeUp(NODE_APU_0,FALSE,0x00, REQUEST_ACK_NO);
    XPm_RequestWakeUp(NODE_APU_1,FALSE,0x00, REQUEST_ACK_NO);
    XPm_RequestWakeUp(NODE_APU_2,FALSE,0x00, REQUEST_ACK_NO);
    XPm_RequestWakeUp(NODE_APU_3,FALSE,0x00, REQUEST_ACK_NO);

}



//<copyright-disclaimer-start>
//  **************************************************************************************************************
//  * © 2024 Advanced Micro Devices, Inc. All rights reserved.                                                   *
//  * DISCLAIMER                                                                                                 *
//  * The information contained herein is for informational purposes only, and is subject to change              *
//  * without notice. While every precaution has been taken in the preparation of this document, it              *
//  * may contain technical inaccuracies, omissions and typographical errors, and AMD is under no                *
//  * obligation to update or otherwise correct this information.  Advanced Micro Devices, Inc. makes            *
//  * no representations or warranties with respect to the accuracy or completeness of the contents of           *
//  * this document, and assumes no liability of any kind, including the implied warranties of noninfringement,  *
//  * merchantability or fitness for particular purposes, with respect to the operation or use of AMD            *
//  * hardware, software or other products described herein.  No license, including implied or                   *
//  * arising by estoppel, to any intellectual property rights is granted by this document.  Terms and           *
//  * limitations applicable to the purchase or use of AMD’s products are as set forth in a signed agreement     *
//  * between the parties or in AMD's Standard Terms and Conditions of Sale. GD-18                               *
//  *                                                                                                            *
//  **************************************************************************************************************
//<copyright-disclaimer-end>
