/*******************************************************************************
 * (c) Copyright 2016-2017 Microsemi SoC Products Group. All rights reserved.
 *
 * CoreSysService_PF driver Device and design info services example.
 *
 * This simple example demonstrates how to use the CoreSysService_PF driver to
 * execute Device and design info services and data security service supported
 * by PolarFire System Controller.
 *
 * This sample project is targeted at a RISC-V design running on the PolarFire
 * High Speed Validation board.
 *
 * This program displays the return data from System controller for various
 * Device and Design services.
 *
 * Please refer README.txt in the root folder of this project for more details.
 *
 * SVN $Revision: 8769 $
 * SVN $Date: 2017-01-13 17:38:49 +0530 (Fri, 13 Jan 2017) $
 */

#include <stdio.h>

#include "hal.h"
#include "miv_rv32_hal\hw_platform.h"
#include "core_uart_apb.h"
#include "miv_rv32_hal.h"
#include "core_gpio.h"
#include "hw_reg_access.h"



/******************************************************************************
 * Maximum receiver buffer size.
 *****************************************************************************/
#define MAX_RX_DATA_SIZE                        256

#define ENTER                                   13u
#define TIMEOUT                                 5000u
//GPIO_instance
gpio_instance_t g_gpio_out;
volatile uint8_t temp = 0;

// MAC Core control/status registers

uint32_t  *MDIO_mgmt_Adress_reg       = (uint32_t *) ( 0x73000028);
uint32_t  *MDIO_mgmt_Command_reg      = (uint32_t *) ( 0x73000024);
uint32_t  *MDIO_mgmt_Control_reg      = (uint32_t *) ( 0x7300002C);
uint32_t  *MDIO_mgmt_Status_reg       = (uint32_t *) ( 0x73000030);
uint32_t  *MDIO_mgmt_Indicators_reg   = (uint32_t *) ( 0x73000034);
uint32_t  *MAC_FIFO_CONFIG_reg        = (uint32_t *) ( 0x7300005C);
uint32_t  *MAC_CONFIG_1_reg           = (uint32_t *) ( 0x73000000);
uint32_t  *MAC_CONFIG_2_reg           = (uint32_t *) ( 0x73000004);
uint32_t  *Station_address_lower_reg  = (uint32_t *) ( 0x73000040);
uint32_t  *Station_address_higher_reg = (uint32_t *) ( 0x73000044);
uint32_t  *MAC_FIFO_CONFIG_reg0       = (uint32_t *) ( 0x73000048);
uint32_t  *MAC_FIFO_CONFIG_reg1       = (uint32_t *) ( 0x7300004C);
uint32_t  *MAC_FIFO_CONFIG_reg2       = (uint32_t *) ( 0x73000050);
uint32_t  *MAC_FIFO_CONFIG_reg3       = (uint32_t *) ( 0x73000054);
uint32_t  *MAC_FIFO_CONFIG_reg4       = (uint32_t *) ( 0x73000058);
uint32_t  *MAC_FIFO_CONFIG_reg5       = (uint32_t *) ( 0x7300005C);
uint32_t  *Frame_control_filter_reg   = (uint32_t *) ( 0x730001C0);
uint32_t  *MDIO_mgmt_CONFIG_reg       = (uint32_t *) ( 0x73000020);
uint32_t  *Interface_control_reg      = (uint32_t *) ( 0x73000038);






/******************************************************************************
 * CoreUARTapb instance data.
 *****************************************************************************/
UART_instance_t g_uart;

