/**
 * tiescbsp.h
 *
*/
/*
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * 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 Texas Instruments Incorporated 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.
 **/
#ifndef _TIESCBSP_H_
#define _TIESCBSP_H_

/*-----------------------------------------------------------------------------------------
------
------  Includes
------
-----------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <xdc/std.h>
#include "tiesc_pruss_intc_mapping.h"
#include "osdrv_pruss.h"
#ifndef ECAT_LIMITED_DEMO
    /*
    ecat_def.h is included only to get CiA402_DEVICE macro definition status.
    This is not needed for limited demo application and hence ignored in that case
    */
    #include "ecat_def.h"
#endif

/*Single datagram accessing contiguous multiple FMMU mapped areas in  a single slave for process data
is supported now by TI ESC firmware.
Process path latency in TI ESC is high when this support is active
For specific use cases (4SM with 3 FMMUs or multiple FMMUs (in a given ESC) are not accessed in a single datagram)
process path latency improvement can be achieved by disabling below define */
#define ENABLE_MULTIPLE_SM_ACCESS_IN_SINGLE_DATAGRAM     0

#if (!CiA402_DEVICE )
    #define EEPROM_SPI /*Comment this to enable volatile EEPROM support for debug*/
#endif

#define SPI_EEPROM_DATA_OFFSET 0xA0000
#ifdef AM335X_FAMILY_BUILD
    /*SPI Flash offset at which application binary downloaded over FOE will be stored*/
    #define FOE_APPL_BIN_OFFSET (SPI_APPL_BIN_OFFSET)
#elif defined(AM43XX_FAMILY_BUILD)
    #define FOE_APPL_BIN_OFFSET (QSPI_APPL_BIN_OFFSET)
#endif

/*#define   OS_TICKS_IN_MILLI_SEC   10 // 100us tick */
#define OS_TICKS_IN_MILLI_SEC   1 /* 1000us tick */
#define PROTO extern

#define SWAPWORD
#define SWAPDWORD


#define ICSS_MDIO_USRPHYSEL_LINKINT_ENABLE 0x40
#define ICSS_MDIO_USRPHYSEL_LINKSTAT_MLINK 0x80

#define CM_PER_SPINLOCK_CLKCTRL_OFFSET  0x44E0010C //Could not find starteware equivalent
#define SPINLOCK_LOCKREG0_OFFSET 0x480CA800


#define TIESC_PERM_RW       0x0
#define TIESC_PERM_WRITE_ONLY 0x1
#define TIESC_PERM_READ_ONLY 0x2

#define TIESC_PERM_WRITE TIESC_PERM_WRITE_ONLY
#define TIESC_PERM_READ TIESC_PERM_READ_ONLY


#define TIESC_MDIO_CLKDIV   79 //For 2.5MHz MDIO clock: 200/(TIESC_MDIO_CLKDIV+1)

#define TIESC_MDIO_RX_LINK_DISABLE  0 //Slow MDIO state m/c based link detection
#define TIESC_MDIO_RX_LINK_ENABLE   1 //Fast link detect using RXLINK forward from PHY to MDIO MLINK
#define TIESC_LINK_POL_ACTIVE_LOW       1
#define TIESC_LINK_POL_ACTIVE_HIGH      0

#define PDI_WD_TRIGGER_RX_SOF       (0 << 4)
#define PDI_WD_TRIGGER_LATCH_IN     (1 << 4)
#define PDI_WD_TRIGGER_SYNC0_OUT    (2 << 4)
#define PDI_WD_TRIGGER_SYNC1_OUT    (3 << 4)

#if ENABLE_MULTIPLE_SM_ACCESS_IN_SINGLE_DATAGRAM
    #define TIESC_PORT0_TX_DELAY    0x98
#else
    #define TIESC_PORT0_TX_DELAY    0x48
#endif
#define TIESC_PORT1_TX_DELAY    TIESC_PORT0_TX_DELAY

#define PDI_ISR_EDIO_NUM    7 //GPMC_CSN(2) -> pr1_edio_data_out7 for ICEv2.J4.Pin21

