/*-------------------------------------------------------------------------------------------------
--
-- File Name    : coaxpressXcvrSpeed.c



-- Description  : This module replicates the CoaXPress Device Link speed settings.




-- Targeted device : Microchip FPGAs
-- Author          : India Solutions Team




--
-- COPYRIGHT 2023 BY MICROCHIP
-- THE INFORMATION CONTAINED IN THIS DOCUMENT IS SUBJECT TO LICENSING RESTRICTIONS
-- FROM MICROCHIP CORP.  IF YOU ARE NOT IN POSSESSION OF WRITTEN AUTHORIZATION FROM
-- MICROCHIP FOR USE OF THIS FILE, THEN THE FILE SHOULD BE IMMEDIATELY DESTROYED AND
-- NO BACK-UP OF THE FILE SHOULD BE MADE.
--



-------------------------------------------------------------------------------------------------*/

#include "hal/hal.h"

#include "coaxpressHost.h"
#include "coaxpressXcvrSpeed.h"

uint32_t pll_lock;

void wait_for_pll_lock()
{
    pll_lock = 0;
    do
    {
        pll_lock = *(volatile unsigned int *)(CXP_DEV_XCVR_BASE +  0x00081088); //PMA_CTRL_R0 - PMA_TXPLL_LOCK_STATUS
        pll_lock = pll_lock && 0x100000000;
        msdelay1(10);
    }while(pll_lock == 0);
}

void update_hdmi_xcvr_speed(uint32_t gpio_status)
{

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110104C)=0x33;//DES_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1101078)=0x3; //SER_RSTPD

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110204C)=0x33;//DES_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1102078)=0x3; //SER_RSTPD

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110404C)=0x33;//DES_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1104078)=0x3; //SER_RSTPD

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110804C)=0x33;//DES_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1108078)=0x3; //SER_RSTPD

    if (gpio_status && 0x00000001) //FHD
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1101074 ) = 0x73;//Lane1 Q2_PCS_LANE0 SER_CLK_CTRL
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1102074 ) = 0x73;//Lane2 Q2_PCS_LANE1 SER_CLK_CTRL
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1104074 ) = 0x73;//Lane3 Q2_PCS_LANE2 SER_CLK_CTRL
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1108074 ) = 0x73;//Lane0 Q2_PCS_LANE3 SER_CLK_CTRL
    }
    else //4K
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1101074 ) = 0x70;//Lane1 Q2_PCS_LANE0 SER_CLK_CTRL
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1102074 ) = 0x70;//Lane2 Q2_PCS_LANE1 SER_CLK_CTRL
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1104074 ) = 0x70;//Lane3 Q2_PMA_LANE2 SER_CLK_CTRL
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1108074 ) = 0x70;//Lane0 Q2_PCS_LANE3 SER_CLK_CTRL
    }


    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1101078)=0x1;//SER_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110104C)=0x30;//DES_RSTPD

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1102078)=0x1;//SER_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110204C)=0x30;//DES_RSTPD

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1104078)=0x1;//SER_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110404C)=0x30;//DES_RSTPD

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x1108078)=0x1;//SER_RSTPD
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + 0x110804C)=0x30;//DES_RSTPD

}

void update_cxp_xcvr_uplink_speed(uint8_t data)
{
    volatile uint32_t calib_status;

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RSTPD)=0x33;
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_RSTPD)=0x3;
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CMD) = 0x00;
    *(volatile unsigned int *)(CMD_RATE_SEL_ADDR)=0x0;   // default Low speed Upconnection Rate Select

    if (data == RATE_1DOT25G) //1.25G
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x40100;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x0;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000005;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x5;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x4419;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x73;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x0;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x101481d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400010;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x0019000A;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x01000000;

    }
    else if (data == RATE_2DOT5G) //2.5G
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x40100;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000005;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x5;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x2219;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x73;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x101491d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400010;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x320014;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x1000000;

    }
    else if (data == RATE_3DOT125G) //3.125
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x40100;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000005;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x5;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x287d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x73;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x101491d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400010;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x7d0019;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x2000000;

    }
    else if (data == RATE_5DOT0G) //5G
    {

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x40100;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x15;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000005;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x5;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x232;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x71;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x101491d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400010;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x320014;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x1000000;

    }
    else if (data == RATE_6DOT25G) //6.25G
    {

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x2a;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x4024f;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x2a;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x4f00;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000006;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x6;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x47d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x71;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x101491d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400010;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x007D000D;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x04000000;

    }
    else if (data == RATE_10DOT0G) //10G
    {
        *(volatile unsigned int *)(CMD_RATE_SEL_ADDR)=0x1;   // Low speed Upconnection Rate Select

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x2a;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x4036f;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x2a;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x6f00;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000007;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x7;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x8264;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x70;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x0;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x1014a1d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400010;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x320014;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x1000000;

    }
    else if (data == RATE_12DOT5G) //12.5G
    {
        *(volatile unsigned int *)(CMD_RATE_SEL_ADDR)=0x1;   // Low speed Upconnection Rate Select

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_2)=0x3f;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_CDR_CTRL_3)=0x4037f;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_1)=0x3f;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_2)=0x11121306;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFEEM_CTRL_3)=0x7f11;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CTRL_2)=0x4000007;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_EM_CTRL_2)=0x7;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RXPLL_DIV)=0x827d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_CLK_CTRL)=0x70;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SERDES_RTL_CTRL)=0x10000;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f071d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x105431c;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_2)=0x400000;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CMD) = 0x400;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_1)=0x7d0019;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + TXPLL_DIV_2)=0x2000000;

    }

    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + SER_RSTPD)=0x1;
    *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_RSTPD)=0x30;


    msdelay1(10);
    //CTLE calibration
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f0715;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x1014a1d;

        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CMD) = 0x40000;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CMD) = 0x00000;

        calib_status = 0;
        do
        {
            calib_status = *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_FLAG);
            calib_status = calib_status && 0x100000;//DES_DFE_CAL_FLAG->FULL_CALIB_DONE
            msdelay1(10);
        }while(calib_status == 0);
    }

    //DFE calibration for Rate 12G
    if (data == RATE_12DOT5G)
    {
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_0)=0xff3f071d;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CTRL_1)=0x105431c;
        msdelay1(10);
        //initiate DFE calibration
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CMD) = 0x10400;
        *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_CMD) = 0x00400;

        calib_status = 0;
        do
        {
            calib_status = *(volatile unsigned int *)(CXP_DEV_XCVR_BASE + DES_DFE_CAL_FLAG);
            calib_status = calib_status && 0x40000;
            msdelay1(10);
        }while(calib_status == 0);
    }

}