void phy_init(void)
{

	volatile uint32_t phy_reg = 0xFFFF;
	volatile uint32_t temp_reg = 0xFFFF;

  // The following configuration steps is taken from VSC8541 data sheet
  // Select page 0
	 *MDIO_mgmt_Adress_reg   = 0x0A1F;
	 *MDIO_mgmt_Control_reg  = 0x0000;
    while ((*MDIO_mgmt_Indicators_reg) != 0);
	// Reading 1f register (default should be 0), writing back 0
    *MDIO_mgmt_Adress_reg  = 0x0A1F;
    *MDIO_mgmt_Command_reg = 0x1;
    while ((*MDIO_mgmt_Indicators_reg) != 0);
    temp_reg = *MDIO_mgmt_Status_reg;
    *MDIO_mgmt_Command_reg = 0x0;
	// Writing VSC 0x17 (write 12:11 = 2'b10)
    *MDIO_mgmt_Control_reg = 0x0;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

  // Reading VSC 0x17
    *MDIO_mgmt_Adress_reg  = 0x0A17;
    *MDIO_mgmt_Command_reg = 0x1;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

    temp_reg = *MDIO_mgmt_Status_reg;
    *MDIO_mgmt_Command_reg  = 0x0;

  // Writing VSC 0x17 (write 12:11 = 2'b10)
    temp_reg = temp_reg | 1<<12; // from 0th bit
    temp_reg = temp_reg & ~(1<<11); // 0000100000 ~ = 11111011111
    *MDIO_mgmt_Control_reg = temp_reg;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

  // SW reset Read and write at 0
    *MDIO_mgmt_Adress_reg = 0x0A00;
    *MDIO_mgmt_Command_reg = 0x1;
    while ((*MDIO_mgmt_Indicators_reg) != 0);
    phy_reg = *MDIO_mgmt_Status_reg;
    *MDIO_mgmt_Command_reg = 0x0;

    *MDIO_mgmt_Adress_reg  = 0x0A00;
     phy_reg = phy_reg | 0x8000;
    *MDIO_mgmt_Control_reg   = phy_reg;
    while ((*MDIO_mgmt_Indicators_reg) != 0);
	// Read until bit15 = 0

    // Wait for soft reset to complete
    do
    {
    	*MDIO_mgmt_Adress_reg = 0x0A00;
    	*MDIO_mgmt_Command_reg  = 0x1;
    	while ((*MDIO_mgmt_Indicators_reg) != 0);

       temp_reg =  *MDIO_mgmt_Status_reg;
       *MDIO_mgmt_Command_reg  = 0x0;
    } while(0 != (temp_reg & 0x8000U));

  // For RGMII mode: configure register 20E2 (to access register 20E2, register 31 must be set to 2).
    // Set bit 11 to 0 and set RX_CLK delay and TX_CLK delay accordingly through bit [6:4] and/or bit [2:0]
    // respectively.

    // Select page 2
    *MDIO_mgmt_Adress_reg  = 0x0A1F;
    *MDIO_mgmt_Control_reg = 0x0002;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

    // Adjust MAC interface slew rate - default is 111 but recommended for 3.3V i/o is 100
    // This is an extra step that is being done for the RTPF evaluation kit, as this uses 3.3V pins (bank 4 : ethernet phy pins)
    *MDIO_mgmt_Adress_reg = 0x0A1B;
    *MDIO_mgmt_Command_reg = 0x1;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

    temp_reg = *MDIO_mgmt_Status_reg;
    *MDIO_mgmt_Command_reg = 0x0;

    temp_reg = temp_reg & 0xFF1FU;
    temp_reg = temp_reg | 0x0080U;

    *MDIO_mgmt_Adress_reg = 0x0A1B;
    *MDIO_mgmt_Control_reg   = temp_reg;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

 /* // For Adjustments for TX and RX clk delay
     *MDIO_mgmt_Adress_reg  = 0x0A14;
     *MDIO_mgmt_Command_reg  = 0x1;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

    temp_reg = *MDIO_mgmt_Status_reg;
    *MDIO_mgmt_Command_reg = 0x0;
    temp_reg = temp_reg | 0x05;  //Write the correct values so that there is NO FCS

    *MDIO_mgmt_Adress_reg = 0x0A14;
    *MDIO_mgmt_Control_reg = temp_reg;
     while ((*MDIO_mgmt_Indicators_reg) != 0); */



   // Select back page 0
    *MDIO_mgmt_Adress_reg = 0x0A1F;
    *MDIO_mgmt_Control_reg  = 0x0000;
    while ((*MDIO_mgmt_Indicators_reg) != 0);


// Make the below if 1 if you want to check far end loopback testing
#if 0
// FAR END TESTING
	 //Reading VSC 0x17
    *MDIO_mgmt_Adress_reg = 0x0A17;
    *MDIO_mgmt_Command_reg = 0x1;
    while ((*MDIO_mgmt_Indicators_reg) != 0);

		    temp_reg = *MDIO_mgmt_Status_reg;
		    *MDIO_mgmt_Command_reg = 0x00000000;

		    // Writing VSC 0x17
		    // far-end loopback
		    temp_reg = temp_reg | 0x00000008;
		    *MDIO_mgmt_Control_reg = temp_reg;
		    while ((*MDIO_mgmt_Indicators_reg) != 0);
#endif

}
// TSE Initialization