/* PDI  side register protection using register permission table (4KB) in memory - disable if you care for performance and memory foot print */
//#define ENABLE_PDI_REG_PERMISSIONS

/* Use ESC system time instead of SYS/BIOS Timestamp_get32 for timing info */
#define USE_ECAT_TIMER

#define ENABLE_ONLINE_FIRMWARE_UPGRADE

/* Uncomment following to enable DC feature of system time compensation via PDI interface instead of ECAT interface
   for synchronizing two independent EtherCAT networks */
//#define SYSTEM_TIME_PDI_CONTROLLED
#define FORCE_SYSTEM_TIME_PDI_CONTROLLED_API
/*Comment to following to enable PDI  ISR and SYNC ISR in HWI context */
#define  ENABLE_PDI_TASK
/* #define ENABLE_PDI_SWI */
#define  ENABLE_SYNC_TASK
/* If PDI and SYNC ISR is handled in HWI context (similar to SSC)
  interrupt mode of CMDACK won't work as they are low priority than
  SYNC and PDI ISR - use polling instead */
/* #define  SUPPORT_CMDACK_POLL_MODE */

#define ASSERT_DMB() __asm("    dmb")
#define ASSERT_DSB() __asm("    dsb")

#ifdef USE_ECAT_TIMER
    #define ECAT_TIMER_INC_P_MS 1000000
#else
    #define ECAT_TIMER_INC_P_MS ecat_timer_inc_p_ms /* ARM frequency: Will be detected during bsp_init*/
    extern volatile Uint32 ecat_timer_inc_p_ms;
#endif

typedef void (*bsp_function_handler)(void);

/* Struct for host to PRUSS command interface */
typedef struct
{
    Uint8 sm_buf_index;
    Uint8 lock_state;
    Uint16 addr;
} t_sm_processdata;

#define LOCK_PD_BUF_AVAILABLE_FOR_HOST  0
#define LOCK_PD_BUF_HOST_ACCESS_START   1
#define LOCK_PD_BUF_HOST_ACCESS_FINISH  2

typedef struct
{
    Uint8 reserved1[0x90];
    Uint32 system_time_low;
    Uint32 system_time_high;
    Uint8 sm_config_ongoing;
    Uint8 reserved2[7];
    Uint16 cmdlow;
    Uint16 cmdlow_ack;
    Uint16 param1low;
    Uint16 param2low;
    Uint16 resp1low;
    Uint16 resp2low;
    #if !defined(SYSTEM_TIME_PDI_CONTROLLED) && !defined(FORCE_SYSTEM_TIME_PDI_CONTROLLED_API)
    Uint8 reserved3[212];
    #else
    Uint8 reserved3[24];
    Uint32 systime_offset_low;
    Uint32 systime_offset_high;
    Uint8 reserved4[180];
    #endif
    t_sm_processdata sm_processdata[6];
} t_host_interface;

/* Struct for register permission array */
typedef struct
{
    Uint8 reserved[1024];
    Uint8 reg_properties[4096];
} t_register_properties;

typedef struct
{
    Uint16 physical_start_addr;
    Uint16 length;
} t_sm_properties;

typedef struct
{
    Uint16 clkdiv;
    Uint8 addr0;
    Uint8 addr1;
    Uint8 link0pol; /* 1: Active lLow 0: Active High */
    Uint8 link1pol; /* 1: Active lLow 0: Active High */
    Uint8 enhancedlink_enable;
} t_mdio_params;

PROTO Int32 bsp_main(void);
PROTO void bsp_esc_reg_perm_init(PRUICSS_Handle
                                 pruIcssHandle);  //Internal API - invoked by bsp_init
PROTO void bsp_init(PRUICSS_Handle pruIcssHandle);
PROTO inline Uint8  bsp_get_pdi_access_perm(Uint16 address, Uint8 access);
PROTO inline Uint8  bsp_pdi_access_perm_word(Uint16 address, Uint8 access);
PROTO inline Uint8  bsp_pdi_access_perm_dword(Uint16 address, Uint8 access);
PROTO inline Uint8  bsp_pdi_access_perm_array(Uint16 address, Uint8 access,
        Uint16 size);
