/****************************************************************************** | |
* | |
* alt_bridge_manager.c - API for the Altera SoC FPGA bridge manager. | |
* | |
******************************************************************************/ | |
/****************************************************************************** | |
* | |
* Copyright 2013 Altera Corporation. All Rights Reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. 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. | |
* | |
* 3. The name of the author may not be used to endorse or promote products | |
* derived from this software without specific prior written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 AUTHOR 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 <stddef.h> | |
#include "alt_bridge_manager.h" | |
#include "alt_clock_manager.h" | |
#include "alt_fpga_manager.h" | |
#include "socal/hps.h" | |
#include "socal/socal.h" | |
#include "socal/alt_rstmgr.h" | |
/******************************************************************************/ | |
ALT_STATUS_CODE alt_bridge_init(ALT_BRIDGE_t bridge, | |
alt_bridge_fpga_is_ready_t fpga_is_ready, | |
void* user_arg) | |
{ | |
uint32_t bridge_reset_mask = 0; | |
// Validate the bridge parameter and set the appropriate bridge reset mask. | |
if (bridge == ALT_BRIDGE_LWH2F) | |
{ | |
bridge_reset_mask = ALT_RSTMGR_BRGMODRST_LWH2F_SET_MSK; | |
} | |
else if (bridge == ALT_BRIDGE_H2F) | |
{ | |
bridge_reset_mask = ALT_RSTMGR_BRGMODRST_H2F_SET_MSK; | |
} | |
else if (bridge == ALT_BRIDGE_F2H) | |
{ | |
bridge_reset_mask = ALT_RSTMGR_BRGMODRST_F2H_SET_MSK; | |
} | |
else | |
{ | |
// Invalid bridge argument specified. | |
return ALT_E_BAD_ARG; | |
} | |
// Place and hold the specified bridge in reset. | |
alt_setbits_word(ALT_RSTMGR_BRGMODRST_ADDR, bridge_reset_mask); | |
// Validate that bridge clock(s) are configured and stable. Perform the | |
// clock checks prior other validations that might depend on clocks being | |
// checked (e.g. FPGA manager dependency on ALT_CLK_L4_MP). | |
// l4_mp_clk is required for all bridges. | |
if (alt_clk_is_enabled(ALT_CLK_L4_MP) != ALT_E_TRUE) | |
{ | |
return ALT_E_BAD_CLK; | |
} | |
// Although a stable l3_main_clk is required for H2F and F2H bridges, the | |
// l3_main_clk is not gated and it runs directly from the Main PLL C1 output | |
// so if this code is executing it effectively means that this clock is stable | |
// and hence there are no meaningful validation checks that software can perform | |
// on the ALT_CLK_L3_MAIN. | |
// lws2f_axi_clk is required for LWH2F bridge and clocks all LWH2F AXI transactions. | |
// s2f_axi_clk is required for H2F bridge and clocks all H2F AXI transactions. | |
// f2s_axi_clk is required for F2H bridge and clocks all F2H AXI transactions. | |
// | |
// NOTE: All of these clocks are sourced from the FPGA and provided to the HPS. | |
// The FPGA must be configured to drive these clocks. Beyond checking that | |
// the FPGA is configured, there are no HPS control and status mechanisms | |
// available to check the operational status of these clocks. | |
// Check that FPGA is powered on. | |
ALT_FPGA_STATE_t fpga_state = alt_fpga_state_get(); | |
if (fpga_state == ALT_FPGA_STATE_POWER_OFF) | |
{ | |
return ALT_E_FPGA_PWR_OFF; | |
} | |
// Check that FPGA has been configured and is in USER mode. | |
if (fpga_state != ALT_FPGA_STATE_USER_MODE) | |
{ | |
return ALT_E_FPGA_NOT_USER_MODE; | |
} | |
// If specified, invoke user defined callback function to determine whether the | |
// FPGA is ready to commence bridge interface transactions. If no user defined | |
// callback function is specified then proceed on the assumption that the FPGA | |
// is ready to commence bridge transactions. | |
if (fpga_is_ready != NULL) | |
{ | |
ALT_STATUS_CODE fpga_ready_status = fpga_is_ready(user_arg); | |
if (fpga_ready_status != ALT_E_SUCCESS) | |
{ | |
// Return the value of the non successful status code as returned from | |
// the user defined callback function. | |
return fpga_ready_status; | |
} | |
} | |
// Release the bridge from reset. | |
alt_clrbits_word(ALT_RSTMGR_BRGMODRST_ADDR, bridge_reset_mask); | |
return ALT_E_SUCCESS; | |
} | |
/******************************************************************************/ | |
ALT_STATUS_CODE alt_bridge_uninit(ALT_BRIDGE_t bridge, | |
alt_bridge_teardown_handshake_t handshake, | |
void* user_arg) | |
{ | |
uint32_t bridge_reset_mask = 0; | |
// Validate the bridge parameter and set the appropriate bridge reset mask. | |
if (bridge == ALT_BRIDGE_LWH2F) | |
{ | |
bridge_reset_mask = ALT_RSTMGR_BRGMODRST_LWH2F_SET_MSK; | |
} | |
else if (bridge == ALT_BRIDGE_H2F) | |
{ | |
bridge_reset_mask = ALT_RSTMGR_BRGMODRST_H2F_SET_MSK; | |
} | |
else if (bridge == ALT_BRIDGE_F2H) | |
{ | |
bridge_reset_mask = ALT_RSTMGR_BRGMODRST_F2H_SET_MSK; | |
} | |
else | |
{ | |
// Invalid bridge argument specified. | |
return ALT_E_BAD_ARG; | |
} | |
if ((alt_read_word(ALT_RSTMGR_BRGMODRST_ADDR) & bridge_reset_mask) == bridge_reset_mask) | |
{ | |
// The bridge is already in reset and therefore considered uninitialized. | |
return ALT_E_SUCCESS; | |
} | |
// If specified, invoke user defined callback function to perform the tear-down | |
// handshake notification protocol with the FPGA. If no user defined callback | |
// function is specified then proceed without performing any tear-down handshake | |
// notification protocol with the FPGA. | |
if (handshake != NULL) | |
{ | |
ALT_STATUS_CODE handshake_status = handshake(user_arg); | |
if (handshake_status != ALT_E_SUCCESS) | |
{ | |
// Return the value of the non successful status code as returned from | |
// the user defined callback function. | |
return handshake_status; | |
} | |
} | |
// Place and hold the bridge in reset. | |
alt_setbits_word(ALT_RSTMGR_BRGMODRST_ADDR, bridge_reset_mask); | |
return ALT_E_SUCCESS; | |
} | |
/******************************************************************************/ | |