void tse_init (void)
{
	uint32_t tse_reg = 0xFFFF, phy_reg, temp;
	volatile uint32_t dummy_timer = 1000000u;

	//TSE Register settings

	tse_reg = *MAC_FIFO_CONFIG_reg;

	*MAC_CONFIG_1_reg           = 0x00000005;
	*MAC_CONFIG_2_reg           = 0x00007201;
	*Station_address_lower_reg  = 0x6060603C;
	*Station_address_higher_reg = 0xB1C00000;
	*MAC_FIFO_CONFIG_reg0       = 0x0000FF00;
	*MAC_FIFO_CONFIG_reg1       = 0x0FFF0000;
	*MAC_FIFO_CONFIG_reg2       = 0x04000180;
	*MAC_FIFO_CONFIG_reg3       = 0x0680FFFF;
	*MAC_FIFO_CONFIG_reg4       = 0x00000000;
	*MAC_FIFO_CONFIG_reg5       = 0x0007FFFF;
	*Frame_control_filter_reg   = 0x0000000F;
	*MDIO_mgmt_CONFIG_reg       = 0x0007;
    *Interface_control_reg      = 0x4;

	// Add delay
	do {
			--dummy_timer;
		} while(dummy_timer != 0u);

	phy_init();


}


/*-------------------------------------------------------------------------*//**
 * main() function.
 */
int main() {
	uint8_t testmsg1[] = {"\r\n\r\nRGMII ethernet loop back demo\n\r"};
	volatile int delay = 59359400;

	/**************************************************************************
	 * Initialize CoreUARTapb with its base address, baud value, and line
	 * configuration.
	 *************************************************************************/
	 UART_init(&g_uart, COREUARTAPB0_BASE_ADDR,
	 BAUD_VALUE_115200, (DATA_8_BITS | NO_PARITY));

	/**************************************************************************
	 * Send the instructions message.
	 *************************************************************************/
	  UART_polled_tx_string(&g_uart,(const uint8_t *)&testmsg1);

      /**************************************************************************
	      * Initialize the CoreGPIO driver with the base address of the CoreGPIO
	      * instance to use and the initial state of the outputs.
	      *************************************************************************/
	   GPIO_init(&g_gpio_out, COREGPIO_OUT_BASE_ADDR, GPIO_APB_32_BITS_BUS);


	     /**************************************************************************
	      * Set the GPIO outputs.
	      *************************************************************************/
	   GPIO_set_output( &g_gpio_out, GPIO_0,0 );
	   GPIO_set_output( &g_gpio_out, GPIO_1,0);
       GPIO_set_output( &g_gpio_out, GPIO_2,0 );
	   GPIO_set_output( &g_gpio_out, GPIO_3,0 );

	   tse_init();

	   uint8_t testmsg2[] = {"\r\n\r\nTSE Init done\n\r"};
	   UART_polled_tx_string(&g_uart,(const uint8_t *)&testmsg2);


       GPIO_set_output( &g_gpio_out, GPIO_0,1 );


	   while(1);

}