PROTO void bsp_exit(PRUICSS_Handle pruIcssHandle);
PROTO Uint32 bsp_get_timer_register(void);
PROTO void bsp_clear_timer_register(void);
PROTO void bsp_get_local_sys_time(Uint32 *systime_low, Uint32 *systime_high);
PROTO void bsp_get_latch0_posedge_time(PRUICSS_Handle pruIcssHandle,
                                       Uint32 *systime_low, Uint32 *systime_high);
PROTO void bsp_get_latch0_negedge_time(PRUICSS_Handle pruIcssHandle,
                                       Uint32 *systime_low, Uint32 *systime_high);
PROTO void bsp_get_latch1_posedge_time(PRUICSS_Handle pruIcssHandle,
                                       Uint32 *systime_low, Uint32 *systime_high);
PROTO void bsp_get_latch1_negedge_time(PRUICSS_Handle pruIcssHandle,
                                       Uint32 *systime_low, Uint32 *systime_high);
#if defined(SYSTEM_TIME_PDI_CONTROLLED) || defined(FORCE_SYSTEM_TIME_PDI_CONTROLLED_API)
PROTO void bsp_pdi_write_system_time(PRUICSS_Handle pruIcssHandle, Uint32 systime);
PROTO void bsp_pdi_write_system_timeoffset(PRUICSS_Handle pruIcssHandle, unsigned long long systime);
PROTO void bsp_pdi_write_systime_delay(PRUICSS_Handle pruIcssHandle, Uint32 systime);
PROTO void bsp_pdi_write_filterconfig(PRUICSS_Handle pruIcssHandle, Uint16 speedcount_start,
                                      Uint8 speedcount_filtdepth, Uint8 systime_filtdepth);
#endif
PROTO void bsp_set_pdi_wd_trigger_mode(PRUICSS_Handle pruIcssHandle,
                                       Uint32 mode);
PROTO  void bsp_set_digio_sw_dataout_enable(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_set_digio_out(PRUICSS_Handle pruIcssHandle, Uint8 num);
PROTO void bsp_clear_digio_out(PRUICSS_Handle pruIcssHandle, Uint8 num);
PROTO void bsp_eeprom_emulation_init(void);
PROTO Int32 bsp_eeprom_load_esc_registers(PRUICSS_Handle pruIcssHandle,
        Int32 reload_flag);
PROTO Int32 bsp_eeprom_emulation_reload(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_eeprom_emulation_command_ack(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_eeprom_emulation_flush(void);
PROTO void bsp_eeprom_emulation_exit(void);
PROTO Uint8 *bsp_get_eeprom_cache_base(void);
void bsp_set_eeprom_updated_time(void);
Uint32 bsp_get_eeprom_updated_time(void);
PROTO void bsp_start_esc_isr(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_send_command_to_firmware(PRUICSS_Handle pruIcssHandle,
                                        Uint32 command, Uint16 param1, Uint16 param2);
PROTO void bsp_pdi_post_read_indication(PRUICSS_Handle pruIcssHandle,
                                        Uint16 address);
PROTO void bsp_pdi_write_indication(PRUICSS_Handle pruIcssHandle,
                                    Uint16 address, Uint16 value);
PROTO void bsp_pdi_mbx_read_start(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_pdi_mbx_read_complete(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_pdi_mbx_write_start(PRUICSS_Handle pruIcssHandle);
PROTO void bsp_pdi_mbx_write_complete(PRUICSS_Handle pruIcssHandle);

PROTO Int16 bsp_get_sm_index(Uint16 address, Uint16 len);
PROTO Uint16 bsp_get_process_data_address(PRUICSS_Handle pruIcssHandle,
        Uint16 address, Uint16 len, Int16 *p_sm_index);
PROTO void bsp_process_data_access_complete(PRUICSS_Handle pruIcssHandle,
        Uint16 address, Uint16 len, Int16 sm_index);

PROTO void bsp_set_sm_properties(Uint8 sm, Uint16 address, Uint16 len);
PROTO t_sm_properties *bsp_get_sm_properties(Uint8 sm);
PROTO Uint32 bsp_read_dword(PRUICSS_Handle pruIcssHandle, Uint16 address);
PROTO Uint32 bsp_read_dword_isr(PRUICSS_Handle pruIcssHandle, Uint16 address);
PROTO Uint16 bsp_read_word(PRUICSS_Handle pruIcssHandle, Uint16 address);
PROTO Uint16 bsp_read_word_isr(PRUICSS_Handle pruIcssHandle, Uint16 address);
PROTO Uint8 bsp_read_byte(PRUICSS_Handle pruIcssHandle, Uint16 address);
PROTO Uint8 bsp_read_byte_isr(PRUICSS_Handle pruIcssHandle, Uint16 address);
PROTO void bsp_read(PRUICSS_Handle pruIcssHandle, Uint8 *pdata, Uint16 address,
                    Uint16 len);
PROTO void bsp_write_dword(PRUICSS_Handle pruIcssHandle, Uint32 val,
                           Uint16 address);
PROTO void bsp_write_word(PRUICSS_Handle pruIcssHandle, Uint16 val,
                          Uint16 address);
PROTO void bsp_write_byte(PRUICSS_Handle pruIcssHandle, Uint8 val,
                          Uint16 address);
PROTO void bsp_write(PRUICSS_Handle pruIcssHandle, Uint8 *pdata,
                     Uint16 address, Uint16 len);
PROTO Uint32 bsp_pruss_mdioreg_read(PRUICSS_Handle pruIcssHandle,
                                    Uint32 regoffset);
PROTO void bsp_pruss_mdioreg_write(PRUICSS_Handle pruIcssHandle, Uint32 val,
                                   Uint32 regoffset);
PROTO Uint32 bsp_pruss_iepreg_read(PRUICSS_Handle pruIcssHandle,
                                   Uint32 regoffset);
PROTO void bsp_pruss_iepreg_write(PRUICSS_Handle pruIcssHandle, Uint32 val,
                                  Uint32 regoffset);
PROTO void bsp_pruss_cmd_intfc_write_word(Uint16 val, volatile Uint16 *ptr);
PROTO Uint16 bsp_pruss_cmd_intfc_read_word(volatile Uint16 *ptr);
PROTO Uint8 bsp_pdi_sm_config_ongoing(PRUICSS_Handle pruIcssHandle);

PROTO Int16 bsp_pruss_mdio_init(PRUICSS_Handle pruIcssHandle,
                                t_mdio_params *pmdio_params);
PROTO Int16 bsp_pruss_mdio_phy_read(PRUICSS_Handle pruIcssHandle,
                                    Uint8 phyaddr, Uint8 regoffset, Uint16 *regval);
PROTO Int16 bsp_pruss_mdio_phy_write(PRUICSS_Handle pruIcssHandle,
                                     Uint8 phyaddr, Uint8 regoffset, Uint16 regval);
PROTO Uint32 bsp_pruss_mdio_phy_link_state(PRUICSS_Handle pruIcssHandle,
        Uint8 phyaddr);

PROTO void bsp_hwspinlock_init(void);
PROTO Uint32 bsp_hwspinlock_lock(int num);
PROTO void bsp_hwspinlock_unlock(int num);
PROTO void bsp_global_mutex_lock(void);
PROTO void bsp_global_mutex_unlock(void);

PROTO void bsp_set_eeprom_update_status(Uint8 status);
PROTO Uint8 bsp_get_eeprom_update_status(void);

PROTO void bsp_set_pru_firmware(Uint32 *frameProc, Uint32 frameProcLen,
                                Uint32 *hostProc, Uint32 hostProcLen);

#ifdef ENABLE_ONLINE_FIRMWARE_UPGRADE
    PROTO void bsp_start_fw_download(Uint32 password);
    PROTO void bsp_store_fw_data(Uint16 *pData, Uint16 Size);
    PROTO void bsp_boot_2_init_handler(void);
#endif
void EcatIsr(void *args);
void Sync0Isr(void *args);
void Sync1Isr(void *args);
#ifndef SUPPORT_CMDACK_POLL_MODE
    void EscCmdLowAckIsr(void *args);
#endif
#endif/*_TIESCBSP_H_ */
