diff --git a/XilinxProcessorIPLib/drivers/vphy/data/vphy.mdd b/XilinxProcessorIPLib/drivers/vphy/data/vphy.mdd new file mode 100755 index 00000000..e405b816 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/data/vphy.mdd @@ -0,0 +1,41 @@ +##****************************************************************************** +## +## Copyright (C) 2015 Xilinx, Inc. All rights reserved. +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## Use of the Software is limited solely to applications: +## (a) running on a Xilinx device, or +## (b) that interact with a Xilinx device through a bus or interconnect. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +## OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. +## +## Except as contained in this notice, the name of the Xilinx shall not be used +## in advertising or otherwise to promote the sale, use or other dealings in +## this Software without prior written authorization from Xilinx. +## +##*****************************************************************************/ + +OPTION psf_version = 2.1; + +BEGIN driver vphy + OPTION supported_peripherals = (vid_phy_controller); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 1.0; + OPTION NAME = vphy; +END driver diff --git a/XilinxProcessorIPLib/drivers/vphy/data/vphy.tcl b/XilinxProcessorIPLib/drivers/vphy/data/vphy.tcl new file mode 100755 index 00000000..349ddd50 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/data/vphy.tcl @@ -0,0 +1,190 @@ +##****************************************************************************** +## +## Copyright (C) 2015 Xilinx, Inc. All rights reserved. +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## Use of the Software is limited solely to applications: +## (a) running on a Xilinx device, or +## (b) that interact with a Xilinx device through a bus or interconnect. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +## OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. +## +## Except as contained in this notice, the name of the Xilinx shall not be used +## in advertising or otherwise to promote the sale, use or other dealings in +## this Software without prior written authorization from Xilinx. +## +##*****************************************************************************/ + +proc generate {drv_handle} { + xdefine_include_file $drv_handle "xparameters.h" "XVPHY" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "Transceiver" "C_Tx_No_Of_Channels" "C_Rx_No_Of_Channels" "C_Tx_Protocol" "C_Rx_Protocol" "C_TX_REFCLK_SEL" "C_RX_REFCLK_SEL" "C_TX_PLL_SELECTION" "C_RX_PLL_SELECTION" "C_NIDRU" "C_NIDRU_REFCLK_SEL" + ::hsi::utils::define_config_file $drv_handle "xvphy_g.c" "XVphy" "DEVICE_ID" "C_BASEADDR" "TRANSCEIVER" "C_Tx_No_Of_Channels" "C_Rx_No_Of_Channels" "C_Tx_Protocol" "C_Rx_Protocol" "C_TX_REFCLK_SEL" "C_RX_REFCLK_SEL" "C_TX_PLL_SELECTION" "C_RX_PLL_SELECTION" "C_NIDRU" "C_NIDRU_REFCLK_SEL" + xdefine_canonical_xpars $drv_handle "xparameters.h" "VPHY" "DEVICE_ID" "C_BASEADDR" "Transceiver" "C_Tx_No_Of_Channels" "C_Rx_No_Of_Channels" "C_Tx_Protocol" "C_Rx_Protocol" "C_TX_REFCLK_SEL" "C_RX_REFCLK_SEL" "C_TX_PLL_SELECTION" "C_RX_PLL_SELECTION" "C_NIDRU" "C_NIDRU_REFCLK_SEL" +} + +# +# Given a list of arguments, define them all in an include file. +# Handles IP model/user parameters, as well as the special parameters NUM_INSTANCES, +# DEVICE_ID +# Will not work for a processor. +# +proc xdefine_include_file {drv_handle file_name drv_string args} { + set args [::hsi::utils::get_exact_arg_list $args] + # Open include file + set file_handle [::hsi::utils::open_include_file $file_name] + + # Get all peripherals connected to this driver + set periphs [::hsi::utils::get_common_driver_ips $drv_handle] + + # Handle special cases + set arg "NUM_INSTANCES" + set posn [lsearch -exact $args $arg] + if {$posn > -1} { + puts $file_handle "/* Definitions for driver [string toupper [common::get_property name $drv_handle]] */" + # Define NUM_INSTANCES + puts $file_handle "#define [::hsi::utils::get_driver_param_name $drv_string $arg] [llength $periphs]" + set args [lreplace $args $posn $posn] + } + + # Check if it is a driver parameter + lappend newargs + foreach arg $args { + set value [common::get_property CONFIG.$arg $drv_handle] + if {[llength $value] == 0} { + lappend newargs $arg + } else { + puts $file_handle "#define [::hsi::utils::get_driver_param_name $drv_string $arg] [common::get_property $arg $drv_handle]" + } + } + set args $newargs + + # Print all parameters for all peripherals + set device_id 0 + foreach periph $periphs { + puts $file_handle "" + puts $file_handle "/* Definitions for peripheral [string toupper [common::get_property NAME $periph]] */" + foreach arg $args { + if {[string compare -nocase "DEVICE_ID" $arg] == 0} { + set value $device_id + incr device_id + } else { + set value [common::get_property CONFIG.$arg $periph] + } + if {[llength $value] == 0} { + set value 0 + } + set value [::hsi::utils::format_addr_string $value $arg] + if {[string compare -nocase "HW_VER" $arg] == 0} { + puts $file_handle "#define [::hsi::utils::get_ip_param_name $periph $arg] \"$value\"" + } elseif {[string compare -nocase "TRANSCEIVER" $arg] == 0} { + puts $file_handle "#define [::hsi::utils::get_ip_param_name $periph $arg]_STR \"$value\"" + if {[string compare -nocase "GTXE2" "$value"] == 0} { + puts $file_handle "#define [::hsi::utils::get_ip_param_name $periph $arg] 1" + } elseif {[string compare -nocase "GTHE3" "$value"] == 0} { + puts $file_handle "#define [::hsi::utils::get_ip_param_name $periph $arg] 4" + } else { + puts $file_handle "#error \"Video PHY currently supports only GTHE3 and GTXE2; $value not supported\"" + } + } else { + puts $file_handle "#define [::hsi::utils::get_ip_param_name $periph $arg] $value" + } + } + puts $file_handle "" + } + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} + +# +# define_canonical_xpars - Used to print out canonical defines for a driver. +# Given a list of arguments, define each as a canonical constant name, using +# the driver name, in an include file. +# +proc xdefine_canonical_xpars {drv_handle file_name drv_string args} { + set args [::hsi::utils::get_exact_arg_list $args] + # Open include file + set file_handle [::hsi::utils::open_include_file $file_name] + + # Get all the peripherals connected to this driver + set periphs [::hsi::utils::get_common_driver_ips $drv_handle] + + # Get the names of all the peripherals connected to this driver + foreach periph $periphs { + set peripheral_name [string toupper [common::get_property NAME $periph]] + lappend peripherals $peripheral_name + } + + # Get possible canonical names for all the peripherals connected to this + # driver + set device_id 0 + foreach periph $periphs { + set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]] + lappend canonicals $canonical_name + + # Create a list of IDs of the peripherals whose hardware instance name + # doesn't match the canonical name. These IDs can be used later to + # generate canonical definitions + if { [lsearch $peripherals $canonical_name] < 0 } { + lappend indices $device_id + } + incr device_id + } + + set i 0 + foreach periph $periphs { + set periph_name [string toupper [common::get_property NAME $periph]] + + # Generate canonical definitions only for the peripherals whose + # canonical name is not the same as hardware instance name + if { [lsearch $canonicals $periph_name] < 0 } { + puts $file_handle "/* Canonical definitions for peripheral $periph_name */" + set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]] + + foreach arg $args { + set lvalue [::hsi::utils::get_driver_param_name $canonical_name $arg] + + # The commented out rvalue is the name of the instance-specific constant + # set rvalue [::hsi::utils::get_ip_param_name $periph $arg] + # The rvalue set below is the actual value of the parameter + set rvalue [::hsi::utils::get_param_value $periph $arg] + if {[llength $rvalue] == 0} { + set rvalue 0 + } + set rvalue [::hsi::utils::format_addr_string $rvalue $arg] + + if {[string compare -nocase "TRANSCEIVER" $arg] == 0} { + puts $file_handle "#define [string toupper $lvalue]_STR \"$rvalue\"" + if {[string compare -nocase "GTXE2" "$rvalue"] == 0} { + puts $file_handle "#define [string toupper $lvalue] 1" + } elseif {[string compare -nocase "GTHE3" "$rvalue"] == 0} { + puts $file_handle "#define [string toupper $lvalue] 4" + } else { + puts $file_handle "#error \"Video PHY currently supports only GTHE3 and GTXE2; $rvalue not supported\"" + } + } else { + puts $file_handle "#define [string toupper $lvalue] $rvalue" + } + + } + puts $file_handle "" + incr i + } + } + + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/Makefile b/XilinxProcessorIPLib/drivers/vphy/src/Makefile new file mode 100644 index 00000000..47761299 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xvphy_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling vphy" + +xvphy_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xvphy_includes + +xvphy_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy.c new file mode 100644 index 00000000..57f8bcee --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy.c @@ -0,0 +1,2312 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_hdmi.h" +#if defined(__MICROBLAZE__) +#include "microblaze_sleep.h" +#elif defined(__arm__) +#include "sleep.h" +#endif +#include "xvphy_gt.h" + +/**************************** Function Prototypes *****************************/ + +extern void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1); +static void XVphy_SelQuad(XVphy *InstancePtr, u8 QuadId); +static u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +static inline XVphy_SysClkDataSelType Pll2SysClkData(XVphy_PllType PllSelect); +static inline XVphy_SysClkOutSelType Pll2SysClkOut(XVphy_PllType PllSelect); +static u32 XVphy_DrpAccess(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u16 Addr, u16 *Val); +static u32 XVphy_PllCalculator(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + u32 PllClkInFreqHz); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function retrieves the configuration for this Video PHY instance and + * fills in the InstancePtr->Config structure. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param ConfigPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * @param EffectiveAddr is the device base address in the virtual memory + * space. If the address translation is not used, then the physical + * address is passed. + * + * @return None. + * + * @note Unexpected errors may occur if the address mapping is changed + * after this function is invoked. + * +*******************************************************************************/ +void XVphy_CfgInitialize(XVphy *InstancePtr, XVphy_Config *ConfigPtr, + u32 EffectiveAddr) +{ + u8 Sel; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(ConfigPtr != NULL); + Xil_AssertVoid(EffectiveAddr != 0x0); + + (void)memset((void *)InstancePtr, 0, sizeof(XVphy)); + InstancePtr->IsReady = 0; + + InstancePtr->Config = *ConfigPtr; + InstancePtr->Config.BaseAddr = EffectiveAddr; + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + InstancePtr->GtAdaptor = &Gtxe2Config; + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE2) { + InstancePtr->GtAdaptor = &Gthe2Config; + } + else { + InstancePtr->GtAdaptor = &Gthe3Config; + } + + const XVphy_SysClkDataSelType SysClkCfg[5][2] = { + {0, XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK}, + {1, XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK}, + {2, XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK}, + {3, XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK}, + {6, XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK}, + }; + for (Sel = 0; Sel < 5; Sel++) { + if (InstancePtr->Config.TxSysPllClkSel == SysClkCfg[Sel][0]) { + InstancePtr->Config.TxSysPllClkSel = SysClkCfg[Sel][1]; + } + if (InstancePtr->Config.RxSysPllClkSel == SysClkCfg[Sel][0]) { + InstancePtr->Config.RxSysPllClkSel = SysClkCfg[Sel][1]; + } + } + + InstancePtr->Config.TxRefClkSel += XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + InstancePtr->Config.RxRefClkSel += XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + InstancePtr->Config.DruRefClkSel += XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +} + +/*****************************************************************************/ +/** +* This function will initialize the PLL selection for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param QpllRefClkSel is the QPLL reference clock selection for the +* quad. +* @param CpllRefClkSel is the CPLL reference clock selection for the +* quad. +* @param TxPllSelect is the reference clock selection for the quad's +* TX PLL dividers. +* @param RxPllSelect is the reference clock selection for the quad's +* RX PLL dividers. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_PllInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllRefClkSelType CpllRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect) +{ + XVphy_SelQuad(InstancePtr, QuadId); + + /* Set configuration in software. */ + XVphy_CfgPllRefClkSel(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMNA, + QpllRefClkSel); + XVphy_CfgPllRefClkSel(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + CpllRefClkSel); + XVphy_CfgSysClkDataSel(InstancePtr, QuadId, XVPHY_DIR_TX, + Pll2SysClkData(TxPllSelect)); + XVphy_CfgSysClkDataSel(InstancePtr, QuadId, XVPHY_DIR_RX, + Pll2SysClkData(RxPllSelect)); + XVphy_CfgSysClkOutSel(InstancePtr, QuadId, XVPHY_DIR_TX, + Pll2SysClkOut(TxPllSelect)); + XVphy_CfgSysClkOutSel(InstancePtr, QuadId, XVPHY_DIR_RX, + Pll2SysClkOut(RxPllSelect)); + + /* Write configuration to hardware at once. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, QuadId); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/* +* This function installs a custom delay/sleep function to be used by the XVphy +* driver. +* +* @param InstancePtr is a pointer to the XVphy instance. +* @param CallbackFunc is the address to the callback function. +* @param CallbackRef is the user data item (microseconds to delay) that +* will be passed to the custom sleep/delay function when it is +* invoked. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void XVphy_SetUserTimerHandler(XVphy *InstancePtr, + XVphy_TimerHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->UserTimerWaitUs = CallbackFunc; + InstancePtr->UserTimerPtr = CallbackRef; +} + +/******************************************************************************/ +/** +* This function is the delay/sleep function for the XVphy driver. For the Zynq +* family, there exists native sleep functionality. For MicroBlaze however, +* there does not exist such functionality. In the MicroBlaze case, the default +* method for delaying is to use a predetermined amount of loop iterations. This +* method is prone to inaccuracy and dependent on system configuration; for +* greater accuracy, the user may supply their own delay/sleep handler, pointed +* to by InstancePtr->UserTimerWaitUs, which may have better accuracy if a +* hardware timer is used. +* +* @param InstancePtr is a pointer to the XVphy instance. +* @param MicroSeconds is the number of microseconds to delay/sleep for. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void XVphy_WaitUs(XVphy *InstancePtr, u32 MicroSeconds) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (MicroSeconds == 0) { + return; + } + +#if defined(__MICROBLAZE__) + if (InstancePtr->UserTimerWaitUs != NULL) { + /* Use the timer handler specified by the user for better + * accuracy. */ + InstancePtr->UserTimerWaitUs(InstancePtr, MicroSeconds); + } + else { + /* MicroBlaze sleep only has millisecond accuracy. Round up. */ + u32 MilliSeconds = (MicroSeconds + 999) / 1000; + MB_Sleep(MilliSeconds); + } +#elif defined(__arm__) + /* Wait the requested amount of time. */ + usleep(MicroSeconds); +#endif +} + +/*****************************************************************************/ +/** +* This function will initialize the clocking for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + + Status = XVphy_ClkCalcParams(InstancePtr, QuadId, ChId, Dir, 0); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XVphy_ClkReconfig(InstancePtr, QuadId, ChId); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XVphy_OutDivReconfig(InstancePtr, QuadId, ChId, Dir); + if (Status != XST_SUCCESS) { + return Status; + } + if ((Dir == XVPHY_DIR_RX) && XVphy_IsBonded(InstancePtr, 0, ChId)) { + XVphy_OutDivReconfig(InstancePtr, 0, ChId, XVPHY_DIR_TX); + } + + Status = XVphy_DirReconfig(InstancePtr, QuadId, ChId, XVPHY_DIR_RX); + + return Status; +} + +/*****************************************************************************/ +/** +* This function will obtian the IP version. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The IP version of the Video PHY core. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_GetVersion(XVphy *InstancePtr) +{ + return XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_VERSION_REG); +} + +/*****************************************************************************/ +/** +* This function will enable or disable the LPM logic in the Video PHY core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Enable will enable (if 1) or disable (if 0) the LPM logic. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_SetRxLpm(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable) +{ + u32 RegVal; + u32 MaskVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_RX_EQ_CDR_REG); + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_RX_CONTROL_RXLPMEN_ALL_MASK; + } + else { + MaskVal = XVPHY_RX_CONTROL_RXLPMEN_MASK(ChId); + } + + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_RX_EQ_CDR_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function will set the TX voltage swing value for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Vs is the voltage swing value to write. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_SetTxVoltageSwing(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Vs) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + if ((ChId == XVPHY_CHANNEL_ID_CH1) || (ChId == XVPHY_CHANNEL_ID_CH2)) { + RegOffset = XVPHY_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XVPHY_TX_DRIVER_CH34_REG; + } + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XVPHY_TX_DRIVER_TXDIFFCTRL_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Vs << XVPHY_TX_DRIVER_TXDIFFCTRL_SHIFT(ChId)); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will set the TX pre-emphasis value for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Pe is the pre-emphasis value to write. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_SetTxPreEmphasis(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Pe) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + if ((ChId == XVPHY_CHANNEL_ID_CH1) || (ChId == XVPHY_CHANNEL_ID_CH2)) { + RegOffset = XVPHY_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XVPHY_TX_DRIVER_CH34_REG; + } + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XVPHY_TX_DRIVER_TXPRECURSOR_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Pe << XVPHY_TX_DRIVER_TXPRECURSOR_SHIFT(ChId)); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function writes the current software configuration for the reference +* clock selections to hardware for the specified quad on all channels. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WriteCfgRefClkSelReg(XVphy *InstancePtr, u8 QuadId) +{ + u32 RegVal = 0; + XVphy_Channel *ChPtr; + XVphy_GtType GtType = InstancePtr->Config.XcvrType; + + XVphy_SelQuad(InstancePtr, QuadId); + + /* Point to the first channel since settings apply to all channels. */ + ChPtr = &InstancePtr->Quads[QuadId].Ch1; + + /* PllRefClkSel. */ + /* - QPLL0. */ + RegVal &= ~XVPHY_REF_CLK_SEL_QPLL0_MASK; + RegVal = InstancePtr->Quads[QuadId].Cmn0.PllRefClkSel; + /* - CPLL. */ + RegVal &= ~XVPHY_REF_CLK_SEL_CPLL_MASK; + RegVal |= (ChPtr->CpllRefClkSel << XVPHY_REF_CLK_SEL_CPLL_SHIFT); + if (GtType == XVPHY_GT_TYPE_GTHE3) { + /* - QPLL1. */ + RegVal &= ~XVPHY_REF_CLK_SEL_QPLL1_MASK; + RegVal |= (InstancePtr->Quads[QuadId].Cmn1.PllRefClkSel << + XVPHY_REF_CLK_SEL_QPLL1_SHIFT); + } + + /* SysClkDataSel. PLLCLKSEL */ + RegVal &= ~XVPHY_REF_CLK_SEL_SYSCLKSEL_MASK; + /* - TXSYSCLKSEL[0]. TXPLLCLKSEL*/ + RegVal |= (ChPtr->TxDataRefClkSel << + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(GtType); + /* - RXSYSCLKSEL[0]. RXPLLCLKSEL*/ + RegVal |= (ChPtr->RxDataRefClkSel << + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(GtType); + + /* SysClkOutSel. */ + /* - TXSYSCLKSEL[1]. */ + RegVal |= (ChPtr->TxOutRefClkSel << + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(GtType); + /* - RXSYSCLKSEL[1]. */ + RegVal |= (ChPtr->RxOutRefClkSel << + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(GtType); + + /* Write to hardware. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_REF_CLK_SEL_REG, + RegVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Configure the channel's line rate. This is a software only configuration and +* this value is used in the PLL calculator. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param LineRate is the line rate to configure software. +* +* @return +* - XST_SUCCESS if the reference clock type is valid. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_CfgLineRate(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u64 LineRateHz) +{ + u8 Id; + u8 Id0; + u8 Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].LineRateHz = + LineRateHz; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Configure the quad's reference clock frequency. This is a software only +* configuration and this value is used in the PLL calculator. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param RefClkType is the reference clock type to operate on. +* @param FreqHz is the reference clock frequency to configure software. +* +* @return +* - XST_SUCCESS if the reference clock type is valid. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_CfgQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType, u32 FreqHz) +{ + u8 RefClkIndex = RefClkType - XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + + if (RefClkType > XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK) { + return XST_FAILURE; + } + InstancePtr->Quads[QuadId].RefClkHz[RefClkIndex] = FreqHz; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Configure the PLL reference clock selection for the specified channel(s). +* This is applied to both direction to the software configuration only. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param SysClkDataSel is the reference clock selection to configure. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_CfgPllRefClkSel(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType RefClkSel) +{ + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].PllRefClkSel = + RefClkSel; + } +} + +/*****************************************************************************/ +/** +* Configure the SYSCLKDATA reference clock selection for the direction. Same +* configuration applies to all channels in the quad. This is applied to the +* software configuration only. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param SysClkDataSel is the reference clock selection to configure. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_CfgSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkDataSelType SysClkDataSel) +{ + XVphy_Channel *ChPtr; + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + /* Select in software - same for all channels. */ + for (Id = Id0; Id <= Id1; Id++) { + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]; + ChPtr->DataRefClkSel[Dir] = SysClkDataSel; + } +} + +/*****************************************************************************/ +/** +* Configure the SYSCLKOUT reference clock selection for the direction. Same +* configuration applies to all channels in the quad. This is applied to the +* software configuration only. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param SysClkOutSel is the reference clock selection to configure. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_CfgSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkOutSelType SysClkOutSel) +{ + XVphy_Channel *ChPtr; + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + /* Select in software - same for all channels. */ + for (Id = Id0; Id <= Id1; Id++) { + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]; + ChPtr->OutRefClkSel[Dir] = SysClkOutSel; + } +} + +/*****************************************************************************/ +/** +* Obtain the channel's PLL reference clock selection. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param ChId is the channel ID which to operate on. +* +* @return The PLL type being used by the channel. +* +* @note None. +* +******************************************************************************/ +XVphy_PllType XVphy_GetPllType(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId) +{ + XVphy_SysClkDataSelType SysClkDataSel; + XVphy_SysClkOutSelType SysClkOutSel; + XVphy_PllType PllType; + + SysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, Dir, ChId); + SysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, Dir, ChId); + + /* The sysclk data and output reference clocks should match. */ + if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK)) { + PllType = XVPHY_PLL_TYPE_CPLL; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL0; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL1; + } + else { + PllType = XVPHY_PLL_TYPE_UNKNOWN; + } + + return PllType; +} + +/*****************************************************************************/ +/** +* Obtain the current reference clock frequency for the quad based on the +* reference clock type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param RefClkType is the type to obtain the clock selection for. +* +* @return The current reference clock frequency for the quad for the +* specified type selection. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_GetQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType) +{ + u32 FreqHz; + + u8 RefClkIndex = RefClkType - XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + + FreqHz = (RefClkType > XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK) ? 0 : + InstancePtr->Quads[QuadId].RefClkHz[RefClkIndex]; + + return FreqHz; +} + +/*****************************************************************************/ +/** +* Obtain the current PLL reference clock selection. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* +* @return The current PLL reference clock selection. +* +* @note None. +* +******************************************************************************/ +XVphy_PllRefClkSelType XVphy_GetPllRefClkSel(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + XVphy_PllRefClkSelType Sel; + u32 RegVal; + + Xil_AssertNonvoid((XVPHY_CHANNEL_ID_CH1 <= ChId) && + (ChId <= XVPHY_CHANNEL_ID_CMN1)); + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_REF_CLK_SEL_REG); + + /* Synchronize software configuration to hardware. */ + Sel = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].PllRefClkSel; + /* Synchronize software configuration to hardware. */ + if (ChId == XVPHY_CHANNEL_ID_CMN0) { + Sel = RegVal & XVPHY_REF_CLK_SEL_QPLL0_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CMN1) { + Sel = RegVal & XVPHY_REF_CLK_SEL_QPLL1_MASK; + Sel >>= XVPHY_REF_CLK_SEL_QPLL1_SHIFT; + } + else { + Sel = RegVal & XVPHY_REF_CLK_SEL_CPLL_MASK; + Sel >>= XVPHY_REF_CLK_SEL_CPLL_SHIFT; + } + + return Sel; +} + +/*****************************************************************************/ +/** +* Obtain the current [RT]XSYSCLKSEL[0] configuration. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param ChId is the channel ID which to operate on. +* +* @return The current [RT]XSYSCLKSEL[0] selection. +* +* @note None. +* +******************************************************************************/ +XVphy_SysClkDataSelType XVphy_GetSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId) +{ + XVphy_SysClkDataSelType Sel; + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_REF_CLK_SEL_REG); + + Sel = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + DataRefClkSel[Dir]; + if (Dir == XVPHY_DIR_TX) { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT( + InstancePtr->Config.XcvrType); + } + else { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT( + InstancePtr->Config.XcvrType); + } + + return Sel; +} + +/*****************************************************************************/ +/** +* Obtain the current [RT]XSYSCLKSEL[1] configuration. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param ChId is the channel ID which to operate on. +* +* @return The current [RT]XSYSCLKSEL[1] selection. +* +* @note None. +* +******************************************************************************/ +XVphy_SysClkOutSelType XVphy_GetSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId) +{ + XVphy_SysClkOutSelType Sel; + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_REF_CLK_SEL_REG); + + Sel = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + OutRefClkSel[Dir]; + if (Dir == XVPHY_DIR_TX) { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT( + InstancePtr->Config.XcvrType); + } + else { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT( + InstancePtr->Config.XcvrType); + } + + return Sel; +} + +/*****************************************************************************/ +/** +* This function will wait for a PMA reset done on the specified channel(s) or +* time out. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the PMA reset has finalized. +* - XST_FAILURE otherwise; waiting for the reset done timed out. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WaitForPmaResetDone(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + u8 Retry = 0; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_STATUS_REG; + } + else { + RegOffset = XVPHY_RX_INIT_STATUS_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_STATUS_PMARESETDONE_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(ChId); + } + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + if (!(RegVal & MaskVal)){ + XVphy_WaitUs(InstancePtr, 1000); + Retry++; + } + } while ((!(RegVal & MaskVal)) && (Retry < 15)); + + if (Retry == 15){ + return XST_FAILURE; + } + else { + return XST_SUCCESS; + } +} + +/*****************************************************************************/ +/** +* This function will wait for a reset done on the specified channel(s) or time +* out. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the reset has finalized. +* - XST_FAILURE otherwise; waiting for the reset done timed out. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WaitForResetDone(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + u8 Retry = 0; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_STATUS_REG; + } + else { + RegOffset = XVPHY_RX_INIT_STATUS_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_STATUS_RESETDONE_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(ChId); + } + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + if (!(RegVal & MaskVal)){ + XVphy_WaitUs(InstancePtr, 1000); + Retry++; + } + } while ((!(RegVal & MaskVal)) && (Retry < 15)); + + if (Retry == 15){ + return XST_FAILURE; + } + else { + return XST_SUCCESS; + } +} + +/*****************************************************************************/ +/** +* This function will wait for a PLL lock on the specified channel(s) or time +* out. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* +* @return +* - XST_SUCCESS if the PLL(s) have locked. +* - XST_FAILURE otherwise; waiting for the lock timed out. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WaitForPllLock(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 RegVal; + u32 MaskVal; + u8 Retry = 0; + + if (ChId == XVPHY_CHANNEL_ID_CMN0) { + MaskVal = XVPHY_PLL_LOCK_STATUS_QPLL0_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CMN1) { + MaskVal = XVPHY_PLL_LOCK_STATUS_QPLL1_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CMNA) { + MaskVal = XVPHY_PLL_LOCK_STATUS_QPLL0_MASK | + XVPHY_PLL_LOCK_STATUS_QPLL1_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_ALL_MASK; + } + else { + MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_MASK(ChId); + } + + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_PLL_LOCK_STATUS_REG); + if (!(RegVal & MaskVal)){ + XVphy_WaitUs(InstancePtr, 1000); + Retry++; + } + } while ((!(RegVal & MaskVal)) && (Retry < 15)); + + if (Retry == 15){ + return XST_FAILURE; + } + else { + return XST_SUCCESS; + } +} + +/*****************************************************************************/ +/** +* This function will reset the GT's PLL logic. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ResetGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_REG; + } + else { + RegOffset = XVPHY_RX_INIT_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_PLLGTRESET_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_PLLGTRESET_MASK(ChId); + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will reset the GT's TX/RX logic. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ResetGtTxRx(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_REG; + } + else { + RegOffset = XVPHY_RX_INIT_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_GTRESET_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_GTRESET_MASK(ChId); + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will reset and enable the Video PHY's user core logic. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_GtUserRdyEnable(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_REG; + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TX_INIT_USERRDY_ALL_MASK; + } + else { + MaskVal = XVPHY_TX_INIT_USERRDY_MASK(ChId); + } + } + else { + RegOffset = XVPHY_RX_INIT_REG; + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_RX_INIT_USERRDY_ALL_MASK; + } + else { + MaskVal = XVPHY_RX_INIT_USERRDY_MASK(ChId); + } + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will reset the specified GT quad. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if a valid PLL was specified. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ResetGt(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir) +{ + XVphy_SysClkDataSelType SysClkDataSel; + XVphy_SysClkOutSelType SysClkOutSel; + XVphy_PllType PllType; + + /* All channels are using the same settings. */ + SysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, Dir, + XVPHY_CHANNEL_ID_CH1); + SysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, Dir, + XVPHY_CHANNEL_ID_CH1); + + /* The sysclk data and output reference clocks should match. */ + if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK)) { + PllType = XVPHY_PLL_TYPE_CPLL; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL0; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL1; + } + else { + return XST_FAILURE; + } + + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_DIR_RX : XVPHY_DIR_TX, 0); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will initiate a write DRP transaction. It is a wrapper around +* XVphy_DrpAccess. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID on which to direct the DRP access. +* @param Dir is an indicator for write (TX) or read (RX). +* @param Addr is the DRP address to issue the DRP access to. +* @param Val is the value to write to the DRP address. +* +* @return +* - XST_SUCCESS if the DRP access was successful. +* - XST_FAILURE otherwise, if the busy bit did not go low, or if +* the ready bit did not go high. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr, u16 Val) +{ + return XVphy_DrpAccess(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX, /* Write. */ + Addr, &Val); +} + +/*****************************************************************************/ +/** +* This function will initiate a read DRP transaction. It is a wrapper around +* XVphy_DrpAccess. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID on which to direct the DRP access. +* @param Dir is an indicator for write (TX) or read (RX). +* @param Addr is the DRP address to issue the DRP access to. +* +* @return +* - XST_SUCCESS if the DRP access was successful. +* - XST_FAILURE otherwise, if the busy bit did not go low, or if +* the ready bit did not go high. +* +* @note None. +* +******************************************************************************/ +u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u16 Addr) +{ + u32 Status; + u16 Val; + + Status = XVphy_DrpAccess(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX, /* Read. */ + Addr, &Val); + + return (Status == XST_SUCCESS) ? Val : 0; +} + +/*****************************************************************************/ +/** +* This function will reset the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmReset(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + XVphy_SelQuad(InstancePtr, QuadId); + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Assert reset. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_RST_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~XVPHY_MMCM_USRCLK_CTRL_RST_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will power down the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the power down if set +* to 1. If set to 0: power down, then power back up. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmPowerDown(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + XVphy_SelQuad(InstancePtr, QuadId); + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Power down. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Hold) { + /* Power up. */ + RegVal &= ~XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will start the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmStart(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir) +{ + u32 Status; + u8 Retry; + + /* Enable MMCM. */ + XVphy_MmcmPowerDown(InstancePtr, QuadId, Dir, FALSE); + + XVphy_WaitUs(InstancePtr, 10000); + + /* Toggle MMCM reset. */ + XVphy_MmcmReset(InstancePtr, QuadId, Dir, FALSE); + + XVphy_WaitUs(InstancePtr, 10000); + + /* Configure MMCM. */ + Retry = 0; + do { + XVphy_WaitUs(InstancePtr, 10000); + Status = XVphy_MmcmWriteParameters(InstancePtr, QuadId, Dir); + Retry++; + } while ((Status != XST_SUCCESS) && (Retry < 3)); + + XVphy_WaitUs(InstancePtr, 10000); + + /* Toggle MMCM reset. */ + XVphy_MmcmReset(InstancePtr, QuadId, Dir, FALSE); +} + +/*****************************************************************************/ +/** +* This function resets the BUFG_GT peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX +* @param Reset specifies TRUE/FALSE value to either assert or deassert +* reset on the BUFG_GT, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_BufgGtReset(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Reset) +{ + u32 RegVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_BUFGGT_TXUSRCLK_REG; + } + else { + RegOffset = XVPHY_BUFGGT_RXUSRCLK_REG; + } + + /* Read BUFG_GT register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Write new value to BUFG_GT register. */ + if (Reset) { + RegVal |= XVPHY_BUFGGT_XXUSRCLK_CLR_MASK; + } + else { + RegVal &= ~XVPHY_BUFGGT_XXUSRCLK_CLR_MASK; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function obtains the divider value of the BUFG_GT peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX +* @param Div 3-bit divider value +* +* @return None. +* +******************************************************************************/ +void XVphy_SetBufgGtDiv(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Div) +{ + u32 RegVal; + u32 RegOffset; + u8 Divider = Div; + + if (Divider == 0) { + Divider = 1; + } + else { + Divider = Divider - 1; + } + + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_BUFGGT_TXUSRCLK_REG; + } + else { + RegOffset = XVPHY_BUFGGT_RXUSRCLK_REG; + } + + /* Read BUFG_GT register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + RegVal &= ~XVPHY_BUFGGT_XXUSRCLK_DIV_MASK; + + /* Shift divider value to correct position. */ + Divider <<= XVPHY_BUFGGT_XXUSRCLK_DIV_SHIFT; + Divider &= XVPHY_BUFGGT_XXUSRCLK_DIV_MASK; + RegVal |= Divider; + + /* Write new value to BUFG_GT ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function enables the TX or RX IBUFDS peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the IBUFDS, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_IBufDsEnable(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Enable) +{ + XVphy_PllRefClkSelType *TypePtr; + u32 RegVal; + u32 MaskVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_IBUFDS_GTXX_CTRL_REG); + + if (Dir == XVPHY_DIR_TX) { + TypePtr = &InstancePtr->Config.TxRefClkSel; + } + else { + TypePtr = &InstancePtr->Config.RxRefClkSel; + } + + if (*TypePtr == XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0) { + MaskVal = XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK; + } + else if (*TypePtr == XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1) { + MaskVal = XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK; + } + + if (Enable) { + RegVal &= ~MaskVal; + } + else { + RegVal |= MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_IBUFDS_GTXX_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function enables the TX or RX CLKOUT1 OBUFTDS peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the OBUFTDS, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_Clkout1OBufTdsEnable(XVphy *InstancePtr, XVphy_DirectionType Dir, + u8 Enable) +{ + u32 RegVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_MISC_TXUSRCLK_REG; + } + else { + RegOffset = XVPHY_MISC_RXUSRCLK_REG; + } + + /* Read XXUSRCLK MISC register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Write new value to XXUSRCLK MISC register. */ + if (Enable) { + RegVal |= XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK; + } + else { + RegVal &= ~XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will set 8b10b encoding for the specified GT PLL. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Enable is an indicator to enable/disable 8b10b encoding. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +void XVphy_Set8b10b(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable) +{ + u32 RegOffset; + u32 MaskVal; + u32 RegVal; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_CONTROL_REG; + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TX_CONTROL_TX8B10BEN_ALL_MASK; + } + else { + MaskVal = XVPHY_TX_CONTROL_TX8B10BEN_MASK(ChId); + } + } + else { + RegOffset = XVPHY_RX_CONTROL_REG; + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_RX_CONTROL_RX8B10BEN_ALL_MASK; + } + else { + MaskVal = XVPHY_RX_CONTROL_RX8B10BEN_MASK(ChId); + } + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will power down the specified GT PLL. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to power down the PLL for. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the power down if set +* to 1. If set to 0: power down, then power back up. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_PowerDownGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Hold) +{ + u32 MaskVal = 0; + u32 RegVal; + u8 Id, Id0, Id1; + + if (XVPHY_ISCH(ChId)) { + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + } + else { + /* When powering down a QPLL, power down for all channels. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + } + for (Id = Id0; Id <= Id1; Id++) { + if (ChId == XVPHY_CHANNEL_ID_CMN0) { + MaskVal |= XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Id); + } + else if (ChId == XVPHY_CHANNEL_ID_CMN1) { + MaskVal |= XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Id); + } + else if (ChId == XVPHY_CHANNEL_ID_CMNA) { + MaskVal |= XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Id) | + XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Id); + } + else { + MaskVal |= XVPHY_POWERDOWN_CONTROL_CPLLPD_MASK(Id); + } + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_POWERDOWN_CONTROL_REG); + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_POWERDOWN_CONTROL_REG, RegVal); + + if (!Hold) { + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_POWERDOWN_CONTROL_REG, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function returns true when the RX and TX are bonded and are running +* from the same (RX) reference clock. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return TRUE if the RX and TX are using the same PLL, FALSE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_IsBonded(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_SysClkDataSelType RxSysClkDataSel; + XVphy_SysClkOutSelType RxSysClkOutSel; + XVphy_SysClkDataSelType TxSysClkDataSel; + XVphy_SysClkOutSelType TxSysClkOutSel; + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + ChId = XVPHY_CHANNEL_ID_CH1; + } + + RxSysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, + XVPHY_DIR_RX, ChId); + RxSysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, + XVPHY_DIR_RX, ChId); + TxSysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, + XVPHY_DIR_TX, ChId); + TxSysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, + XVPHY_DIR_TX, ChId); + + if ((RxSysClkDataSel == TxSysClkDataSel) && + (RxSysClkOutSel == TxSysClkOutSel)) { + return TRUE; + } + + return FALSE; +} + +/*****************************************************************************/ +/** +* This function will try to find the necessary PLL divisor values to produce +* the configured line rate given the specified PLL input frequency. This will +* be done for all channels specified by ChId. +* This function is a wrapper for XVphy_PllCalculator. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to calculate the PLL values for. +* @param ChId is the channel ID to calculate the PLL values for. +* @param Dir is an indicator for TX or RX. +* @param PllClkInFreqHz is the PLL input frequency on which to base the +* calculations on. A value of 0 indicates to use the currently +* configured quad PLL reference clock. A non-zero value indicates +* to ignore what is currently configured in SW, and use a custom +* frequency instead. +* +* @return +* - XST_SUCCESS if valid PLL values were found to satisfy the +* constraints. +* - XST_FAILURE otherwise. +* +* @note If successful, the channel's PllParams structure will be +* modified with the valid PLL parameters. +* +******************************************************************************/ +u32 XVphy_ClkCalcParams(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u32 PllClkInFreqHz) +{ + u32 Status = XST_SUCCESS; + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + Status = XVphy_PllCalculator(InstancePtr, QuadId, Id, Dir, + PllClkInFreqHz); + if (Status != XST_SUCCESS) { + return Status; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the current output divider configuration over DRP. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID for which to write the settings for. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_OutDivReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + u8 Id; + u8 Id0; + u8 Id1; + + if (!XVPHY_ISCH(ChId)) { + ChId = XVPHY_CHANNEL_ID_CHA; + } + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_RECONFIG, 0); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + Status = XVphy_OutDivChReconfig(InstancePtr, QuadId, Id, Dir); + if (Status != XST_SUCCESS) { + break; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the current RX/TX configuration over DRP. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID for which to write the settings for. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_DirReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status = XST_SUCCESS; + u8 Id, Id0, Id1; + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE2) && + (Dir == XVPHY_DIR_TX)) { + return XST_SUCCESS; + } + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_RECONFIG, 0); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (Dir == XVPHY_DIR_TX) { + Status = XVphy_TxPllRefClkDiv1Reconfig(InstancePtr, + QuadId, Id); + } + else { + Status = XVphy_RxChReconfig(InstancePtr, QuadId, Id); + } + if (Status != XST_SUCCESS) { + break; + } + } + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_RECONFIG, 1); + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the current clocking settings for each channel to +* hardware based on the configuration stored in the driver's instance. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID for which to write the settings for. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 Status; + u8 Id; + u8 Id0; + u8 Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (XVPHY_ISCH(Id)) { + Status = XVphy_ClkChReconfig(InstancePtr, QuadId, Id); + } + else if (XVPHY_ISCMN(ChId)) { + Status = XVphy_ClkCmnReconfig(InstancePtr, QuadId, Id); + } + if (Status != XST_SUCCESS) { + return Status; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the channel IDs to correspond with the supplied +* channel ID based on the protocol. HDMI uses 3 channels; DP uses 4. This ID +* translation is done to allow other functions to operate iteratively over +* multiple channels. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID used to determine the indices. +* @param Id0 is a pointer to the start channel ID to set. +* @param Id1 is a pointer to the end channel ID to set. +* +* @return None. +* +* @note The contents of Id0 and Id1 will be set according to ChId. +* +******************************************************************************/ +void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1) +{ + if (ChId == XVPHY_CHANNEL_ID_CHA) { + *Id0 = XVPHY_CHANNEL_ID_CH1; + if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + *Id1 = XVPHY_CHANNEL_ID_CH3; + } + else { + *Id1 = XVPHY_CHANNEL_ID_CH4; + } + } + else if (ChId == XVPHY_CHANNEL_ID_CMNA) { + *Id0 = XVPHY_CHANNEL_ID_CMN0; + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + *Id1 = XVPHY_CHANNEL_ID_CMN1; + } + else { + *Id1 = XVPHY_CHANNEL_ID_CMN0; + } + } + else { + *Id0 = *Id1 = ChId; + } +} + +/*****************************************************************************/ +/** +* This function will set the Video PHY IP to operate on the specified GT quad. +* All Video PHY future accesses will operate on the specified quad until this +* a different quad is set. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XVphy_SelQuad(XVphy *InstancePtr, u8 QuadId) +{ + u32 RegVal; + + RegVal = (QuadId << XVPHY_BANK_SELECT_RX_SHIFT) | QuadId; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_BANK_SELECT_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function will write the mixed-mode clock manager (MMCM) values currently +* stored in the driver's instance structure to hardware . +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the MMCM write was successful. +* - XST_FAILURE otherwise, if the configuration success bit did +* not go low. +* +* @note None. +* +******************************************************************************/ +static u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir) +{ + u32 RegOffsetCtrl; + u32 RegOffsetClk; + u32 RegVal; + XVphy_Mmcm *MmcmParams; + u8 Retry; + + XVphy_SelQuad(InstancePtr, QuadId); + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + RegOffsetClk = XVPHY_MMCM_TXUSRCLK_REG1; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + RegOffsetClk = XVPHY_MMCM_RXUSRCLK_REG1; + } + MmcmParams = &InstancePtr->Quads[QuadId].Mmcm[Dir]; + + /* Check Parameters if has been Initialized */ + if (!MmcmParams->DivClkDivide && !MmcmParams->ClkFbOutMult && + !MmcmParams->ClkFbOutFrac && !MmcmParams->ClkOut0Frac && + !MmcmParams->ClkOut0Div && !MmcmParams->ClkOut1Div && + !MmcmParams->ClkOut2Div) { + return XST_FAILURE; + } + + /* MMCM_[TX|RX]USRCLK_REG1 */ + RegVal = MmcmParams->DivClkDivide; + RegVal |= (MmcmParams->ClkFbOutMult << + XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_SHIFT); + RegVal |= (MmcmParams->ClkFbOutFrac << + XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_SHIFT); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* MMCM_[TX|RX]USRCLK_REG2 */ + RegOffsetClk += 4; + RegVal = MmcmParams->ClkOut0Div; + RegVal |= (MmcmParams->ClkOut0Frac << + XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_SHIFT); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* MMCM_[TX|RX]USRCLK_REG3 */ + RegOffsetClk += 4; + RegVal = MmcmParams->ClkOut1Div; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* MMCM_[TX|RX]USRCLK_REG4 */ + RegOffsetClk += 4; + RegVal = MmcmParams->ClkOut2Div; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* Update the MMCM. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_CFG_NEW_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + /* Wait until the MMCM indicates configuration has succeeded. */ + Retry = 0; + do { + XVphy_WaitUs(InstancePtr, 1000); + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetCtrl); + if (Retry > 15) { + return XST_FAILURE; + } + Retry++; + } while (!(RegVal & XVPHY_MMCM_USRCLK_CTRL_CFG_SUCCESS_MASK)); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will translate from XVphy_PllType to XVphy_SysClkDataSelType. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The reference clock type based on the PLL selection. +* +* @note None. +* +******************************************************************************/ +static inline XVphy_SysClkDataSelType Pll2SysClkData(XVphy_PllType PllSelect) +{ + return (PllSelect == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL) ? + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL0) ? + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK : + XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; +} + +/*****************************************************************************/ +/** +* This function will translate from XVphy_PllType to XVphy_SysClkOutSelType. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The reference clock type based on the PLL selection. +* +* @note None. +* +******************************************************************************/ +static inline XVphy_SysClkOutSelType Pll2SysClkOut(XVphy_PllType PllSelect) +{ + return (PllSelect == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL) ? + XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL0) ? + XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK : + XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; +} + +/*****************************************************************************/ +/** +* This function will initiate a DRP transaction (either read or write). +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID on which to direct the DRP access. +* @param Dir is an indicator for write (TX) or read (RX). +* @param Addr is the DRP address to issue the DRP access to. +* @param Val is a pointer to the data value. In write mode, this pointer +* will hold the value to write. In read mode, this pointer will +* be populated with the read value. +* +* @return +* - XST_SUCCESS if the DRP access was successful. +* - XST_FAILURE otherwise, if the busy bit did not go low, or if +* the ready bit did not go high. +* +* @note In read mode (Dir == XVPHY_DIR_RX), the data pointed to by Val +* will be populated with the u16 value that was read._ +* +******************************************************************************/ +static u32 XVphy_DrpAccess(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u16 Addr, u16 *Val) +{ + u32 RegOffsetCtrl; + u32 RegOffsetSts; + u32 RegVal; + u8 Retry; + + XVphy_SelQuad(InstancePtr, QuadId); + + /* Determine which DRP registers to use based on channel. */ + if (XVPHY_ISCMN(ChId)) { + RegOffsetCtrl = XVPHY_DRP_CONTROL_COMMON_REG; + RegOffsetSts = XVPHY_DRP_STATUS_COMMON_REG; + } + else { + RegOffsetCtrl = XVPHY_DRP_CONTROL_CH1_REG + + (4 * XVPHY_CH2IDX(ChId)); + RegOffsetSts = XVPHY_DRP_STATUS_CH1_REG + + (4 * (XVPHY_CH2IDX(ChId))); + } + + /* Wait until the DRP status indicates that it is not busy.*/ + Retry = 0; + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetSts); + if (Retry > 15) { + return XST_FAILURE; + } + Retry++; + } while (RegVal & XVPHY_DRP_STATUS_DRPBUSY_MASK); + + /* Write the command to the channel's DRP. */ + RegVal = (Addr & XVPHY_DRP_CONTROL_DRPADDR_MASK); + RegVal |= XVPHY_DRP_CONTROL_DRPEN_MASK; + if (Dir == XVPHY_DIR_TX) { + /* Enable write. */ + RegVal |= XVPHY_DRP_CONTROL_DRPWE_MASK; + RegVal |= ((*Val << XVPHY_DRP_CONTROL_DRPDI_SHIFT) & + XVPHY_DRP_CONTROL_DRPDI_MASK); + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + /* Wait until the DRP status indicates ready.*/ + Retry = 0; + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetSts); + if (Retry > 15) { + return XST_FAILURE; + } + Retry++; + } while (!(RegVal & XVPHY_DRP_STATUS_DRPRDY_MASK)); + + if (Dir == XVPHY_DIR_RX) { + /* Mask non-data out for read. */ + RegVal &= XVPHY_DRP_STATUS_DRPO_MASK; + /* Populate Val with read contents. */ + *Val = RegVal; + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will try to find the necessary PLL divisor values to produce +* the configured line rate given the specified PLL input frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to calculate the PLL values for. +* @param ChId is the channel ID to calculate the PLL values for. +* @param Dir is an indicator for TX or RX. +* @param PllClkInFreqHz is the PLL input frequency on which to base the +* calculations on. A value of 0 indicates to use the currently +* configured quad PLL reference clock. A non-zero value indicates +* to ignore what is currently configured in SW, and use a custom +* frequency instead. +* +* @return +* - XST_SUCCESS if valid PLL values were found to satisfy the +* constraints. +* - XST_FAILURE otherwise. +* +* @note If successful, the channel's PllParams structure will be +* modified with the valid PLL parameters. +* +******************************************************************************/ +static u32 XVphy_PllCalculator(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + u32 PllClkInFreqHz) +{ + u32 Status; + u64 PllClkOutFreqHz; + u64 CalcLineRateFreqHz; + u8 Id, Id0, Id1; + u64 PllClkInFreqHzIn = PllClkInFreqHz; + XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(ChId)]; + + if (!PllClkInFreqHzIn) { + PllClkInFreqHzIn = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + PllPtr->PllRefClkSel); + } + + /* Select PLL value table offsets. */ + const XVphy_GtPllDivs *GtPllDivs; + if (XVPHY_ISCH(ChId)) { + GtPllDivs = &InstancePtr->GtAdaptor->CpllDivs; + } + else { + GtPllDivs = &InstancePtr->GtAdaptor->QpllDivs; + } + + const u8 *M, *N1, *N2, *D; + for (N2 = GtPllDivs->N2; *N2 != 0; N2++) { + for (N1 = GtPllDivs->N1; *N1 != 0; N1++) { + for (M = GtPllDivs->M; *M != 0; M++) { + PllClkOutFreqHz = (PllClkInFreqHzIn * *N1 * *N2) / *M; + + /* Test if the calculated PLL clock is in the VCO range. */ + Status = XVphy_CheckPllOpRange(InstancePtr, QuadId, ChId, + PllClkOutFreqHz); + if (Status != XST_SUCCESS) { + continue; + } + + if (XVPHY_ISCH(ChId)) { + PllClkOutFreqHz *= 2; + } + /* Apply TX/RX divisor. */ + for (D = GtPllDivs->D; *D != 0; D++) { + CalcLineRateFreqHz = PllClkOutFreqHz / *D; + if (CalcLineRateFreqHz == PllPtr->LineRateHz) { + goto calc_done; + } + } + } + } + } + /* Calculation failed, don't change divisor settings. */ + return XST_FAILURE; + +calc_done: + /* Found the multiplier and divisor values for requested line rate. */ + PllPtr->PllParams.MRefClkDiv = *M; + PllPtr->PllParams.NFbDiv = *N1; + PllPtr->PllParams.N2FbDiv = *N2; /* Won't be used for QPLL.*/ + PllPtr->PllParams.IsLowerBand = 1; /* Won't be used for CPLL. */ + + if (XVPHY_ISCMN(ChId)) { + /* Same divisor value for all channels if using a QPLL. */ + ChId = XVPHY_CHANNEL_ID_CHA; + } + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].OutDiv[Dir] = + *D; + if (Dir == XVPHY_DIR_RX) { + XVphy_CfgSetCdr(InstancePtr, QuadId, Id); + } + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy.h b/XilinxProcessorIPLib/drivers/vphy/src/xvphy.h new file mode 100644 index 00000000..73b766f1d --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy.h @@ -0,0 +1,800 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * Version 1.0 supports: + * - GTXE2 and GTHE3 GT types. + * - DisplayPort and HDMI protocols. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +#ifndef XVPHY_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_H_ + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xvphy_hw.h" +#include "xvidc.h" +#include "xvphy_dp.h" + +/****************************** Type Definitions ******************************/ + +/* This typedef enumerates the different GT types available. */ +typedef enum { + XVPHY_GT_TYPE_GTXE2 = 1, + XVPHY_GT_TYPE_GTHE2 = 2, + XVPHY_GT_TYPE_GTPE2 = 3, + XVPHY_GT_TYPE_GTHE3 = 4, + XVPHY_GT_TYPE_GTHE4 = 5, +} XVphy_GtType; + +/** + * This typedef enumerates the various protocols handled by the Video PHY + * controller (VPHY). + */ +typedef enum { + XVPHY_PROTOCOL_DP = 0, + XVPHY_PROTOCOL_HDMI, + XVPHY_PROTOCOL_NONE +} XVphy_ProtocolType; + +/* This typedef enumerates is used to specify RX/TX direction information. */ +typedef enum { + XVPHY_DIR_RX = 0, + XVPHY_DIR_TX +} XVphy_DirectionType; + +/** + * This typedef enumerates the list of available interrupt handler types. The + * values are used as parameters to the XVphy_SetIntrHandler function. + */ +typedef enum { + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE = XVPHY_INTR_TXRESETDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE = XVPHY_INTR_RXRESETDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK = XVPHY_INTR_CPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK = XVPHY_INTR_QPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK = XVPHY_INTR_QPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE = XVPHY_INTR_TXALIGNDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK = XVPHY_INTR_QPLL1_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE = + XVPHY_INTR_TXCLKDETFREQCHANGE_MASK, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE = + XVPHY_INTR_RXCLKDETFREQCHANGE_MASK, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT = XVPHY_INTR_TXTMRTIMEOUT_MASK, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT = XVPHY_INTR_RXTMRTIMEOUT_MASK, +} XVphy_IntrHandlerType; + +/** + * This typedef enumerates the list of available hdmi handler types. The + * values are used as parameters to the XVphy_SetHdmiCallback function. + */ +typedef enum { + XVPHY_HDMI_HANDLER_TXINIT = 1, /**< TX init handler. */ + XVPHY_HDMI_HANDLER_TXREADY, /**< TX ready handler. */ + XVPHY_HDMI_HANDLER_RXINIT, /**< RX init handler. */ + XVPHY_HDMI_HANDLER_RXREADY /**< RX ready handler. */ +} XVphy_HdmiHandlerType; + +/** + * This typedef enumerates the different PLL types for a given GT channel. + */ +typedef enum { + XVPHY_PLL_TYPE_CPLL = 1, + XVPHY_PLL_TYPE_QPLL = 2, + XVPHY_PLL_TYPE_QPLL0 = 3, + XVPHY_PLL_TYPE_QPLL1 = 4, + XVPHY_PLL_TYPE_PLL0 = 5, + XVPHY_PLL_TYPE_PLL1 = 6, + XVPHY_PLL_TYPE_UNKNOWN = 7, +} XVphy_PllType; + +/** + * This typedef enumerates the available channels. + */ +typedef enum { + XVPHY_CHANNEL_ID_CH1 = 1, + XVPHY_CHANNEL_ID_CH2 = 2, + XVPHY_CHANNEL_ID_CH3 = 3, + XVPHY_CHANNEL_ID_CH4 = 4, + XVPHY_CHANNEL_ID_CMN0 = 5, + XVPHY_CHANNEL_ID_CMN1 = 6, + XVPHY_CHANNEL_ID_CHA = 7, + XVPHY_CHANNEL_ID_CMNA = 8, + XVPHY_CHANNEL_ID_CMN = XVPHY_CHANNEL_ID_CMN0, +} XVphy_ChannelId; + +/** + * This typedef enumerates the available reference clocks for the PLL clock + * selection multiplexer. + */ +typedef enum { + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0 = XVPHY_REF_CLK_SEL_XPLL_GTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1 = XVPHY_REF_CLK_SEL_XPLL_GTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK = XVPHY_REF_CLK_SEL_XPLL_GTGREFCLK, +} XVphy_PllRefClkSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX datapaths. + */ +typedef enum { + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL, + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL, + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0, + XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1, +} XVphy_SysClkDataSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX output clocks. + */ +typedef enum { + XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, + XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0, + XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1, +} XVphy_SysClkOutSelType; + +/** + * This typedef enumerates the available clocks that are used as multiplexer + * input selections for the RX/TX output clock. + */ +typedef enum { + XVPHY_OUTCLKSEL_TYPE_OUTCLKPCS = 1, + XVPHY_OUTCLKSEL_TYPE_OUTCLKPMA, + XVPHY_OUTCLKSEL_TYPE_PLLREFCLK_DIV1, + XVPHY_OUTCLKSEL_TYPE_PLLREFCLK_DIV2, + XVPHY_OUTCLKSEL_TYPE_PROGDIVCLK +} XVphy_OutClkSelType; + +/* This typedef enumerates the possible states a transceiver can be in. */ +typedef enum { + XVPHY_GT_STATE_IDLE, /**< Idle state. */ + XVPHY_GT_STATE_LOCK, /**< Lock state. */ + XVPHY_GT_STATE_RESET, /**< Reset state. */ + XVPHY_GT_STATE_ALIGN, /**< Align state. */ + XVPHY_GT_STATE_READY /**< Ready state. */ +} XVphy_GtState; + +typedef enum { + XVPHY_LOG_EVT_NONE = 1, /**< Log event none. */ + XVPHY_LOG_EVT_QPLL_EN, /**< Log event QPLL enable. */ + XVPHY_LOG_EVT_QPLL_RST, /**< Log event QPLL reset. */ + XVPHY_LOG_EVT_QPLL_LOCK, /**< Log event QPLL lock. */ + XVPHY_LOG_EVT_QPLL_RECONFIG, /**< Log event QPLL reconfig. */ + XVPHY_LOG_EVT_QPLL0_EN, /**< Log event QPLL0 enable. */ + XVPHY_LOG_EVT_QPLL0_RST, /**< Log event QPLL0 reset. */ + XVPHY_LOG_EVT_QPLL0_LOCK, /**< Log event QPLL0 lock. */ + XVPHY_LOG_EVT_QPLL0_RECONFIG, /**< Log event QPLL0 reconfig. */ + XVPHY_LOG_EVT_QPLL1_EN, /**< Log event QPLL1 enable. */ + XVPHY_LOG_EVT_QPLL1_RST, /**< Log event QPLL1 reset. */ + XVPHY_LOG_EVT_QPLL1_LOCK, /**< Log event QPLL1 lock. */ + XVPHY_LOG_EVT_QPLL1_RECONFIG, /**< Log event QPLL1 reconfig. */ + XVPHY_LOG_EVT_PLL0_EN, /**< Log event PLL0 reset. */ + XVPHY_LOG_EVT_PLL0_RST, /**< Log event PLL0 reset. */ + XVPHY_LOG_EVT_PLL0_LOCK, /**< Log event PLL0 lock. */ + XVPHY_LOG_EVT_PLL0_RECONFIG, /**< Log event PLL0 reconfig. */ + XVPHY_LOG_EVT_PLL1_EN, /**< Log event PLL1 reset. */ + XVPHY_LOG_EVT_PLL1_RST, /**< Log event PLL1 reset. */ + XVPHY_LOG_EVT_PLL1_LOCK, /**< Log event PLL1 lock. */ + XVPHY_LOG_EVT_PLL1_RECONFIG, /**< Log event PLL1 reconfig. */ + XVPHY_LOG_EVT_CPLL_EN, /**< Log event CPLL reset. */ + XVPHY_LOG_EVT_CPLL_RST, /**< Log event CPLL reset. */ + XVPHY_LOG_EVT_CPLL_LOCK, /**< Log event CPLL lock. */ + XVPHY_LOG_EVT_CPLL_RECONFIG, /**< Log event CPLL reconfig. */ + XVPHY_LOG_EVT_TXPLL_EN, /**< Log event TXPLL enable. */ + XVPHY_LOG_EVT_TXPLL_RST, /**< Log event TXPLL reset. */ + XVPHY_LOG_EVT_RXPLL_EN, /**< Log event RXPLL enable. */ + XVPHY_LOG_EVT_RXPLL_RST, /**< Log event RXPLL reset. */ + XVPHY_LOG_EVT_GTRX_RST, /**< Log event GT RX reset. */ + XVPHY_LOG_EVT_GTTX_RST, /**< Log event GT TX reset. */ + XVPHY_LOG_EVT_VID_TX_RST, /**< Log event Vid TX reset. */ + XVPHY_LOG_EVT_VID_RX_RST, /**< Log event Vid RX reset. */ + XVPHY_LOG_EVT_TX_ALIGN, /**< Log event TX align. */ + XVPHY_LOG_EVT_TX_TMR, /**< Log event TX timer. */ + XVPHY_LOG_EVT_RX_TMR, /**< Log event RX timer. */ + XVPHY_LOG_EVT_GT_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_INIT, /**< Log event init. */ + XVPHY_LOG_EVT_TXPLL_RECONFIG, /**< Log event TXPLL reconfig. */ + XVPHY_LOG_EVT_RXPLL_RECONFIG, /**< Log event RXPLL reconfig. */ + XVPHY_LOG_EVT_RXPLL_LOCK, /**< Log event RXPLL lock. */ + XVPHY_LOG_EVT_TXPLL_LOCK, /**< Log event TXPLL lock. */ + XVPHY_LOG_EVT_TX_RST_DONE, /**< Log event TX reset done. */ + XVPHY_LOG_EVT_RX_RST_DONE, /**< Log event RX reset done. */ + XVPHY_LOG_EVT_TX_FREQ, /**< Log event TX frequency. */ + XVPHY_LOG_EVT_RX_FREQ /**< Log event RX frequency. */ +} XVphy_LogEvent; + +/******************************************************************************/ +/** + * Callback type which represents the handler for interrupts. + * + * @param InstancePtr is a pointer to the XVphy instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_IntrHandler)(void *InstancePtr); + +/******************************************************************************/ +/** + * Callback type which represents a custom timer wait handler. This is only + * used for Microblaze since it doesn't have a native sleep function. To avoid + * dependency on a hardware timer, the default wait functionality is implemented + * using loop iterations; this isn't too accurate. If a custom timer handler is + * used, the user may implement their own wait implementation using a hardware + * timer (see example/) for better accuracy. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param MicroSeconds is the number of microseconds to be passed to the + * timer function. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_TimerHandler)(void *InstancePtr, u32 MicroSeconds); + +/******************************************************************************/ +/** + * Generic callback type. + * + * @param CallbackRef is a pointer to the callback reference. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_Callback)(void *CallbackRef); + +/** + * This typedef contains configuration information for CPLL/QPLL programming. + */ +typedef struct { + u8 MRefClkDiv; + /* Aliases for N (QPLL) and N1/N2 (CPLL). */ + union { + u8 NFbDivs[2]; + u8 NFbDiv; + struct { + u8 N1FbDiv; + u8 N2FbDiv; + }; + }; + u16 Cdr[5]; + u8 IsLowerBand; +} XVphy_PllParam; + +/** + * This typedef contains configuration information for PLL type and its + * reference clock. + */ +typedef struct { + /* Below members are common between CPLL/QPLL. */ + u64 LineRateHz; /**< The line rate for the + channel. */ + union { + XVphy_PllParam QpllParams; + XVphy_PllParam CpllParams; /**< Parameters for a CPLL. */ + XVphy_PllParam PllParams; + }; + union { + XVphy_PllRefClkSelType CpllRefClkSel; + /**< Multiplexer selection for + the reference clock of + the CPLL. */ + XVphy_PllRefClkSelType PllRefClkSel; + }; + /* Below members are CPLL specific. */ + union { + struct { + u8 RxOutDiv; /**< Output clock divider D for + the RX datapath. */ + u8 TxOutDiv; /**< Output clock divider D for + the TX datapath. */ + }; + u8 OutDiv[2]; + }; + union { + struct { + XVphy_GtState RxState; /**< Current state of RX GT. */ + XVphy_GtState TxState; /**< Current state of TX GT. */ + }; + XVphy_GtState GtState[2]; + }; + union { + struct { + XVphy_ProtocolType RxProtocol; + /**< The protocol which the RX + path is used for. */ + XVphy_ProtocolType TxProtocol; + /**< The protocol which the TX + path is used for. */ + }; + XVphy_ProtocolType Protocol[2]; + }; + union { + struct { + XVphy_SysClkDataSelType RxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX datapath. */ + XVphy_SysClkDataSelType TxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX datapath. */ + }; + XVphy_SysClkDataSelType DataRefClkSel[2]; + }; + union { + struct { + XVphy_SysClkOutSelType RxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX output clock. */ + XVphy_SysClkOutSelType TxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX output clock. */ + }; + XVphy_SysClkOutSelType OutRefClkSel[2]; + }; + union { + struct { + XVphy_OutClkSelType RxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the RX output clock. */ + XVphy_OutClkSelType TxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the TX output clock. */ + }; + XVphy_OutClkSelType OutClkSel[2]; + }; + union { + struct { + u8 RxDelayBypass; /**< Bypasses the delay + alignment block for the + RX output clock. */ + u8 TxDelayBypass; /**< Bypasses the delay + alignment block for the + TX output clock. */ + }; + u8 DelayBypass; + }; + u8 RxDataWidth; /**< In bits. */ + u8 RxIntDataWidth; /**< In bytes. */ +} XVphy_Channel; + +/** + * This typedef contains configuration information for MMCM programming. + */ +typedef struct { + u8 DivClkDivide; + u8 ClkFbOutMult; + u16 ClkFbOutFrac; + u8 ClkOut0Div; + u16 ClkOut0Frac; + u8 ClkOut1Div; + u8 ClkOut2Div; +} XVphy_Mmcm; + +/** + * This typedef represents a GT quad. + */ +typedef struct { + union { + struct { + XVphy_Mmcm RxMmcm; /**< Mixed-mode clock manager + (MMCM) parameters for + RX. */ + XVphy_Mmcm TxMmcm; /**< MMCM parameters for TX. */ + }; + XVphy_Mmcm Mmcm[2]; /**< MMCM parameters. */ + }; + union { + struct { + XVphy_Channel Ch1; + XVphy_Channel Ch2; + XVphy_Channel Ch3; + XVphy_Channel Ch4; + XVphy_Channel Cmn0; + XVphy_Channel Cmn1; + }; + XVphy_Channel Plls[6]; + }; + union { + struct { + u32 GtRefClk0Hz; + u32 GtRefClk1Hz; + u32 GtNorthRefClk0Hz; + u32 GtNorthRefClk1Hz; + u32 GtSouthRefClk0Hz; + u32 GtSouthRefClk1Hz; + u32 GtgRefClkHz; + }; + u32 RefClkHz[7]; + }; +} XVphy_Quad; + +/** + * This typedef contains the logging mechanism for debug. + */ +typedef struct { + u16 DataBuffer[256]; /**< Log buffer with event data. */ + u8 HeadIndex; /**< Index of the head entry of the + Event/DataBuffer. */ + u8 TailIndex; /**< Index of the tail entry of the + Event/DataBuffer. */ +} XVphy_Log; + +/** + * This typedef contains configuration information for the Video PHY core. + */ +typedef struct { + u16 DeviceId; /**< Device instance ID. */ + u32 BaseAddr; /**< The base address of the core + instance. */ + XVphy_GtType XcvrType; /**< VPHY Transceiver Type */ + u8 TxChannels; /**< No. of active channels in TX */ + u8 RxChannels; /**< No. of active channels in RX */ + XVphy_ProtocolType TxProtocol; /**< Protocol which TX is used for. */ + XVphy_ProtocolType RxProtocol; /**< Protocol which RX is used for. */ + XVphy_PllRefClkSelType TxRefClkSel; /**< TX REFCLK selection. */ + XVphy_PllRefClkSelType RxRefClkSel; /**< RX REFCLK selection. */ + XVphy_SysClkDataSelType TxSysPllClkSel; /**< TX SYSCLK selection. */ + XVphy_SysClkDataSelType RxSysPllClkSel; /**< RX SYSCLK selectino. */ + u8 DruIsPresent; /**< A data recovery unit (DRU) exists + in the design .*/ + XVphy_PllRefClkSelType DruRefClkSel; /**< DRU REFCLK selection. */ +} XVphy_Config; + +/* Forward declaration. */ +struct XVphy_GtConfigS; + +/** + * The XVphy driver instance data. The user is required to allocate a variable + * of this type for every XVphy device in the system. A pointer to a variable of + * this type is then passed to the driver API functions. + */ +typedef struct { + u32 IsReady; /**< Device is initialized and + ready. */ + XVphy_Config Config; /**< Configuration structure for + the Video PHY core. */ + const struct XVphy_GtConfigS *GtAdaptor; + XVphy_Log Log; /**< A log of events. */ + XVphy_Quad Quads[2]; /**< The quads available to the + Video PHY core.*/ + u32 HdmiRxRefClkHz; /**< HDMI RX refclk. */ + u32 HdmiTxRefClkHz; /**< HDMI TX refclk. */ + u8 HdmiRxTmdsClockRatio; /**< HDMI TMDS clock ratio. */ + u8 HdmiTxSampleRate; /**< HDMI TX sample rate. */ + u8 HdmiRxDruIsEnabled; /**< The DRU is enabled. */ + XVphy_IntrHandler IntrCpllLockHandler; /**< Callback function for CPLL + lock interrupts. */ + void *IntrCpllLockCallbackRef; /**< A pointer to the user data + passed to the CPLL lock + callback function. */ + XVphy_IntrHandler IntrQpllLockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpllLockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XVphy_IntrHandler IntrQpll1LockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpll1LockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XVphy_IntrHandler IntrTxResetDoneHandler; /**< Callback function for TX + reset done lock + interrupts. */ + void *IntrTxResetDoneCallbackRef; /**< A pointer to the user data + passed to the TX reset + done lock callback + function. */ + XVphy_IntrHandler IntrRxResetDoneHandler; /**< Callback function for RX + reset done lock + interrupts. */ + void *IntrRxResetDoneCallbackRef; /**< A pointer to the user data + passed to the RX reset + done lock callback + function. */ + XVphy_IntrHandler IntrTxAlignDoneHandler; /**< Callback function for TX + align done lock + interrupts. */ + void *IntrTxAlignDoneCallbackRef; /**< A pointer to the user data + passed to the TX align + done lock callback + function. */ + XVphy_IntrHandler IntrTxClkDetFreqChangeHandler; /**< Callback function + for TX clock detector + frequency change + interrupts. */ + void *IntrTxClkDetFreqChangeCallbackRef; /**< A pointer to the user data + passed to the TX clock + detector frequency + change callback + function. */ + XVphy_IntrHandler IntrRxClkDetFreqChangeHandler; /**< Callback function + for RX clock detector + frequency change + interrupts. */ + void *IntrRxClkDetFreqChangeCallbackRef; /**< A pointer to the user data + passed to the RX clock + detector frequency + change callback + function. */ + XVphy_IntrHandler IntrTxTmrTimeoutHandler; /**< Callback function for TX + timer timeout + interrupts. */ + void *IntrTxTmrTimeoutCallbackRef; /**< A pointer to the user data + passed to the TX timer + timeout callback + function. */ + XVphy_IntrHandler IntrRxTmrTimeoutHandler; /**< Callback function for RX + timer timeout + interrupts. */ + void *IntrRxTmrTimeoutCallbackRef; /**< A pointer to the user data + passed to the RX timer + timeout callback + function. */ + /* HDMI callbacks. */ + XVphy_Callback HdmiTxInitCallback; /**< Callback for TX init. */ + void *HdmiTxInitRef; /**< To be passed to the TX init + callback. */ + XVphy_Callback HdmiTxReadyCallback; /**< Callback for TX ready. */ + void *HdmiTxReadyRef; /**< To be passed to the TX + ready callback. */ + XVphy_Callback HdmiRxInitCallback; /**< Callback for RX init. */ + void *HdmiRxInitRef; /**< To be passed to the RX + init callback. */ + XVphy_Callback HdmiRxReadyCallback; /**< Callback for RX ready. */ + void *HdmiRxReadyRef; /**< To be passed to the RX + ready callback. */ + XVphy_TimerHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ +} XVphy; + +/**************************** Function Prototypes *****************************/ + +/* xvphy.c: Setup and initialization functions. */ +void XVphy_CfgInitialize(XVphy *InstancePtr, XVphy_Config *ConfigPtr, + u32 EffectiveAddr); +u32 XVphy_PllInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllRefClkSelType CpllxRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect); +u32 XVphy_ClkInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +void XVphy_WaitUs(XVphy *InstancePtr, u32 MicroSeconds); +void XVphy_SetUserTimerHandler(XVphy *InstancePtr, + XVphy_TimerHandler CallbackFunc, void *CallbackRef); + +/* xvphy.c: GT attributes update function. */ +u32 XVphy_UpdateGtProtocolParameters(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_ProtocolType Protocol); + +/* xvphy.c: Voltage swing and preemphasis. */ +void XVphy_SetRxLpm(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable); +void XVphy_SetTxVoltageSwing(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Vs); +void XVphy_SetTxPreEmphasis(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Pe); + +/* xvphy.c: Channel configuration functions - setters. */ +u32 XVphy_WriteCfgRefClkSelReg(XVphy *InstancePtr, u8 QuadId); +u32 XVphy_CfgLineRate(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u64 LineRateHz); +u32 XVphy_CfgQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType, u32 FreqHz); +void XVphy_CfgPllRefClkSel(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType RefClkSel); +void XVphy_CfgSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkDataSelType SysClkDataSel); +void XVphy_CfgSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkOutSelType SysClkOutSel); + +u32 XVphy_ClkCalcParams(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u32 PllClkInFreqHz); +u32 XVphy_OutDivReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_DirReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_ClkReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy.c: Channel configuration functions - getters. */ +XVphy_PllType XVphy_GetPllType(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); +u32 XVphy_GetQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType); +XVphy_PllRefClkSelType XVphy_GetPllRefClkSel(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +XVphy_SysClkDataSelType XVphy_GetSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); +XVphy_SysClkOutSelType XVphy_GetSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); + +/* xvphy.c: Reset functions. */ +u32 XVphy_WaitForPmaResetDone(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_WaitForResetDone(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_WaitForPllLock(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_ResetGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); +u32 XVphy_ResetGtTxRx(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); +u32 XVphy_GtUserRdyEnable(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); +u32 XVphy_ResetGt(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir); + +/* xvphy.c: GT/MMCM DRP access. */ +u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr, u16 Val); +u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr); +void XVphy_MmcmReset(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold); +void XVphy_MmcmPowerDown(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold); +void XVphy_MmcmStart(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir); +void XVphy_BufgGtReset(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Reset); +void XVphy_SetBufgGtDiv(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Div); +void XVphy_IBufDsEnable(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Enable); +void XVphy_Clkout1OBufTdsEnable(XVphy *InstancePtr, XVphy_DirectionType Dir, + u8 Enable); + +/* xvphy.c Miscellaneous control. */ +u32 XVphy_GetVersion(XVphy *InstancePtr); +void XVphy_Set8b10b(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable); +u32 XVphy_PowerDownGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Hold); +u32 XVphy_IsBonded(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy_log.c: Logging functions. */ +void XVphy_LogReset(XVphy *InstancePtr); +void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data); +u16 XVphy_LogRead(XVphy *InstancePtr); +void XVphy_LogDisplay(XVphy *InstancePtr); + +/* xvphy_intr.c: Interrupt handling functions. */ +void XVphy_SetIntrHandler(XVphy *InstancePtr, XVphy_IntrHandlerType HandlerType, + XVphy_IntrHandler CallbackFunc, void *CallbackRef); +void XVphy_InterruptHandler(XVphy *InstancePtr); +void XVphy_IntrEnable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr); +void XVphy_IntrDisable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr); + +/* xvphy_selftest.c: Self test function. */ +u32 XVphy_SelfTest(XVphy *InstancePtr); + +/* xvphy_sinit.c: Configuration extraction function. */ +XVphy_Config *XVphy_LookupConfig(u16 DeviceId); + +/* xvphy_dp.c, xvphy_hdmi.c, xvphy_hdmi_intr.c: Protocol specific functions. */ +u32 XVphy_DpInitialize(XVphy *InstancePtr, XVphy_Config *CfgPtr, u8 QuadId, + XVphy_PllRefClkSelType CpllRefClkSel, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect, + u8 LinkRate); +u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, + u32 SystemFrequency); +u32 XVphy_SetHdmiTxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc, + XVidC_ColorFormat ColorFormat); +u32 XVphy_SetHdmiRxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +u32 XVphy_HdmiCfgCalcMmcmParam(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc); + +void XVphy_HdmiUpdateClockSelection(XVphy *InstancePtr, u8 QuadId, + XVphy_SysClkDataSelType TxSysPllClkSel, + XVphy_SysClkDataSelType RxSysPllClkSel); +void XVphy_ClkDetFreqReset(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +u32 XVphy_ClkDetGetRefClkFreqHz(XVphy *InstancePtr, XVphy_DirectionType Dir); +u32 XVphy_DruGetRefClkFreqHz(XVphy *InstancePtr); +void XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +void XVphy_DpDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +void XVphy_SetHdmiCallback(XVphy *InstancePtr, + XVphy_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef); + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XVPHY_CH2IDX(Id) ((Id) - XVPHY_CHANNEL_ID_CH1) +#define XVPHY_ISCH(Id) (((Id) == XVPHY_CHANNEL_ID_CHA) || \ + ((XVPHY_CHANNEL_ID_CH1 <= (Id)) && ((Id) <= XVPHY_CHANNEL_ID_CH4))) +#define XVPHY_ISCMN(Id) (((Id) == XVPHY_CHANNEL_ID_CMNA) || \ + ((XVPHY_CHANNEL_ID_CMN0 <= (Id)) && ((Id) <= XVPHY_CHANNEL_ID_CMN1))) + +#define XVphy_IsTxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XVPHY_PLL_TYPE_QPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId))) +#define XVphy_IsRxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XVPHY_PLL_TYPE_QPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId))) +#define XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId) \ + (XVPHY_PLL_TYPE_CPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) +#define XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId) \ + (XVPHY_PLL_TYPE_CPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) + +#endif /* XVPHY_H_ */ diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_dp.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_dp.c new file mode 100644 index 00000000..1f9f40da --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_dp.c @@ -0,0 +1,335 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_dp.c + * + * This file contains video PHY functionality specific to the DisplayPort + * protocol. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   vkd  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xparameters.h" +#include "xstatus.h" +#include "xvphy_dp.h" +#include "xvphy.h" +#include "string.h" + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function initializes the Video PHY for DisplayPort. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param CfgPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * @param QuadId is the GT quad ID to operate on. + * @param CpllRefClkSel is the CPLL reference clock selection for the + * quad. + * @param QpllRefClkSel is the QPLL reference clock selection for the + * quad. + * @param TxPllSelect is the reference clock selection for the quad's + * TX PLL dividers. + * @param RxPllSelect is the reference clock selection for the quad's + * RX PLL dividers. + * @param LinkRate is the line rate to set for the quad's channels. + * + * @return + * - XST_SUCCESS. + * + * @note None. + * +*******************************************************************************/ +u32 XVphy_DpInitialize(XVphy *InstancePtr, XVphy_Config *CfgPtr, u8 QuadId, + XVphy_PllRefClkSelType CpllRefClkSel, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect, + u8 LinkRate) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Setup the instance */ + (void)memset((void *)InstancePtr, 0, sizeof(XVphy)); + XVphy_CfgInitialize(InstancePtr, CfgPtr, CfgPtr->BaseAddr); + + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT); + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + + XVphy_LogReset(InstancePtr); + + XVphy_LogWrite(InstancePtr, (XVPHY_LOG_EVT_INIT), 0); + + InstancePtr->Quads[QuadId].Plls[0].TxState = (XVPHY_GT_STATE_IDLE); + + InstancePtr->Quads[QuadId].Plls[0].RxState = (XVPHY_GT_STATE_IDLE); + + switch (InstancePtr->Config.XcvrType) { + case XVPHY_GT_TYPE_GTXE2: + case XVPHY_GT_TYPE_GTHE2: + XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0, + XVPHY_DP_REF_CLK_FREQ_HZ_135); + XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1, + XVPHY_DP_REF_CLK_FREQ_HZ_135); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1, + XVPHY_GTXE2_DIFF_SWING_DP_L1); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH2, + XVPHY_GTXE2_DIFF_SWING_DP_L1); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH3, + XVPHY_GTXE2_DIFF_SWING_DP_L1); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH4, + XVPHY_GTXE2_DIFF_SWING_DP_L1); + break; + case XVPHY_GT_TYPE_GTHE3: + XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0, + XVPHY_DP_REF_CLK_FREQ_HZ_162); + XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1, + XVPHY_DP_REF_CLK_FREQ_HZ_162); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1, XVPHY_GTHE3_DIFF_SWING_DP_L1); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH2, XVPHY_GTHE3_DIFF_SWING_DP_L1); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH3, XVPHY_GTHE3_DIFF_SWING_DP_L1); + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH4, XVPHY_GTHE3_DIFF_SWING_DP_L1); + XVphy_SetTxPreEmphasis(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1, XVPHY_GTHE3_PREEMP_DP_L0); + XVphy_SetTxPreEmphasis(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH2, XVPHY_GTHE3_PREEMP_DP_L0); + XVphy_SetTxPreEmphasis(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH3, XVPHY_GTHE3_PREEMP_DP_L0); + XVphy_SetTxPreEmphasis(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH4, XVPHY_GTHE3_PREEMP_DP_L0); + break; + default: + break; + } + + XVphy_Set8b10b(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX, + 1); + XVphy_Set8b10b(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + 1); + XVphy_SetRxLpm(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + 1); + + XVphy_PllInitialize(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + QpllRefClkSel, CpllRefClkSel, TxPllSelect, RxPllSelect); + + InstancePtr->IsReady = (u32)(XIL_COMPONENT_IS_READY); + + XVphy_LogWrite(InstancePtr, (XVPHY_LOG_EVT_INIT), 1); + + return (XST_SUCCESS); + +} + +/******************************************************************************/ +/** +* This function prints Vphy debug information on STDIO/Uart console. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_DpDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + XVphy_ChannelId CmnId; + u8 CpllDVal; + u8 QpllDVal; + u8 UsesQpll0; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[0]; + + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("TX => CPLL / "); + } + else if (ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK) { + UsesQpll0 = (TRUE); + CmnId = XVPHY_CHANNEL_ID_CMN0; + xil_printf("TX => QPLL1, "); + } + else if (ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN; + xil_printf("TX => QPLL, "); + } + else { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN1; + xil_printf("TX => QPLL0, "); + } + + if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("RX => CPLL\n\r"); + } + else if (ChPtr->RxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK) { + UsesQpll0 = (TRUE); + CmnId = XVPHY_CHANNEL_ID_CMN0; + xil_printf("RX => QPLL0, \n\r"); + } + else if (ChPtr->RxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK){ + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN; + xil_printf("RX => QPLL, \n\r"); + } + else { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN1; + xil_printf("RX => QPLL1, \n\r"); + } + + xil_printf("RX state: "); + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].RxState) { + case (XVPHY_GT_STATE_IDLE): + xil_printf("idle\n\r"); + break; + case (XVPHY_GT_STATE_LOCK): + if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("CPLL lock\n\r"); + } + else { + xil_printf("QPLL%d lock\n\r", (UsesQpll0 ? 0 : 1)); + } + break; + case (XVPHY_GT_STATE_RESET): + xil_printf("GT reset\n\r"); + break; + case (XVPHY_GT_STATE_READY): + xil_printf("ready\n\r"); + break; + default: + xil_printf("unknown\n\r"); + break; + } + + xil_printf("TX state: "); + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].TxState) { + case (XVPHY_GT_STATE_IDLE): + xil_printf("idle\n\r"); + break; + case (XVPHY_GT_STATE_LOCK): + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("CPLL lock\n\r"); + } + else { + xil_printf("QPLL%d lock\n\r", (UsesQpll0 ? 0 : 1)); + } + break; + case (XVPHY_GT_STATE_RESET): + xil_printf("GT reset\n\r"); + break; + case (XVPHY_GT_STATE_ALIGN): + xil_printf("align\n\r"); + break; + case (XVPHY_GT_STATE_READY): + xil_printf("ready\n\r"); + break; + default: + xil_printf("unknown\n\r"); + break; + } + + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + QpllDVal = ChPtr->RxOutDiv; + CpllDVal = ChPtr->TxOutDiv; + } + else { + CpllDVal = ChPtr->RxOutDiv; + QpllDVal = ChPtr->TxOutDiv; + } + + xil_printf("\n\r"); + xil_printf("QPLL settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N : %d - D : %d\n\r", + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.MRefClkDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv, + QpllDVal); + xil_printf("\n\r"); + + xil_printf("CPLL settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N1 : %d - N2 : %d - D : %d\n\r", + ChPtr->PllParams.MRefClkDiv, + ChPtr->PllParams.N1FbDiv, + ChPtr->PllParams.N2FbDiv, + CpllDVal); + xil_printf("\n\r"); + + print(" \n\r"); +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_dp.h b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_dp.h new file mode 100644 index 00000000..ed523e4a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_dp.h @@ -0,0 +1,94 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   vkd  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +#ifndef XVPHY_DP_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_DP_H_ + +/************************** Constant Definitions ******************************/ + +/* GTXE2. */ +#define XVPHY_GTXE2_DIFF_SWING_DP_L0 0x03 +#define XVPHY_GTXE2_DIFF_SWING_DP_L1 0x06 +#define XVPHY_GTXE2_DIFF_SWING_DP_L2 0x09 +#define XVPHY_GTXE2_DIFF_SWING_DP_L3 0x0F + +#define XVPHY_GTXE2_PREEMP_DP_L0 0x00 +#define XVPHY_GTXE2_PREEMP_DP_L1 0x0E +#define XVPHY_GTXE2_PREEMP_DP_L2 0x14 +#define XVPHY_GTXE2_PREEMP_DP_L3 0x14 + +/* GTHE3. */ +#define XVPHY_GTHE3_DIFF_SWING_DP_L0 0x03 +#define XVPHY_GTHE3_DIFF_SWING_DP_L1 0x06 +#define XVPHY_GTHE3_DIFF_SWING_DP_L2 0x09 +#define XVPHY_GTHE3_DIFF_SWING_DP_L3 0x0F + +#define XVPHY_GTHE3_PREEMP_DP_L0 0x00 +#define XVPHY_GTHE3_PREEMP_DP_L1 0x0E +#define XVPHY_GTHE3_PREEMP_DP_L2 0x14 +#define XVPHY_GTHE3_PREEMP_DP_L3 0x14 + +/* DP line rate coding. */ +#define XVPHY_DP_LINK_BW_SET_162GBPS 0x06 +#define XVPHY_DP_LINK_BW_SET_270GBPS 0x0A +#define XVPHY_DP_LINK_BW_SET_540GBPS 0x14 + +#define XVPHY_DP_LINK_RATE_HZ_162GBPS 1620000000LL +#define XVPHY_DP_LINK_RATE_HZ_270GBPS 2700000000LL +#define XVPHY_DP_LINK_RATE_HZ_540GBPS 5400000000LL + +#define XVPHY_DP_REF_CLK_FREQ_HZ_162 162000000LL +#define XVPHY_DP_REF_CLK_FREQ_HZ_135 135000000LL +#define XVPHY_DP_REF_CLK_FREQ_HZ_81 81000000LL +#define XVPHY_DP_REF_CLK_FREQ_HZ_270 270000000LL + +#endif /* XVPHY_HDMI_H_ */ diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_g.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_g.c new file mode 100644 index 00000000..7192a467 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_g.c @@ -0,0 +1,64 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: +* DO NOT EDIT. +* +* Copyright (C) 2010-2015 Xilinx, Inc. All Rights Reserved.* +*Permission is hereby granted, free of charge, to any person obtaining a copy +*of this software and associated documentation files (the Software), to deal +*in the Software without restriction, including without limitation the rights +*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +*copies of the Software, and to permit persons to whom the Software is +*furnished to do so, subject to the following conditions: +* +*The above copyright notice and this permission notice shall be included in +*all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +*(a) running on a Xilinx device, or +*(b) that interact with a Xilinx device through a bus or interconnect. +* +*THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +*XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +*OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xvphy.h" + +/* +* The configuration table for devices +*/ + +XVphy_Config XVphy_ConfigTable[] = +{ + { + XPAR_VID_PHY_CONTROLLER_0_DEVICE_ID, + XPAR_VID_PHY_CONTROLLER_0_BASEADDR, + XPAR_VID_PHY_CONTROLLER_0_TRANSCEIVER, + XPAR_VID_PHY_CONTROLLER_0_TX_NO_OF_CHANNELS, + XPAR_VID_PHY_CONTROLLER_0_RX_NO_OF_CHANNELS, + XPAR_VID_PHY_CONTROLLER_0_TX_PROTOCOL, + XPAR_VID_PHY_CONTROLLER_0_RX_PROTOCOL, + XPAR_VID_PHY_CONTROLLER_0_TX_REFCLK_SEL, + XPAR_VID_PHY_CONTROLLER_0_RX_REFCLK_SEL, + XPAR_VID_PHY_CONTROLLER_0_TX_PLL_SELECTION, + XPAR_VID_PHY_CONTROLLER_0_RX_PLL_SELECTION, + XPAR_VID_PHY_CONTROLLER_0_NIDRU, + XPAR_VID_PHY_CONTROLLER_0_NIDRU_REFCLK_SEL + } +}; diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gt.h b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gt.h new file mode 100644 index 00000000..7732ac96 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gt.h @@ -0,0 +1,107 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_gt.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +#ifndef XVPHY_GT_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_GT_H_ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" +#include "xil_assert.h" + +/****************************** Type Definitions ******************************/ + +typedef struct { + const u8 *M; + const u8 *N1; + const u8 *N2; + const u8 *D; +} XVphy_GtPllDivs; + +typedef struct XVphy_GtConfigS { + u32 (*CfgSetCdr)(XVphy *, u8, XVphy_ChannelId); + u32 (*CheckPllOpRange)(XVphy *, u8, XVphy_ChannelId, u64); + u32 (*OutDivChReconfig)(XVphy *, u8, XVphy_ChannelId, + XVphy_DirectionType); + u32 (*ClkChReconfig)(XVphy *, u8, XVphy_ChannelId); + u32 (*ClkCmnReconfig)(XVphy *, u8, XVphy_ChannelId); + u32 (*RxChReconfig)(XVphy *, u8, XVphy_ChannelId); + u32 (*TxPllRefClkDiv1Reconfig)(XVphy *, u8, XVphy_ChannelId); + + XVphy_GtPllDivs CpllDivs; + XVphy_GtPllDivs QpllDivs; +} XVphy_GtConfig; + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XVphy_CfgSetCdr(Ip, ...) \ + ((Ip)->GtAdaptor->CfgSetCdr(Ip, __VA_ARGS__)) +#define XVphy_CheckPllOpRange(Ip, ...) \ + ((Ip)->GtAdaptor->CheckPllOpRange(Ip, __VA_ARGS__)) +#define XVphy_OutDivChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->OutDivChReconfig(Ip, __VA_ARGS__)) +#define XVphy_ClkChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->ClkChReconfig(Ip, __VA_ARGS__)) +#define XVphy_ClkCmnReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->ClkCmnReconfig(Ip, __VA_ARGS__)) +#define XVphy_RxChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->RxChReconfig(Ip, __VA_ARGS__)) +#define XVphy_TxPllRefClkDiv1Reconfig(Ip, ...) \ + ((Ip)->GtAdaptor->TxPllRefClkDiv1Reconfig(Ip, __VA_ARGS__)) + +/*************************** Variable Declarations ****************************/ + +const XVphy_GtConfig Gtxe2Config; +const XVphy_GtConfig Gthe2Config; +const XVphy_GtConfig Gthe3Config; + +#endif /* XVPHY_GT_H_ */ diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gthe2.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gthe2.c new file mode 100644 index 00000000..3724e78d --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gthe2.c @@ -0,0 +1,686 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_gthe2.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy_gt.h" +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId); +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode); +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode); + +u32 XVphy_Gthe2CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_Gthe2CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz); +u32 XVphy_Gthe2OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_Gthe2ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe2ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId); +u32 XVphy_Gthe2RxChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); + +/************************** Constant Definitions ******************************/ + +/* DRP register space. */ +#define XVPHY_DRP_RXCDR_CFG(n) (0xA8 + n) + +#define XVPHY_DRP_CPLL_PROG 0x5E +#define XVPHY_DRP_OUT_DIV_PROG 0x88 +#define XVPHY_DRP_QPLL_CFG 0x32 +#define XVPHY_DRP_QPLL_REFCLK_DIV_PROG 0x33 +#define XVPHY_DRP_QPLL_FBDIV_PROG 0x36 +#define XVPHY_DRP_QPLL_FBDIV_RATIO_PROG 0x37 +#define XVPHY_DRP_RXCDR_CFG_WORD0 0xA8 +#define XVPHY_DRP_RXCDR_CFG_WORD1 0xA9 +#define XVPHY_DRP_RXCDR_CFG_WORD2 0xAA +#define XVPHY_DRP_RXCDR_CFG_WORD3 0xAB +#define XVPHY_DRP_RXCDR_CFG_WORD4 0xAC + +/* PLL operating ranges. */ +#define XVPHY_QPLL_LB_MIN 8000000000LL +#define XVPHY_QPLL_LB_MAX 13100000000LL +#define XVPHY_QPLL_UB_MIN 8000000000LL +#define XVPHY_QPLL_UB_MAX 13100000000LL +#define XVPHY_CPLL_MIN 1600000000LL +#define XVPHY_CPLL_MAX 5160000000LL + +#define XVPHY_DIFF_SWING_DP_L0 0x03 +#define XVPHY_DIFF_SWING_DP_L1 0x06 +#define XVPHY_DIFF_SWING_DP_L2 0x09 +#define XVPHY_DIFF_SWING_DP_L3 0x0F + +#define XVPHY_PREEMP_DP_L0 0x00 +#define XVPHY_PREEMP_DP_L1 0x0E +#define XVPHY_PREEMP_DP_L2 0x14 +#define XVPHY_PREEMP_DP_L3 0x14 + +const u8 Gthe2CpllDivsM[] = {1, 2, 0}; +const u8 Gthe2CpllDivsN1[] = {4, 5, 0}; +const u8 Gthe2CpllDivsN2[] = {1, 2, 3, 4, 5, 0}; +const u8 Gthe2CpllDivsD[] = {1, 2, 4, 8, 0}; + +const u8 Gthe2QpllDivsM[] = {4, 3, 2, 1, 0}; +const u8 Gthe2QpllDivsN1[] = {16, 20, 32, 40, 64, 66, 80, 100, 0}; +const u8 Gthe2QpllDivsN2[] = {1, 0}; +const u8 Gthe2QpllDivsD[] = {8, 4, 2, 1, 0}; + +const XVphy_GtConfig Gthe2Config = { + .CfgSetCdr = XVphy_Gthe2CfgSetCdr, + .CheckPllOpRange = XVphy_Gthe2CheckPllOpRange, + .OutDivChReconfig = XVphy_Gthe2OutDivChReconfig, + .ClkChReconfig = XVphy_Gthe2ClkChReconfig, + .ClkCmnReconfig = XVphy_Gthe2ClkCmnReconfig, + .RxChReconfig = XVphy_Gthe2RxChReconfig, + .TxPllRefClkDiv1Reconfig = NULL, + + .CpllDivs = { + .M = Gthe2CpllDivsM, + .N1 = Gthe2CpllDivsN1, + .N2 = Gthe2CpllDivsN2, + .D = Gthe2CpllDivsD, + }, + .QpllDivs = { + .M = Gthe2QpllDivsM, + .N1 = Gthe2QpllDivsN1, + .N2 = Gthe2QpllDivsN2, + .D = Gthe2QpllDivsD, + }, +}; + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will set the clock and data recovery (CDR) values for a given +* channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe2CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + + /* Set CDR values only for CPLLs. */ + if ((ChId < XVPHY_CHANNEL_ID_CH1) || (ChId > XVPHY_CHANNEL_ID_CH4)) { + return XST_FAILURE; + } + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + /* Update the RXCDR_CFG2 settings. */ + ChPtr->PllParams.Cdr[0] = 0x0020; + ChPtr->PllParams.Cdr[1] = 0x07FE; + ChPtr->PllParams.Cdr[3] = (ChPtr->RxOutDiv == 1) ? 0xC208 : 0xC220; + ChPtr->PllParams.Cdr[4] = 0x0018; + + /* RxOutDiv = 1 => Cdr[2] = 0x2000 + * RxOutDiv = 2 => Cdr[2] = 0x1000 + * RxOutDiv = 4 => Cdr[2] = 0x0800 + * RxOutDiv = 8 => Cdr[2] = 0x0400 */ + u8 RxOutDiv = ChPtr->RxOutDiv; + ChPtr->PllParams.Cdr[2] = 0x2000; + while (RxOutDiv >>= 1) { + ChPtr->PllParams.Cdr[2] >>= 1; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will check if a given PLL output frequency is within the +* operating range of the PLL for the GT type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param PllClkOutFreqHz is the frequency to check. +* +* @return +* - XST_SUCCESS if the frequency resides within the PLL's range. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe2CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz) +{ + u32 Status = XST_FAILURE; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) && + (XVPHY_QPLL_LB_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL_LB_MAX)) { + Status = XST_SUCCESS; + } + else if ((ChId >= XVPHY_CHANNEL_ID_CH1) && + (ChId <= XVPHY_CHANNEL_ID_CH4) && + (XVPHY_CPLL_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_CPLL_MAX)) { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the output divider logic for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe2OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for TX/RX dividers. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x88); + + if (Dir == XVPHY_DIR_RX) { + /* Mask out RX_OUT_DIV. */ + DrpVal &= ~0x07; + /* Set RX_OUT_DIV. */ + WriteVal = XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + DrpVal |= WriteVal; + } + else { + /* Mask out TX_OUT_DIV. */ + DrpVal &= ~0x70; + /* Set TX_OUT_DIV. */ + WriteVal = XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + DrpVal |= (WriteVal << 4); + } + /* Write new DRP register value for TX/RX dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x88, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe2ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for PLL dividers. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x5E); + /* Mask out clock divider bits. */ + DrpVal &= ~(0x1FFF); + /* Set CPLL_FBDIV. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 2); + DrpVal |= WriteVal; + /* Set CPLL_FBDIV_45. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 1); + DrpVal |= (WriteVal << 7); + /* Set CPLL_REFCLKDIV. */ + WriteVal = XVphy_MToDrpEncoding(InstancePtr, QuadId, ChId); + DrpVal |= (WriteVal << 8); + /* Write new DRP register value for PLL dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x5E, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the common channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param CmnId is the common channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe2ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for QPLL_CFG. */ + DrpVal = 0x01C1; + /* Mask out QPLL_CFG. */ + DrpVal &= ~(1 << 6); + /* Set QPLL_CFG lower/upper band setting to hardware. */ + WriteVal = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.IsLowerBand; + DrpVal |= (WriteVal << 6); + /* Write new DRP register value for QPLL_CFG. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x32, DrpVal); + + /* Obtain current DRP register value for QPLL_REFCLK_DIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x33); + DrpVal |= 0x0068; + /* Mask out QPLL_REFCLK_DIV. */ + DrpVal &= ~(0xF800); + /* Set QPLL_REFCLK_DIV. */ + WriteVal = XVphy_MToDrpEncoding(InstancePtr, QuadId, CmnId); + DrpVal |= (WriteVal << 11); + /* Write new DRP register value for QPLL_REFCLK_DIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x33, DrpVal); + + /* Obtain current DRP register value for QPLL_FBDIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x36); + /* Mask out QPLL_FBDIV. */ + DrpVal &= ~(0x3FFF); + /* Set QPLL_FBDIV. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, CmnId, 0); + DrpVal |= WriteVal; + /* Write new DRP register value for QPLL_FBDIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x36, DrpVal); + + /* Obtain current DRP register value for QPLL_FBDIV_RATIO. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x37); + /* Mask out QPLL_FBDIV_RATIO. */ + DrpVal &= ~(1 << 6); + /* Set QPLL_FBDIV_RATIO. */ + if (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)].PllParams. + NFbDiv != 66) { + DrpVal |= (1 << 6); + } + /* Write new DRP register value for QPLL_FBDIV_RATIO. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x37, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel's RX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe2RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + u16 DrpVal; + u8 CfgIndex; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + /* RXCDR_CFG(CfgIndex) */ + for (CfgIndex = 0; CfgIndex < 5; CfgIndex++) { + DrpVal = ChPtr->PllParams.Cdr[CfgIndex]; + if (!DrpVal) { + /* Don't modify RX_CDR configuration. */ + continue; + } + XVphy_DrpWrite(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXCDR_CFG(CfgIndex), DrpVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will translate the configured M value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return The DRP encoding for M. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u8 MRefClkDiv; + u8 DrpEncode; + + if ((ChId >= XVPHY_CHANNEL_ID_CH1) && (ChId <= XVPHY_CHANNEL_ID_CH4)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else { + MRefClkDiv = 0; + } + + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(MRefClkDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured D value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return The DRP encoding for D. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u8 OutDiv; + u8 DrpEncode; + + OutDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + OutDiv[Dir]; + + DrpEncode = XVphy_DrpEncodeCpllTxRxD(OutDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured N1/N2 value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param NId specified to operate on N1 (if == 1) or N2 (if == 2). +* +* @return The DRP encoding for N1/N2. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId) +{ + u8 NFbDiv; + u16 DrpEncode; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.NFbDiv; + DrpEncode = XVphy_DrpEncodeQpllN(NFbDiv); + } + else if (NId == 1) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.N1FbDiv; + DrpEncode = XVphy_DrpEncodeCpllN1(NFbDiv); + } + else { + NFbDiv = InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.N2FbDiv; + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(NFbDiv); + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's M or CPLL's M or N2 +* values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's M or CPLL's M or N2 values. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 16; + break; + case 6: + DrpEncode = 5; + break; + case 10: + DrpEncode = 7; + break; + case 12: + DrpEncode = 13; + break; + case 20: + DrpEncode = 15; + break; + case 2: + case 3: + case 4: + case 5: + case 8: + case 16: + DrpEncode = (AttrEncode - 2); + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's N1 value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's N1 value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode) +{ + u8 DrpEncode; + + DrpEncode = AttrEncode - 4; + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's D values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's D value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 0; + break; + case 2: + DrpEncode = 1; + break; + case 4: + DrpEncode = 2; + break; + case 8: + DrpEncode = 3; + break; + case 16: + DrpEncode = 4; + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's N value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's N value. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode) +{ + u16 DrpEncode; + + switch (AttrEncode) { + case 16: + DrpEncode = 0x020; + break; + case 20: + DrpEncode = 0x030; + break; + case 32: + DrpEncode = 0x060; + break; + case 40: + DrpEncode = 0x080; + break; + case 64: + DrpEncode = 0x0E0; + break; + case 66: + DrpEncode = 0x140; + break; + case 80: + DrpEncode = 0x120; + break; + case 100: + DrpEncode = 0x170; + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gthe3.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gthe3.c new file mode 100644 index 00000000..bb5a4d98 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gthe3.c @@ -0,0 +1,865 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_gthe3.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy_gt.h" +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId); +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode); +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode); +static u8 Xvphy_DrpEncodeRxDataWidth(u8 AttrEncode); +static u8 Xvphy_DrpEncodeRxIntDataWidth(u8 AttrEncode); +static u16 XVphy_DrpEncodeClk25(u32 RefClkFreqHz); + +u32 XVphy_Gthe3CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_Gthe3CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz); +u32 XVphy_Gthe3OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_Gthe3ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe3ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId); +u32 XVphy_Gthe3RxChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe3TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); + +/************************** Constant Definitions ******************************/ + +/* DRP register space. */ +#define XVPHY_DRP_RXCDR_CFG(n) (0x0E + n) + +#define XVPHY_DRP_CPLL_FBDIV 0x28 +#define XVPHY_DRP_CPLL_REFCLK_DIV 0x2A +#define XVPHY_DRP_RXOUT_DIV 0x63 +#define XVPHY_DRP_TXCLK25 0x7A +#define XVPHY_DRP_TXOUT_DIV 0x7C +#define XVPHY_DRP_QPLL1_FBDIV 0x94 +#define XVPHY_DRP_QPLL1_REFCLK_DIV 0x98 +#define XVPHY_DRP_RXCDR_CFG_WORD0 0x0E +#define XVPHY_DRP_RXCDR_CFG_WORD1 0x0F +#define XVPHY_DRP_RXCDR_CFG_WORD2 0x10 +#define XVPHY_DRP_RXCDR_CFG_WORD3 0x11 +#define XVPHY_DRP_RXCDR_CFG_WORD4 0x12 + +/* PLL operating ranges. */ +#define XVPHY_QPLL0_MIN 9800000000LL +#define XVPHY_QPLL0_MAX 16300000000LL +#define XVPHY_QPLL1_MIN 8000000000LL +#define XVPHY_QPLL1_MAX 13000000000LL +#define XVPHY_CPLL_MIN 2000000000LL +#define XVPHY_CPLL_MAX 6250000000LL + +const u8 Gthe3CpllDivsM[] = {1, 2, 0}; +const u8 Gthe3CpllDivsN1[] = {4, 5, 0}; +const u8 Gthe3CpllDivsN2[] = {1, 2, 3, 4, 5, 0}; +const u8 Gthe3CpllDivsD[] = {1, 2, 4, 8, 0}; + +const u8 Gthe3QpllDivsM[] = {4, 3, 2, 1, 0}; +const u8 Gthe3QpllDivsN1[] = {16, 20, 32, 40, 64, 66, 80, 100, 160, 0}; +const u8 Gthe3QpllDivsN2[] = {1, 0}; +const u8 Gthe3QpllDivsD[] = {16, 8, 4, 2, 1, 0}; + +const XVphy_GtConfig Gthe3Config = { + .CfgSetCdr = XVphy_Gthe3CfgSetCdr, + .CheckPllOpRange = XVphy_Gthe3CheckPllOpRange, + .OutDivChReconfig = XVphy_Gthe3OutDivChReconfig, + .ClkChReconfig = XVphy_Gthe3ClkChReconfig, + .ClkCmnReconfig = XVphy_Gthe3ClkCmnReconfig, + .RxChReconfig = XVphy_Gthe3RxChReconfig, + .TxPllRefClkDiv1Reconfig = XVphy_Gthe3TxPllRefClkDiv1Reconfig, + + .CpllDivs = { + .M = Gthe3CpllDivsM, + .N1 = Gthe3CpllDivsN1, + .N2 = Gthe3CpllDivsN2, + .D = Gthe3CpllDivsD, + }, + .QpllDivs = { + .M = Gthe3QpllDivsM, + .N1 = Gthe3QpllDivsN1, + .N2 = Gthe3QpllDivsN2, + .D = Gthe3QpllDivsD, + }, +}; + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will set the clock and data recovery (CDR) values for a given +* channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 PllClkInFreqHz; + XVphy_Channel *ChPtr; + u32 Status = XST_SUCCESS; + + /* Set CDR values only for CPLLs. */ + if ((ChId < XVPHY_CHANNEL_ID_CH1) || (ChId > XVPHY_CHANNEL_ID_CH4)) { + return XST_FAILURE; + } + + /* This is DP specific. */ + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + ChPtr->PllParams.Cdr[0] = 0x0000; + ChPtr->PllParams.Cdr[1] = 0x0000; + ChPtr->PllParams.Cdr[3] = 0x0000; + ChPtr->PllParams.Cdr[4] = 0x0000; + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_DP) { + PllClkInFreqHz = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + ChPtr->CpllRefClkSel); + + if ((ChPtr->RxOutDiv == 1) && (PllClkInFreqHz == 270000000)) { + ChPtr->PllParams.Cdr[2] = 0x0766; + } + else if ((ChPtr->RxOutDiv == 2) && + (PllClkInFreqHz == 135000000)) { + ChPtr->PllParams.Cdr[2] = 0x0756; + } + /* RBR does not use DP159 forwarded clock and expects 162MHz. */ + else if (ChPtr->RxOutDiv == 2) { + ChPtr->PllParams.Cdr[2] = 0x0721; + } + else { + Status = XST_FAILURE; + } + } + else if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + /* RxOutDiv = 1 => Cdr[2] = 0x07E4 + * RxOutDiv = 2 => Cdr[2] = 0x07D4 + * RxOutDiv = 4 => Cdr[2] = 0x07C4 + * RxOutDiv = 8 => Cdr[2] = 0x07B4 + * RxOutDiv = 16 => Cdr[2] = 0x07A4 */ + ChPtr->PllParams.Cdr[2] = 0x07E4; + while (ChPtr->RxOutDiv >>= 1) { + ChPtr->PllParams.Cdr[2] -= 0x10; + } + /* Restore RxOutDiv. */ + ChPtr->RxOutDiv = 1 << ((0x7E4 - ChPtr->PllParams.Cdr[2]) >> 4); + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will check if a given PLL output frequency is within the +* operating range of the PLL for the GT type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param PllClkOutFreqHz is the frequency to check. +* +* @return +* - XST_SUCCESS if the frequency resides within the PLL's range. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz) +{ + u32 Status = XST_FAILURE; + + if (((ChId == XVPHY_CHANNEL_ID_CMN0) && + (XVPHY_QPLL0_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL0_MAX)) || + ((ChId == XVPHY_CHANNEL_ID_CMN1) && + (XVPHY_QPLL1_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL1_MAX)) || + ((ChId >= XVPHY_CHANNEL_ID_CH1) && + (ChId <= XVPHY_CHANNEL_ID_CH4) && + (XVPHY_CPLL_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_CPLL_MAX))) { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the output divider logic for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u16 DrpVal; + u16 WriteVal; + if (Dir == XVPHY_DIR_RX) { + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x63); + /* Mask out RX_OUT_DIV. */ + DrpVal &= ~0x07; + /* Set RX_OUT_DIV. */ + WriteVal = XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + DrpVal |= WriteVal; + /* Write new DRP register value for RX dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x63, DrpVal); + } + else { + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x7C); + /* Mask out TX_OUT_DIV. */ + DrpVal &= ~0x700; + /* Set TX_OUT_DIV. */ + WriteVal = XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + DrpVal |= (WriteVal << 8); + /* Write new DRP register value for RX dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x7C, DrpVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for PLL dividers. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x28); + /* Mask out clock divider bits. */ + DrpVal &= ~(0xFF80); + /* Set CPLL_FBDIV. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 2); + DrpVal |= (WriteVal << 8); + /* Set CPLL_FBDIV_45. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 1); + DrpVal |= (WriteVal << 7); + /* Write new DRP register value for PLL dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x28, DrpVal); + + /* Write CPLL Ref Clk Div. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x2A); + /* Mask out clock divider bits. */ + DrpVal &= ~(0xF800); + /* Set CPLL_REFCLKDIV. */ + WriteVal = XVphy_MToDrpEncoding(InstancePtr, QuadId, ChId); + DrpVal |= (WriteVal << 11); + /* Write new DRP register value for PLL dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x2A, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the common channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param CmnId is the common channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for QPLLx_FBDIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x14 : 0x94); + /* Mask out QPLLx_FBDIV. */ + DrpVal &= ~(0xFF); + /* Set QPLLx_FBDIV. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, CmnId, 0); + DrpVal |= WriteVal; + /* Write new DRP register value for QPLLx_FBDIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x14 : 0x94, DrpVal); + + /* Obtain current DRP register value for QPLLx_REFCLK_DIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x18 : 0x98); + /* Mask out QPLLx_REFCLK_DIV. */ + DrpVal &= ~(0xF80); + /* Set QPLLx_REFCLK_DIV. */ + WriteVal = XVphy_MToDrpEncoding(InstancePtr, QuadId, CmnId); + DrpVal |= (WriteVal << 7); + /* Write new DRP register value for QPLLx_REFCLK_DIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x18 : 0x98, DrpVal); + + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + /* QPLLx_LPF */ + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv) { + case 40: + DrpVal = 0x3FF; + break; + case 80: + DrpVal = 0x3F4; + break; + case 160: + DrpVal = 0x3FC; + break; + default: + DrpVal = 0x3FE; + break; + } + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x19 : 0x99, DrpVal); + + /* QPLLx_CP */ + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv) { + case 160: + DrpVal = 0x1FF; + break; + default: + DrpVal = (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x1F : 0x7F; + break; + } + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x16 : 0x96, DrpVal); + + /* QPLLx_CFG4 */ + DrpVal = 0x1B; + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x30 : 0xB0, DrpVal); + /* QPLLx_LOCK_CFG */ + DrpVal = 0x25E8; + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x12 : 0x92, DrpVal); + /* QPLLx_LOCK_CFG_G3 */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x1D : 0x9D, DrpVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel's RX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + u16 DrpVal; + u16 WriteVal; + u8 CfgIndex; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + /* RXCDR_CFG(CfgIndex) */ + for (CfgIndex = 0; CfgIndex < 5; CfgIndex++) { + DrpVal = ChPtr->PllParams.Cdr[CfgIndex]; + if (!DrpVal) { + /* Don't modify RX_CDR configuration. */ + continue; + } + XVphy_DrpWrite(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXCDR_CFG(CfgIndex), DrpVal); + } + + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x66); + DrpVal &= ~(0x3); + WriteVal = Xvphy_DrpEncodeRxIntDataWidth(ChPtr->RxIntDataWidth); + DrpVal |= WriteVal; + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x66, DrpVal); + + /* RX_DATA_WIDTH */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x03); + DrpVal &= ~(0x1E0); + WriteVal = Xvphy_DrpEncodeRxDataWidth(ChPtr->RxDataWidth); + WriteVal <<= 5; + DrpVal |= WriteVal; + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x03, DrpVal); + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function will configure the channel's TX CLKDIV1 settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe3TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, XVPHY_DRP_TXCLK25); + DrpVal &= ~(0xF800); + DrpVal |= XVphy_DrpEncodeClk25(InstancePtr->HdmiTxRefClkHz) << 11; + + return XVphy_DrpWrite(InstancePtr, QuadId, ChId, XVPHY_DRP_TXCLK25, + DrpVal); +} + +/*****************************************************************************/ +/** +* This function will translate the configured M value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return The DRP encoding for M. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u8 MRefClkDiv; + u8 DrpEncode; + + if ((ChId >= XVPHY_CHANNEL_ID_CH1) && (ChId <= XVPHY_CHANNEL_ID_CH4)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else { + MRefClkDiv = 0; + } + + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(MRefClkDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured D value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return The DRP encoding for D. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u8 OutDiv; + u8 DrpEncode; + + OutDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + OutDiv[Dir]; + + DrpEncode = XVphy_DrpEncodeCpllTxRxD(OutDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured N1/N2 value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param NId specified to operate on N1 (if == 1) or N2 (if == 2). +* +* @return The DRP encoding for N1/N2. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId) +{ + u8 NFbDiv; + u16 DrpEncode; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.NFbDiv; + DrpEncode = XVphy_DrpEncodeQpllN(NFbDiv); + } + else if (NId == 1) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.N1FbDiv; + DrpEncode = XVphy_DrpEncodeCpllN1(NFbDiv); + } + else { + NFbDiv = InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.N2FbDiv; + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(NFbDiv); + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's M or CPLL's M or N2 +* values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's M or CPLL's M or N2 values. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 16; + break; + case 6: + DrpEncode = 5; + break; + case 10: + DrpEncode = 7; + break; + case 12: + DrpEncode = 13; + break; + case 20: + DrpEncode = 15; + break; + case 2: + case 3: + case 4: + case 5: + case 8: + case 16: + DrpEncode = (AttrEncode - 2); + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's N1 value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's N1 value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode) +{ + u8 DrpEncode; + + DrpEncode = AttrEncode - 4; + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's D values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's D value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 0; + break; + case 2: + DrpEncode = 1; + break; + case 4: + DrpEncode = 2; + break; + case 8: + DrpEncode = 3; + break; + case 16: + DrpEncode = 4; + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's N value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's N value. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode) +{ + u16 DrpEncode; + + if ((16 <= AttrEncode) && (AttrEncode <= 160)) { + DrpEncode = AttrEncode - 2; + } + else { + DrpEncode = 0xFF; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured RXDATAWIDTH to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the RXDATAWIDTH value. +* +* @note None. +* +******************************************************************************/ +static u8 Xvphy_DrpEncodeRxDataWidth(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 16: + DrpEncode = 2; + break; + case 20: + DrpEncode = 3; + break; + case 32: + DrpEncode = 4; + break; + case 40: + DrpEncode = 5; + break; + case 64: + DrpEncode = 6; + break; + case 80: + DrpEncode = 7; + break; + case 128: + DrpEncode = 8; + break; + case 160: + DrpEncode = 9; + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured RXINTDATAWIDTH to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the RXINTDATAWIDTH value. +* +* @note None. +* +******************************************************************************/ +static u8 Xvphy_DrpEncodeRxIntDataWidth(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 2: + DrpEncode = 0; + break; + case 4: + DrpEncode = 1; + break; + default: + DrpEncode = 2; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CLK25 to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CLK25 value. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_DrpEncodeClk25(u32 RefClkFreqHz) +{ + u16 DrpEncode; + u32 RefClkFreqMHz = RefClkFreqHz / 1000000; + + DrpEncode = ((RefClkFreqMHz / 25) + + (((RefClkFreqMHz % 25) > 0) ? 1 : 0)) - 1; + + return DrpEncode; +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gtxe2.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gtxe2.c new file mode 100644 index 00000000..d9616a50 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_gtxe2.c @@ -0,0 +1,768 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_gtxe2.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy_gt.h" +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId); +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode); +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode); +static u16 XVphy_DrpEncodeClk25(u32 RefClkFreqHz); + +u32 XVphy_Gtxe2CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_Gtxe2CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz); +u32 XVphy_Gtxe2OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_Gtxe2ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gtxe2ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId); +u32 XVphy_Gtxe2RxChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gtxe2TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); + +/************************** Constant Definitions ******************************/ + +/* DRP register space. */ +#define XVPHY_DRP_RXCDR_CFG(n) (0xA8 + n) + +#define XVPHY_DRP_RXDATAWIDTH 0x11 +#define XVPHY_DRP_CPLL_PROG 0x5E +#define XVPHY_DRP_OUT_DIV_PROG 0x88 +#define XVPHY_DRP_QPLL_CFG 0x32 +#define XVPHY_DRP_QPLL_REFCLK_DIV_PROG 0x33 +#define XVPHY_DRP_QPLL_FBDIV_PROG 0x36 +#define XVPHY_DRP_QPLL_FBDIV_RATIO_PROG 0x37 +#define XVPHY_DRP_TXCLK25 0x6A +#define XVPHY_DRP_RXCDR_CFG_WORD0 0xA8 +#define XVPHY_DRP_RXCDR_CFG_WORD1 0xA9 +#define XVPHY_DRP_RXCDR_CFG_WORD2 0xAA +#define XVPHY_DRP_RXCDR_CFG_WORD3 0xAB +#define XVPHY_DRP_RXCDR_CFG_WORD4 0xAC + +/* PLL operating ranges. */ +#define XVPHY_QPLL_LB_MIN 5930000000LL +#define XVPHY_QPLL_LB_MAX 8000000000LL +#define XVPHY_QPLL_UB_MIN 9800000000LL +#define XVPHY_QPLL_UB_MAX 12500000000LL +#define XVPHY_CPLL_MIN 1600000000LL +#define XVPHY_CPLL_MAX 3300000000LL + +const u8 Gtxe2CpllDivsM[] = {1, 2, 0}; +const u8 Gtxe2CpllDivsN1[] = {4, 5, 0}; +const u8 Gtxe2CpllDivsN2[] = {1, 2, 3, 4, 5, 0}; +const u8 Gtxe2CpllDivsD[] = {1, 2, 4, 8, 0}; + +const u8 Gtxe2QpllDivsM[] = {4, 3, 2, 1, 0}; +const u8 Gtxe2QpllDivsN1[] = {16, 20, 32, 40, 64, 66, 80, 100, 0}; +const u8 Gtxe2QpllDivsN2[] = {1, 0}; +const u8 Gtxe2QpllDivsD[] = {8, 4, 2, 1, 0}; + +const XVphy_GtConfig Gtxe2Config = { + .CfgSetCdr = XVphy_Gtxe2CfgSetCdr, + .CheckPllOpRange = XVphy_Gtxe2CheckPllOpRange, + .OutDivChReconfig = XVphy_Gtxe2OutDivChReconfig, + .ClkChReconfig = XVphy_Gtxe2ClkChReconfig, + .ClkCmnReconfig = XVphy_Gtxe2ClkCmnReconfig, + .RxChReconfig = XVphy_Gtxe2RxChReconfig, + .TxPllRefClkDiv1Reconfig = XVphy_Gtxe2TxPllRefClkDiv1Reconfig, + + .CpllDivs = { + .M = Gtxe2CpllDivsM, + .N1 = Gtxe2CpllDivsN1, + .N2 = Gtxe2CpllDivsN2, + .D = Gtxe2CpllDivsD, + }, + .QpllDivs = { + .M = Gtxe2QpllDivsM, + .N1 = Gtxe2QpllDivsN1, + .N2 = Gtxe2QpllDivsN2, + .D = Gtxe2QpllDivsD, + }, +}; + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will set the clock and data recovery (CDR) values for a given +* channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + + /* Set CDR values only for CPLLs. */ + if ((ChId < XVPHY_CHANNEL_ID_CH1) || (ChId > XVPHY_CHANNEL_ID_CH4)) { + return XST_FAILURE; + } + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + ChPtr->PllParams.Cdr[0] = 0x0020; + ChPtr->PllParams.Cdr[2] = 0x23FF; + ChPtr->PllParams.Cdr[3] = + (InstancePtr->Config.RxProtocol != XVPHY_PROTOCOL_HDMI) ? + 0x0000 : 0x8000; + ChPtr->PllParams.Cdr[4] = 0x0003; + + /* Update the RXCDR_CFG2 settings. */ + switch (ChPtr->RxOutDiv) { + case 1: + ChPtr->PllParams.Cdr[1] = (InstancePtr->Config.RxProtocol == + XVPHY_PROTOCOL_DP) ? 0x2040 : 0x1040; + break; + case 2: + ChPtr->PllParams.Cdr[1] = 0x4020; + break; + case 4: + ChPtr->PllParams.Cdr[1] = 0x4010; + break; + case 8: + ChPtr->PllParams.Cdr[1] = 0x4008; + break; + default: + ChPtr->PllParams.Cdr[1] = 0x4010; + break; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will check if a given PLL output frequency is within the +* operating range of the PLL for the GT type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param PllClkOutFreqHz is the frequency to check. +* +* @return +* - XST_SUCCESS if the frequency resides within the PLL's range. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz) +{ + u32 Status = XST_FAILURE; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) && + ((XVPHY_QPLL_LB_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL_LB_MAX))) { + InstancePtr->Quads[QuadId].Cmn0.PllParams.IsLowerBand = 1; + Status = XST_SUCCESS; + } + else if ((ChId == XVPHY_CHANNEL_ID_CMN0) && + ((XVPHY_QPLL_UB_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL_UB_MAX) && + (InstancePtr->Config.RxProtocol != + XVPHY_PROTOCOL_HDMI))) { + InstancePtr->Quads[QuadId].Cmn0.PllParams.IsLowerBand = 0; + Status = XST_SUCCESS; + } + else if ((ChId >= XVPHY_CHANNEL_ID_CH1) && + (ChId <= XVPHY_CHANNEL_ID_CH4) && + (XVPHY_CPLL_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_CPLL_MAX)) { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the output divider logic for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for TX/RX dividers. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x88); + + if (Dir == XVPHY_DIR_RX) { + /* Mask out RX_OUT_DIV. */ + DrpVal &= ~0x07; + /* Set RX_OUT_DIV. */ + WriteVal = XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + DrpVal |= WriteVal; + } + else { + /* Mask out TX_OUT_DIV. */ + DrpVal &= ~0x70; + /* Set TX_OUT_DIV. */ + WriteVal = XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + DrpVal |= (WriteVal << 4); + } + /* Write new DRP register value for TX/RX dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x88, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for PLL dividers. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x5E); + /* Mask out clock divider bits. */ + DrpVal &= ~(0x1FFF); + /* Set CPLL_FBDIV. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 2); + DrpVal |= WriteVal; + /* Set CPLL_FBDIV_45. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 1); + DrpVal |= (WriteVal << 7); + /* Set CPLL_REFCLKDIV. */ + WriteVal = XVphy_MToDrpEncoding(InstancePtr, QuadId, ChId); + DrpVal |= (WriteVal << 8); + /* Write new DRP register value for PLL dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x5E, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the common channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param CmnId is the common channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId) +{ + u16 DrpVal; + u16 WriteVal; + + /* Obtain current DRP register value for QPLL_CFG. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x32); + /* Mask out QPLL_CFG. */ + DrpVal &= ~(1 << 6); + /* Set QPLL_CFG lower/upper band setting to hardware. */ + WriteVal = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.IsLowerBand; + DrpVal |= (WriteVal << 6); + /* Write new DRP register value for QPLL_CFG. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x32, DrpVal); + + /* Obtain current DRP register value for QPLL_REFCLK_DIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x33); + /* Mask out QPLL_REFCLK_DIV. */ + DrpVal &= ~(0xF800); + /* Set QPLL_REFCLK_DIV. */ + WriteVal = XVphy_MToDrpEncoding(InstancePtr, QuadId, CmnId); + DrpVal |= (WriteVal << 11); + /* Write new DRP register value for QPLL_REFCLK_DIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x33, DrpVal); + + /* Obtain current DRP register value for QPLL_FBDIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x36); + /* Mask out QPLL_FBDIV. */ + DrpVal &= ~(0x3FFF); + /* Set QPLL_FBDIV. */ + WriteVal = XVphy_NToDrpEncoding(InstancePtr, QuadId, CmnId, 0); + DrpVal |= WriteVal; + /* Write new DRP register value for QPLL_FBDIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x36, DrpVal); + + /* Obtain current DRP register value for QPLL_FBDIV_RATIO. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, CmnId, 0x37); + /* Mask out QPLL_FBDIV_RATIO. */ + DrpVal &= ~(1 << 6); + /* Set QPLL_FBDIV_RATIO. */ + if (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)].PllParams. + NFbDiv != 66) { + DrpVal |= (1 << 6); + } + /* Write new DRP register value for QPLL_FBDIV_RATIO. */ + XVphy_DrpWrite(InstancePtr, QuadId, CmnId, 0x37, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel's RX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ +/* Missing: RXCDR_LOCK_CFG, RX_LPM_*_CFG, RX_DFE_*_CFG */ + XVphy_Channel *ChPtr; + u16 DrpVal; + u8 CfgIndex; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + /* RXCDR_CFG(CfgIndex) */ + for (CfgIndex = 0; CfgIndex < 5; CfgIndex++) { + DrpVal = ChPtr->PllParams.Cdr[CfgIndex]; + if (!DrpVal) { + /* Don't modify RX_CDR configuration. */ + continue; + } + XVphy_DrpWrite(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXCDR_CFG(CfgIndex), DrpVal); + } + + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + /* Set internal Data width */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXDATAWIDTH); + DrpVal &= ~(0x7800); + if (InstancePtr->HdmiRxDruIsEnabled) { + /* Set internal Data width of the RX GT to 2-byte */ + DrpVal |= (0 << 14); + + /* Set RX Data width of the RX GT to 20 bits */ + DrpVal |= (3 << 11); + } + else { + /* Set internal Data width of the RX GT to 4-byte */ + DrpVal |= (1 << 14); + + /* Set RX Data width of the RX GT to 40 bits */ + DrpVal |= (5 << 11); + } + XVphy_DrpWrite(InstancePtr, QuadId, ChId, XVPHY_DRP_RXDATAWIDTH, + DrpVal); + + /* Set QPLL Lower Band */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x99, 0x8480); + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x9A, 0x1); + + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel's TX CLKDIV1 settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gtxe2TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, XVPHY_DRP_TXCLK25); + DrpVal &= ~(0x1F); + DrpVal |= XVphy_DrpEncodeClk25(InstancePtr->HdmiTxRefClkHz); + + return XVphy_DrpWrite(InstancePtr, QuadId, ChId, XVPHY_DRP_TXCLK25, + DrpVal); +} + +/*****************************************************************************/ +/** +* This function will translate the configured M value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return The DRP encoding for M. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u8 MRefClkDiv; + u8 DrpEncode; + + if ((ChId >= XVPHY_CHANNEL_ID_CH1) && (ChId <= XVPHY_CHANNEL_ID_CH4)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else { + MRefClkDiv = 0; + } + + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(MRefClkDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured D value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return The DRP encoding for D. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u8 OutDiv; + u8 DrpEncode; + + OutDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + OutDiv[Dir]; + + DrpEncode = XVphy_DrpEncodeCpllTxRxD(OutDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured N1/N2 value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param NId specified to operate on N1 (if == 1) or N2 (if == 2). +* +* @return The DRP encoding for N1/N2. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId) +{ + u8 NFbDiv; + u16 DrpEncode; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.NFbDiv; + DrpEncode = XVphy_DrpEncodeQpllN(NFbDiv); + } + else if (NId == 1) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.N1FbDiv; + DrpEncode = XVphy_DrpEncodeCpllN1(NFbDiv); + } + else { + NFbDiv = InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.N2FbDiv; + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(NFbDiv); + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's M or CPLL's M or N2 +* values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's M or CPLL's M or N2 values. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 16; + break; + case 6: + DrpEncode = 5; + break; + case 10: + DrpEncode = 7; + break; + case 12: + DrpEncode = 13; + break; + case 20: + DrpEncode = 15; + break; + case 2: + case 3: + case 4: + case 5: + case 8: + case 16: + DrpEncode = (AttrEncode - 2); + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's N1 value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's N1 value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode) +{ + u8 DrpEncode; + + DrpEncode = AttrEncode - 4; + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's D values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's D value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 0; + break; + case 2: + DrpEncode = 1; + break; + case 4: + DrpEncode = 2; + break; + case 8: + DrpEncode = 3; + break; + case 16: + DrpEncode = 4; + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's N value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's N value. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode) +{ + u16 DrpEncode; + + switch (AttrEncode) { + case 16: + DrpEncode = 0x020; + break; + case 20: + DrpEncode = 0x030; + break; + case 32: + DrpEncode = 0x060; + break; + case 40: + DrpEncode = 0x080; + break; + case 64: + DrpEncode = 0x0E0; + break; + case 66: + DrpEncode = 0x140; + break; + case 80: + DrpEncode = 0x120; + break; + case 100: + DrpEncode = 0x170; + break; + default: + DrpEncode = 0xFF; + break; + } + + return DrpEncode; +} + +static u16 XVphy_DrpEncodeClk25(u32 RefClkFreqHz) +{ + u16 DrpEncode; + u32 RefClkFreqMHz = RefClkFreqHz / 1000000; + + DrpEncode = ((RefClkFreqMHz / 25) + + (((RefClkFreqMHz % 25) > 0) ? 1 : 0)) - 1; + + return DrpEncode; +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi.c new file mode 100644 index 00000000..360f6f11 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi.c @@ -0,0 +1,1948 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi.c + * + * This file contains video PHY functionality specific to the HDMI protocol. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xparameters.h" +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_hdmi.h" + +/****************************** Type Definitions ******************************/ + +typedef struct { + u64 DruLineRate; + u16 PllScale; + u32 Qpll0RefClkMin; + u32 Qpll1RefClkMin; + u32 CpllRefClkMin; + u16 TxMmcmScale; + u32 TxMmcmFvcoMin; + u32 TxMmcmFvcoMax; + u16 RxMmcmScale; + u32 RxMmcmFvcoMin; + u32 RxMmcmFvcoMax; +} XVphy_GtHdmiChars; + +/**************************** Function Prototypes *****************************/ + +extern void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1); +static const XVphy_GtHdmiChars *GetGtHdmiPtr(XVphy *InstancePtr); +static void XVphy_HdmiSetSystemClockSelection(XVphy *InstancePtr, u8 QuadId); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function initializes the Video PHY for HDMI. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param CfgPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * @param SystemFrequency is the system frequency for the HDMI logic + * to be based on. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, + u32 SystemFrequency) +{ + u8 Id, Id0, Id1; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Setup the instance. */ + XVphy_CfgInitialize(InstancePtr, CfgPtr, CfgPtr->BaseAddr); + + /* Set default. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_IDLE; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + } + /* Interrupt Disable. */ + XVphy_IntrDisable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK | + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK | + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE | + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK | + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + + /* Setup HDMI interrupt handler callback*/ + XVphy_HdmiIntrHandlerCallbackInit(InstancePtr); + + /* Configure clock detector. */ + XVphy_ClkDetEnable(InstancePtr, FALSE); + XVphy_ClkDetSetFreqTimeout(InstancePtr, SystemFrequency); + XVphy_ClkDetSetFreqLockThreshold(InstancePtr, + (255 << (XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT))); + + /* Start capturing logs. */ + XVphy_LogReset(InstancePtr); + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_INIT, 0); + + XVphy_HdmiSetSystemClockSelection(InstancePtr, QuadId); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_BufgGtReset(InstancePtr, XVPHY_DIR_TX,TRUE); + XVphy_BufgGtReset(InstancePtr, XVPHY_DIR_RX,TRUE); + XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_TX, 1); + XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_RX, 1); + } + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + XVphy_ResetGtTxRx(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + XVphy_ResetGtTxRx(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + XVphy_PowerDownGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMNA, TRUE); + XVphy_PowerDownGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_MmcmPowerDown(InstancePtr, QuadId, XVPHY_DIR_TX, TRUE); + XVphy_MmcmPowerDown(InstancePtr, QuadId, XVPHY_DIR_RX, TRUE); + XVphy_MmcmReset(InstancePtr, QuadId, XVPHY_DIR_TX, TRUE); + XVphy_MmcmReset(InstancePtr, QuadId, XVPHY_DIR_RX, TRUE); + XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_TX, (FALSE)); + XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_RX, (FALSE)); + + + /* DRU Settings. */ + if (InstancePtr->Config.DruIsPresent) { + XVphy_DruReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_DruEnable(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + XVphy_DruSetGain(InstancePtr, XVPHY_CHANNEL_ID_CHA, 9, 16, 5); + } + + XVphy_SetRxLpm(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + 1); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, Id, 0x1); + XVphy_SetTxPreEmphasis(InstancePtr, QuadId, Id, 0x1); + } + + /* Clear Interrupt Register */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + 0xFFFFFFFF); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + 0xFFFFFFFF); + + /* Interrupt Enable. */ + XVphy_IntrEnable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK | + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK | + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE | + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK | + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + XVphy_ClkDetEnable(InstancePtr, TRUE); + + /* Set the flag to indicate the driver is. */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* Init done. */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_INIT, 1); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function Sets the System Clock Selection +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XVphy_HdmiSetSystemClockSelection(XVphy *InstancePtr, u8 QuadId) +{ + XVphy_PllType XVphy_QPllType; + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_QPllType = XVPHY_PLL_TYPE_QPLL; + } + else { + XVphy_QPllType = XVPHY_PLL_TYPE_QPLL0; + } + + /* Set system clock selections */ + if (InstancePtr->Config.TxSysPllClkSel == + InstancePtr->Config.RxSysPllClkSel) { + if (InstancePtr->Config.RxSysPllClkSel == + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVPHY_PLL_TYPE_CPLL, + XVPHY_PLL_TYPE_CPLL); + } + else { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVphy_QPllType, + XVphy_QPllType); + } + } + else if (InstancePtr->Config.TxSysPllClkSel == + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.TxRefClkSel, + XVPHY_PLL_TYPE_CPLL, + XVphy_QPllType); + } + else { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, + InstancePtr->Config.TxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVphy_QPllType, + XVPHY_PLL_TYPE_CPLL); + } +} + +/*****************************************************************************/ +/** +* This function Updates the VPHY clocking. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param TxSysPllClkSel is the SYSCLKDATA selection for TX. +* @param RxSysPllClkSel is the SYSCLKDATA selection for RX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiUpdateClockSelection(XVphy *InstancePtr, u8 QuadId, + XVphy_SysClkDataSelType TxSysPllClkSel, + XVphy_SysClkDataSelType RxSysPllClkSel) +{ + u8 Id, Id0, Id1; + + /* Reset PLL */ + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + /* Set default. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_IDLE; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + } + + /* Update VPhy Clocking */ + InstancePtr->Config.TxSysPllClkSel = TxSysPllClkSel; + InstancePtr->Config.RxSysPllClkSel = RxSysPllClkSel; + XVphy_HdmiSetSystemClockSelection(InstancePtr, QuadId); +} + +/*****************************************************************************/ +/** +* This function resets the GT TX alignment module. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Reset specifies TRUE/FALSE value to either assert or deassert +* reset on the TX alignment module, respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_TxAlignReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read TX align register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_TX_BUFFER_BYPASS_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Id); + } + + /* Write new value to BUFG_GT register. */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_TX_BUFFER_BYPASS_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function resets the GT TX alignment module. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Start specifies TRUE/FALSE value to either start or ttop the TX +* alignment module, respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_TxAlignStart(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Start) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read TX align register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_TX_BUFFER_BYPASS_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Id); + } + + /* Write new value to BUFG_GT register. */ + if (Start) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_TX_BUFFER_BYPASS_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function enables the VPHY's detector peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the clock detector respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetEnable(XVphy *InstancePtr, u8 Enable) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + + /* Write new value to clkdet ctrl register. */ + if (Enable) { + RegVal |= XVPHY_CLKDET_CTRL_RUN_MASK; + } + else { + RegVal &= ~XVPHY_CLKDET_CTRL_RUN_MASK; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function clears the clock detector TX/RX timer. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetTimerClear(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir) +{ + u32 RegVal; + + /* Read the clock detector control register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + + if (Dir == XVPHY_DIR_TX) { + RegVal |= XVPHY_CLKDET_CTRL_TX_TMR_CLR_MASK; + } + else { + RegVal |= XVPHY_CLKDET_CTRL_RX_TMR_CLR_MASK; + } + + /* Write new value to clkdet ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function resets clock detector TX/RX frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetFreqReset(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + + if (Dir == XVPHY_DIR_TX) { + RegVal |= XVPHY_CLKDET_CTRL_TX_FREQ_RST_MASK; + } + else { + RegVal |= XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK; + } + + /* Write new value to clkdet ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the clock detector frequency lock counter threshold value. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ThresholdVal is the threshold value to be set. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetSetFreqLockThreshold(XVphy *InstancePtr, u16 ThresholdVal) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + RegVal &= ~XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK; + + /* Update with new threshold. */ + RegVal |= (ThresholdVal << XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT); + + /* Write new value to clkdet ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function checks clock detector RX/TX frequency zero indicator bit. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for RX or TX. +* +* @return - TRUE if zero frequency. +* - FALSE otherwise, if non-zero frequency. +* +* @note None. +* +******************************************************************************/ +u8 XVphy_ClkDetCheckFreqZero(XVphy *InstancePtr, XVphy_DirectionType Dir) +{ + u32 MaskVal = 0; + u32 RegVal; + + if (Dir == XVPHY_DIR_TX) { + MaskVal = XVPHY_CLKDET_STAT_TX_FREQ_ZERO_MASK; + } + else { + MaskVal = XVPHY_CLKDET_STAT_RX_FREQ_ZERO_MASK; + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_STAT_REG); + RegVal &= MaskVal; + + if (RegVal) { + return (TRUE); + } + + return (FALSE); +} + +/*****************************************************************************/ +/** +* This function sets clock detector frequency lock counter threshold value. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param TimeoutVal is the timeout value and is normally the system clock +* frequency. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetSetFreqTimeout(XVphy *InstancePtr, u32 TimeoutVal) +{ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_FREQ_TMR_TO_REG, TimeoutVal); +} + +/*****************************************************************************/ +/** +* This function loads the timer to TX/RX in the clock detector. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for RX or TX. +* @param TimeoutVal is the timeout value to store in the clock detector. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetTimerLoad(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, u32 TimeoutVal) +{ + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_CLKDET_TMR_TX_REG; + } + else { + RegOffset = XVPHY_CLKDET_TMR_RX_REG; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, TimeoutVal); +} + +/*****************************************************************************/ +/** +* This function returns the frequency of the RX/TX reference clock as +* measured by the clock detector peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for RX or TX. +* +* @return The measured frequency of the RX/TX reference clock. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkDetGetRefClkFreqHz(XVphy *InstancePtr, XVphy_DirectionType Dir) +{ + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_CLKDET_FREQ_TX_REG; + } + else { + RegOffset = XVPHY_CLKDET_FREQ_RX_REG; + } + + return XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); +} + +/*****************************************************************************/ +/** +* This function returns the frequency of the DRU reference clock as measured by +* the clock detector peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The measured frequency of the DRU reference clock. +* +* @note The design must have a DRU for this function to return a valid +* value. +* +******************************************************************************/ +u32 XVphy_DruGetRefClkFreqHz(XVphy *InstancePtr) +{ + /* Verify argument. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Read clock frequency. */ + return XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_FREQ_DRU_REG); +} + +/*****************************************************************************/ +/** +* This function resets the DRU in the VPHY. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Reset specifies TRUE/FALSE value to either enable or disable +* the DRU respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read DRU ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CTRL_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_DRU_CTRL_RST_MASK(Id); + } + + /* Write DRU ctrl register. */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_DRU_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function enabled/disables the DRU in the VPHY. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the DRU, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruEnable(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Enable) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read DRU ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CTRL_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_DRU_CTRL_EN_MASK(Id); + } + + /* Write DRU ctrl register. */ + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_DRU_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function gets the DRU version +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return None. +* +******************************************************************************/ +u16 XVphy_DruGetVersion(XVphy *InstancePtr) +{ + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_STAT_REG); + RegVal &= XVPHY_DRU_STAT_VERSION_MASK; + RegVal >>= XVPHY_DRU_STAT_VERSION_SHIFT; + + return ((u16)RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the DRU center frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId specifies the channel ID. +* @param CenterFreqHz is the frequency value to set. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruSetCenterFreqHz(XVphy *InstancePtr, XVphy_ChannelId ChId, + u64 CenterFreqHz) +{ + u32 CenterFreqL; + u32 CenterFreqH; + u32 RegOffset; + u8 Id, Id0, Id1; + + /* Split the 64-bit input into 2 32-bit values. */ + CenterFreqL = (u32)CenterFreqHz; + CenterFreqHz >>= 32; + CenterFreqHz &= XVPHY_DRU_CFREQ_H_MASK;; + CenterFreqH = (u32)CenterFreqHz; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegOffset = XVPHY_DRU_CFREQ_L_REG(Id); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, + CenterFreqL); + + RegOffset = XVPHY_DRU_CFREQ_H_REG(Id); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, + CenterFreqH); + } +} + +/*****************************************************************************/ +/** +* This function sets the DRU gain. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param G1 gain value. +* @param G1_P gain value. +* @param G2 gain value. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruSetGain(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 G1, u8 G1_P, + u8 G2) +{ + u32 RegVal; + u32 RegOffset; + u8 Id, Id0, Id1; + + RegVal = G1 & XVPHY_DRU_GAIN_G1_MASK; + RegVal |= (G1_P << XVPHY_DRU_GAIN_G1_P_SHIFT) & + XVPHY_DRU_GAIN_G1_P_MASK; + RegVal |= (G2 << XVPHY_DRU_GAIN_G2_SHIFT) & XVPHY_DRU_GAIN_G2_MASK; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegOffset = XVPHY_DRU_GAIN_REG(Id); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } +} + +/*****************************************************************************/ +/** +* This function calculates the center frequency value for the DRU. +* +* @param InstancePtr is a pointer to the XVphy GT core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return The calculated DRU Center frequency value. +* +* @note According to XAPP875: +* Center_f = fDIN * (2^32)/fdruclk +* The DRU clock is derived from the measured reference clock and +* the current QPLL settings. +* +******************************************************************************/ +u64 XVphy_DruCalcCenterFreqHz(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + u64 DruRefClk; + u64 ClkDetRefClk; + u64 DataRate; + u64 FDin; + u64 FDruClk; + + DruRefClk = XVphy_DruGetRefClkFreqHz(InstancePtr); + ClkDetRefClk = XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_RX); + + /* Take the master channel (channel 1). */ + ChPtr = &InstancePtr->Quads[QuadId].Ch1; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + FDruClk = (DruRefClk * InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.NFbDiv) / + (ChPtr->RxOutDiv * 20); + } + else { + FDruClk = (DruRefClk * ChPtr->PllParams.N1FbDiv * + ChPtr->PllParams.N2FbDiv * 2) / + (ChPtr->PllParams.MRefClkDiv * ChPtr->RxOutDiv * 20); + } + + DataRate = 10 * ClkDetRefClk; + FDin = DataRate * ((u64)1 << 32); + + /* Check for divide by zero. */ + if (FDin && FDruClk) { + return (FDin / FDruClk); + } + return 0; +} + +/*****************************************************************************/ +/** +* This function sets the GT RX CDR and Equalization for DRU mode. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Enable enables the DRU logic (when 1), or disables (when 0). +* +* @return None. +* +******************************************************************************/ +void XVphy_HdmiGtDruModeEnable(XVphy *InstancePtr, u8 Enable) +{ + u32 RegVal; + u32 RegMask; + u8 Id, Id0, Id1; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_RX_EQ_CDR_REG); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegMask |= XVPHY_RX_STATUS_RXCDRHOLD_MASK(Id) | + XVPHY_RX_STATUS_RXOSOVRDEN_MASK(Id) | + XVPHY_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Id) | + XVPHY_RX_STATUS_RXLPMHFOVRDEN_MASK(Id); + } + + if (Enable) { + RegVal |= RegMask; + } + else { + RegVal &= ~RegMask; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_RX_EQ_CDR_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function calculates the HDMI MMCM parameters. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* @param Ppc specifies the total number of pixels per clock. +* - 1 = XVIDC_PPC_1 +* - 2 = XVIDC_PPC_2 +* - 4 = XVIDC_PPC_4 +* @param Bpc specifies the color depth/bits per color component. +* - 6 = XVIDC_BPC_6 +* - 8 = XVIDC_BPC_8 +* - 10 = XVIDC_BPC_10 +* - 12 = XVIDC_BPC_12 +* - 16 = XVIDC_BPC_16 +* +* @return +* - XST_SUCCESS if calculated PLL parameters updated successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_HdmiCfgCalcMmcmParam(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc) +{ + u32 RefClk; + u8 Div; + u8 Mult; + u8 Valid; + u64 LineRate; + XVphy_Mmcm *MmcmPtr; + + if (Dir == XVPHY_DIR_RX) { + RefClk = InstancePtr->HdmiRxRefClkHz; + MmcmPtr= &InstancePtr->Quads[QuadId].RxMmcm; + + RefClk = RefClk / (GetGtHdmiPtr(InstancePtr))->RxMmcmScale; + Mult = (GetGtHdmiPtr(InstancePtr))->RxMmcmFvcoMax / RefClk; + } + else { + RefClk = InstancePtr->HdmiTxRefClkHz; + MmcmPtr= &InstancePtr->Quads[QuadId].TxMmcm; + + RefClk = RefClk / (GetGtHdmiPtr(InstancePtr))->TxMmcmScale; + Mult = (GetGtHdmiPtr(InstancePtr))->TxMmcmFvcoMax / RefClk; + + /* Get line rate. */ + if (XVphy_IsTxUsingQpll(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + LineRate = InstancePtr->Quads[QuadId].Cmn0.LineRateHz; + } + else { + LineRate = InstancePtr->Quads[QuadId].Ch1.LineRateHz; + } + } + + Div = 1; + + /* In case of 4 pixels per clock, the M must be a multiple of four. */ + if (Ppc == XVIDC_PPC_4) { + Mult = Mult / 4; + Mult = Mult * 4; + } + /* Else the M must be a multiple of two. */ + else { + Mult = Mult / 2; + Mult = Mult * 2; + } + + if (!((Mult > 1) && (Mult < 65))) { + return (XST_FAILURE); /* Mult is out of range. */ + } + + Valid = (FALSE); + do { + MmcmPtr->ClkFbOutMult = Mult; + MmcmPtr->DivClkDivide = Div; + + /* Link clock: TMDS clock ratio 1/40. */ + if ((LineRate / 1000000) >= 3400) { + MmcmPtr->ClkOut0Div = Mult; + } + /* Link clock: TMDS clock ratio 1/10. */ + else { + MmcmPtr->ClkOut0Div = Mult * 4; + } + + /* TMDS Clock */ + MmcmPtr->ClkOut1Div = Mult * ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1); + + /* Video clock. */ + switch (Bpc) { + case XVIDC_BPC_10: + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 5 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + else { + MmcmPtr->ClkOut2Div = (Mult * 5 / 2 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + case XVIDC_BPC_12: + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 6 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + else { + MmcmPtr->ClkOut2Div = (Mult * 3 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + case XVIDC_BPC_16 : + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 8 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + else { + MmcmPtr->ClkOut2Div = (Mult * 4 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + case XVIDC_BPC_8: + default: + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 4 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + else { + MmcmPtr->ClkOut2Div = (Mult * 2 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + } + + if (Dir == XVPHY_DIR_RX) { + /* Correct divider value if TMDS clock ratio is 1/40. */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + if ((MmcmPtr->ClkOut2Div % 4) == 0) { + MmcmPtr->ClkOut2Div = + MmcmPtr->ClkOut2Div / 4; + } + /* Not divisible by 4: repeat loop with a lower + * multiply value. */ + else { + MmcmPtr->ClkOut2Div = 255; + } + } + } + /* TX. */ + else if ((LineRate / 1000000) >= 3400) { + if ((MmcmPtr->ClkOut2Div % 4) == 0) { + MmcmPtr->ClkOut2Div = + MmcmPtr->ClkOut2Div / 4; + } + /* Not divisible by 4: repeat loop with a lower + * multiply value. */ + else { + MmcmPtr->ClkOut2Div = 255; + } + } + + /* Check values. */ + if ((MmcmPtr->ClkOut0Div <= 128) && + (MmcmPtr->ClkOut1Div <= 128) && + (MmcmPtr->ClkOut2Div <= 128)) { + Valid = (TRUE); + } + /* 4 pixels per clock. */ + else if (Ppc == (XVIDC_PPC_4)) { + /* Decrease Mult value. */ + Mult -= 4; + } + /* 2 pixels per clock. */ + else { + /* Decrease M value. */ + Mult -= 2; + } + } while (!Valid); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function calculates the QPLL parameters. +* +* @param InstancePtr is a pointer to the HDMI GT core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if calculated QPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_HdmiQpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + u64 RefClk; + u32 *RefClkPtr; + u64 TxLineRate; + u8 Id, Id0, Id1; + + u8 SRArray[] = {1, 3, 5}; + u8 SRIndex; + u8 SRValue; + + XVphy_SysClkDataSelType SysClkDataSel; + XVphy_SysClkOutSelType SysClkOutSel; + XVphy_ChannelId ActiveCmnId; + + u32 QpllRefClk; + u32 QpllClkMin; + + /* Determine QPLL reference clock from the first (master) channel. */ + if (Dir == XVPHY_DIR_RX) { + QpllRefClk = InstancePtr->HdmiRxRefClkHz; + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + } + else { + QpllRefClk = InstancePtr->HdmiTxRefClkHz; + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + } + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + /* Determine which QPLL to use. */ + if (((101875000 <= QpllRefClk) && (QpllRefClk <= 122500000)) || + ((203750000 <= QpllRefClk) && + (QpllRefClk <= 245000000)) || + ((407000000 <= QpllRefClk) && + (QpllRefClk <= 490000000))) { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN1; + QpllClkMin = (u32) XVPHY_HDMI_GTHE3_QPLL1_REFCLK_MIN; + } + else { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN0; + QpllClkMin = (u32) XVPHY_HDMI_GTHE3_QPLL0_REFCLK_MIN; + } + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE2) { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN; + QpllClkMin = (GetGtHdmiPtr(InstancePtr))->Qpll0RefClkMin; + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN; + QpllClkMin = (GetGtHdmiPtr(InstancePtr))->Qpll0RefClkMin; + } + + /* Update QPLL clock selections. */ + XVphy_CfgSysClkDataSel(InstancePtr, QuadId, Dir, SysClkDataSel); + XVphy_CfgSysClkOutSel(InstancePtr, QuadId, Dir, SysClkOutSel); + + /* RX is using QPLL. */ + if (Dir == XVPHY_DIR_RX) { + /* Check if the reference clock is not below the minimum QPLL + * input frequency. */ + if (QpllRefClk >= QpllClkMin) { + RefClk = QpllRefClk; + + /* Scaled line rate. */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, (RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, (RefClk * 10)); + } + + /* Clear DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Set RX data width to 40 and 4 bytes. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxIntDataWidth = 4; + } + + } + /* The reference clock is below the minimum frequency thus + * select the DRU. */ + else if (InstancePtr->Config.DruIsPresent) { + RefClk = XVphy_DruGetRefClkFreqHz(InstancePtr); + + /* Round input frequency to 10 kHz. */ + RefClk = RefClk / 10000; + RefClk = RefClk * 10000; + + /* Set the DRU to operate at a linerate of 2.5 Gbps. */ + XVphy_CfgLineRate(InstancePtr, + QuadId, XVPHY_CHANNEL_ID_CMNA, + (GetGtHdmiPtr(InstancePtr))->DruLineRate); + + /* Set DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 1; + + /* Set RX data width to 40 and 4 bytes. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxIntDataWidth = 2; + } + } + else { + xil_printf("Low resolution video isn't supported in " + "this version.\r\n No DRU instance found.\r\n"); + return (XST_FAILURE); + } + } + + /* TX is using QPLL. */ + else { + /* Update TX line rates. */ + XVphy_CfgLineRate(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMNA, + (u64)((*RefClkPtr) * 10)); + TxLineRate = (*RefClkPtr) / 100000;; + + /* Set default TX sample rate. */ + InstancePtr->HdmiTxSampleRate = 1; + + /* Check if the linerate is above the 340 Mcsc. */ + if ((TxLineRate) >= 3400) { + (*RefClkPtr) = (*RefClkPtr) / 4; + } + } + + /* Calculate QPLL values. */ + for (SRIndex = 0; SRIndex < sizeof(SRArray); SRIndex++) { + /* Only use oversampling when then TX is using the QPLL. */ + if (Dir == XVPHY_DIR_TX) { + SRValue = SRArray[SRIndex]; + + /* TX reference clock is below the minimum QPLL clock + * input frequency. */ + if ((*RefClkPtr) < QpllClkMin) { + RefClk = ((*RefClkPtr) * SRValue); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 10)); + } + } + /* TX reference clock is in QPLL clock input range. + * In this case don't increase the reference clock, but + * increase the line rate. */ + else { + RefClk = (*RefClkPtr); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 40 *SRValue)); + } + + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 10 *SRValue)); + } + } + } + /* For all other reference clocks force sample rate to one. */ + else { + SRValue = 1; + } + + Status = XVphy_ClkCalcParams(InstancePtr, QuadId, ActiveCmnId, + Dir, RefClk); + if (Status == (XST_SUCCESS)) { + /* Only execute when the TX is using the QPLL. */ + if (Dir == XVPHY_DIR_TX) { + /* Set TX sample rate. */ + InstancePtr->HdmiTxSampleRate = SRValue; + + /* Update reference clock only when the + * reference clock is below the minimum QPLL + * input frequency. */ + if ((*RefClkPtr) < QpllClkMin) { + (*RefClkPtr) = (*RefClkPtr) * SRValue; + } + else if (SRValue > 1) { + xil_printf("\n\rCouldn't find the " + "correct GT parameters for this " + "video resolution.\n\r"); + xil_printf("Try another GT PLL layout." + "\n\r"); + return (XST_FAILURE); + } + } + return (XST_SUCCESS); + } + } + xil_printf("QPLL config not found!\r\n"); + return (XST_FAILURE); +} + +/*****************************************************************************/ +/** +* This function calculates the CPLL parameters. +* +* @param InstancePtr is a pointer to the HDMI GT core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if calculated CPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_HdmiCpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + u64 RefClk; + u32 *RefClkPtr; + u32 TxLineRate; + u8 ChIndex; + u8 Id, Id0, Id1; + + u8 SRArray[] = {1, 3, 5}; + u8 SRIndex; + u8 SRValue; + + /* TX is using CPLL. */ + if ((Dir == XVPHY_DIR_TX) && (!XVphy_IsBonded(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1))) { + + /* Set default TX sample rate. */ + InstancePtr->HdmiTxSampleRate = 1; + + /* Set line rate. */ + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + XVphy_CfgLineRate(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + (u64)((*RefClkPtr) * 10)); + TxLineRate = (*RefClkPtr) / 100000; + + /* Check if the line rate is above the 340 Mcsc. */ + if (TxLineRate >= 3400) { + (*RefClkPtr) = (*RefClkPtr) / 4; + } + } + /* RX is using CPLL. */ + else { + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + + /* Check if the reference clock is not below the minimum CPLL + * input frequency. */ + if ((*RefClkPtr) >= + (GetGtHdmiPtr(InstancePtr))->CpllRefClkMin) { + RefClk = (*RefClkPtr); + + /* Scaled linerate */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, (RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, (RefClk * 10)); + } + + /* Clear DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Set RX data width to 40 and 4 bytes. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxIntDataWidth = 4; + } + + } + /* The reference clock is below the minimum frequency thus + * select the DRU. */ + else { + if (InstancePtr->Config.DruIsPresent) { + RefClk = XVphy_DruGetRefClkFreqHz(InstancePtr); + + /* Round input frequency to 100 kHz. */ + RefClk = RefClk / 10000; + RefClk = RefClk * 10000; + + /* Set the DRU to operate at a linerate of + * 2.5 Gbps. */ + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, + (GetGtHdmiPtr(InstancePtr))-> + DruLineRate); + + /* Set DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 1; + + /* Set RX data width to 40 and 4 bytes. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + + if (TxLineRate > (((GetGtHdmiPtr(InstancePtr)) + ->DruLineRate) / 1000000)) { + xil_printf("Warning: " + "This video format is not " + "supported by this device\r\n"); + xil_printf(" " + "Change to another format\r\n"); + } + } + else { + xil_printf("Low resolution video isn't " + "supported in this version.\r\n" + "No DRU instance found.\r\n"); + return (XST_FAILURE); + } + } + } + + /* Try different sample rates. */ + for (SRIndex = 0; SRIndex < sizeof(SRArray); SRIndex++) { + /* Only use oversampling when then TX is using the CPLL. */ + if ((Dir == XVPHY_DIR_TX) && (!XVphy_IsBonded(InstancePtr, + QuadId, XVPHY_CHANNEL_ID_CH1))) { + SRValue = SRArray[SRIndex]; + + /* Multiply the reference clock with the sample rate + * value. */ + RefClk = ((*RefClkPtr) * SRValue); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, (RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, (RefClk * 10)); + } + } + /* For all other reference clocks force sample rate to one. */ + else { + SRValue = 1; + } + + Status = XVphy_ClkCalcParams(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, Dir, RefClk); + if (Status == (XST_SUCCESS)) { + /* Only execute when the TX is using the QPLL. */ + if ((Dir == XVPHY_DIR_TX) && (!XVphy_IsBonded( + InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1))) { + InstancePtr->HdmiTxSampleRate = SRValue; + + (*RefClkPtr) = (*RefClkPtr) * SRValue; + } + return (XST_SUCCESS); + } + } + + xil_printf("CPLL config not found!\r\n"); + return (XST_FAILURE); +} + +/*****************************************************************************/ +/** +* This function update/set the HDMI TX parameter. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Ppc is the pixels per clock to set. +* @param Bpc is the bits per color to set. +* @param ColorFormat is the color format to set. +* +* @return +* - XST_SUCCESS if TX parameters set/updated. +* - XST_FAILURE if low resolution video not supported. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_SetHdmiTxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc, + XVidC_ColorFormat ColorFormat) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((Ppc == (XVIDC_PPC_2)) || (Ppc == (XVIDC_PPC_4))); + Xil_AssertNonvoid((Bpc == (XVIDC_BPC_8)) || (Bpc == (XVIDC_BPC_10)) || + (Bpc == (XVIDC_BPC_12)) || (Bpc == (XVIDC_BPC_16))); + Xil_AssertNonvoid((ColorFormat == (XVIDC_CSF_RGB)) || + (ColorFormat == (XVIDC_CSF_YCRCB_444)) || + (ColorFormat == (XVIDC_CSF_YCRCB_422)) || + (ColorFormat == (XVIDC_CSF_YCRCB_420))); + + /* Only calculate the QPLL/CPLL parameters when the GT TX and RX are not + * coupled. */ + if (!XVphy_IsBonded(InstancePtr, QuadId, ChId)) { + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + Status = XVphy_HdmiCpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + } + else { + Status = XVphy_HdmiQpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + /* Update SysClk and PLL Clk registers immediately. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, QuadId); + + } + } + /* Bonded mode. */ + else { + /* Copy reference clock. */ + InstancePtr->HdmiTxRefClkHz = InstancePtr->HdmiRxRefClkHz; + + /* Copy the line rate. */ + if (XVphy_IsRxUsingQpll(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1)) { + InstancePtr->Quads[QuadId].Ch1.LineRateHz = + InstancePtr->Quads[QuadId].Cmn0.LineRateHz; + } + else { + InstancePtr->Quads[QuadId].Cmn0.LineRateHz = + InstancePtr->Quads[QuadId].Ch1.LineRateHz; + } + + InstancePtr->HdmiTxSampleRate = 1; + + Status = (XST_SUCCESS); + } + + if (Status == (XST_SUCCESS)) { + /* Calculate TXPLL parameters. + * In HDMI the colordepth in YUV422 is always 12 bits, + * although on the link itself it is being transmitted as + * 8-bits. Therefore if the colorspace is YUV422, then force the + * colordepth to 8 bits. */ + if (ColorFormat == XVIDC_CSF_YCRCB_422) { + Status = XVphy_HdmiCfgCalcMmcmParam(InstancePtr, QuadId, + ChId, XVPHY_DIR_TX, Ppc, XVIDC_BPC_8); + } + /* Other colorspaces. */ + else { + Status = XVphy_HdmiCfgCalcMmcmParam(InstancePtr, QuadId, + ChId, XVPHY_DIR_TX, Ppc, Bpc); + } + + Status = (XST_SUCCESS); + } + else { + Status = (XST_FAILURE); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function update/set the HDMI RX parameter. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if RX parameters set/updated. +* - XST_FAILURE if low resolution video not supported. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_SetHdmiRxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 Status; + u64 DruCenterFreq; + u8 Id, Id0, Id1; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + Status = XVphy_HdmiCpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + } + else { + Status = XVphy_HdmiQpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + /* Update SysClk and PLL Clk registers immediately */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, QuadId); + } + + if (XVphy_IsBonded(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CH1)) { + /* Same divisor value for all channels. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + TxOutDiv = InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(Id)].RxOutDiv; + } + } + + + if (InstancePtr->HdmiRxDruIsEnabled) { + DruCenterFreq = XVphy_DruCalcCenterFreqHz(InstancePtr, QuadId, + ChId); + XVphy_DruSetCenterFreqHz(InstancePtr, XVPHY_CHANNEL_ID_CHA, + DruCenterFreq); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function prints Video PHY debug information related to HDMI. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 RegValue; + XVphy_Channel *ChPtr; + XVphy_ChannelId CmnId; + u8 CpllDVal; + u8 QpllDVal; + u8 UsesQpll0; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[0]; + + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("TX => CPLL / "); + } + else { + if ((ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) || + (ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK)) { + UsesQpll0 = (TRUE); + CmnId = XVPHY_CHANNEL_ID_CMN0; + } + else { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN1; + } + xil_printf("TX => QPLL%d / ", (UsesQpll0 ? 0 : 1)); + } + + if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("RX => CPLL\n\r"); + } + else { + if ((ChPtr->RxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) || + (ChPtr->RxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK)) { + UsesQpll0 = (TRUE); + CmnId = XVPHY_CHANNEL_ID_CMN0; + } + else { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN1; + } + xil_printf("RX => QPLL%d\n\r", (UsesQpll0 ? 0 : 1)); + } + + xil_printf("RX state: "); + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].RxState) { + case (XVPHY_GT_STATE_IDLE): + xil_printf("idle\n\r"); + break; + case (XVPHY_GT_STATE_LOCK): + if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("CPLL lock\n\r"); + } + else { + xil_printf("QPLL%d lock\n\r", (UsesQpll0 ? 0 : 1)); + } + break; + case (XVPHY_GT_STATE_RESET): + xil_printf("GT reset\n\r"); + break; + case (XVPHY_GT_STATE_READY): + xil_printf("ready\n\r"); + break; + default: + xil_printf("unknown\n\r"); + break; + } + + xil_printf("TX state: "); + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].TxState) { + case (XVPHY_GT_STATE_IDLE): + xil_printf("idle\n\r"); + break; + case (XVPHY_GT_STATE_LOCK): + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("CPLL lock\n\r"); + } + else { + xil_printf("QPLL%d lock\n\r", (UsesQpll0 ? 0 : 1)); + } + break; + case (XVPHY_GT_STATE_RESET): + xil_printf("GT reset\n\r"); + break; + case (XVPHY_GT_STATE_ALIGN): + xil_printf("align\n\r"); + break; + case (XVPHY_GT_STATE_READY): + xil_printf("ready\n\r"); + break; + default: + xil_printf("unknown\n\r"); + break; + } + + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + QpllDVal = ChPtr->RxOutDiv; + CpllDVal = ChPtr->TxOutDiv; + } + else { + CpllDVal = ChPtr->RxOutDiv; + QpllDVal = ChPtr->TxOutDiv; + } + + xil_printf("\n\r"); + xil_printf("QPLL%d settings\n\r", (UsesQpll0 ? 0 : 1)); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N : %d - D : %d\n\r", + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.MRefClkDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv, QpllDVal); + xil_printf("\n\r"); + + xil_printf("CPLL settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N1 : %d - N2 : %d - D : %d\n\r", + ChPtr->PllParams.MRefClkDiv, + ChPtr->PllParams.N1FbDiv, + ChPtr->PllParams.N2FbDiv, + CpllDVal); + xil_printf("\n\r"); + + xil_printf("RX MMCM settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("Mult : %d - Div : %d - Clk0Div : %d - Clk1Div : %d - " + "Clk2Div : %d\n\r", + InstancePtr->Quads[QuadId].RxMmcm.ClkFbOutMult, + InstancePtr->Quads[QuadId].RxMmcm.DivClkDivide, + InstancePtr->Quads[QuadId].RxMmcm.ClkOut0Div, + InstancePtr->Quads[QuadId].RxMmcm.ClkOut1Div, + InstancePtr->Quads[QuadId].RxMmcm.ClkOut2Div); + xil_printf("\n\r"); + + xil_printf("TX MMCM settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("Mult : %d - Div : %d - Clk0Div : %d - Clk1Div : %d - " + "Clk2Div : %d\n\r", + InstancePtr->Quads[QuadId].TxMmcm.ClkFbOutMult, + InstancePtr->Quads[QuadId].TxMmcm.DivClkDivide, + InstancePtr->Quads[QuadId].TxMmcm.ClkOut0Div, + InstancePtr->Quads[QuadId].TxMmcm.ClkOut1Div, + InstancePtr->Quads[QuadId].TxMmcm.ClkOut2Div); + xil_printf("\n\r"); + + if (InstancePtr->Config.DruIsPresent) { + xil_printf("DRU Settings\n\r"); + xil_printf("-------------\n\r"); + RegValue = XVphy_DruGetVersion(InstancePtr); + xil_printf("Version : %d\n\r", RegValue); + + if (InstancePtr->HdmiRxDruIsEnabled) { + RegValue = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_GAIN_REG(ChId)); + + xil_printf("G1 : %d\n\rG1_P : %d\n\r" + "G2 : %d\n\r", + ((RegValue & XVPHY_DRU_GAIN_G1_MASK)), + ((RegValue & XVPHY_DRU_GAIN_G1_P_MASK) >> + XVPHY_DRU_GAIN_G1_P_SHIFT), + ((RegValue & XVPHY_DRU_GAIN_G2_MASK) >> + XVPHY_DRU_GAIN_G2_SHIFT)); + + RegValue = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CFREQ_H_REG(ChId)); + xil_printf("Center_F : %x", RegValue); + + RegValue = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CFREQ_L_REG(ChId)); + xil_printf("%x\n\r", RegValue); + } + else { + xil_printf("DRU is disabled\n\r"); + } + + xil_printf(" \n\r"); + } +} + +static const XVphy_GtHdmiChars Gthe3HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTHE3_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTHE3_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTHE3_QPLL0_REFCLK_MIN, + .Qpll1RefClkMin = XVPHY_HDMI_GTHE3_QPLL1_REFCLK_MIN, + .CpllRefClkMin = XVPHY_HDMI_GTHE3_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTHE3_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTHE3_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MAX, +}; +static const XVphy_GtHdmiChars Gthe2HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTHE2_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTHE2_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTHE2_QPLL_REFCLK_MIN, + .Qpll1RefClkMin = 0, + .CpllRefClkMin = XVPHY_HDMI_GTHE2_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTHE2_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTHE2_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MAX, +}; +static const XVphy_GtHdmiChars Gtxe2HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTXE2_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTXE2_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTXE2_QPLL_REFCLK_MIN, + .Qpll1RefClkMin = 0, + .CpllRefClkMin = XVPHY_HDMI_GTXE2_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTXE2_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTXE2_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MAX, +}; + +/*****************************************************************************/ +/** +* This function returns a pointer to the HDMI parameters based on the GT type. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - A pointer to the HDMI GT characteristics. +* - NULL if the GT type is unsupported. +* +* @note None. +* +******************************************************************************/ +static const XVphy_GtHdmiChars *GetGtHdmiPtr(XVphy *InstancePtr) +{ + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + return &Gtxe2HdmiChars; + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE2) { + return &Gthe2HdmiChars; + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + return &Gthe3HdmiChars; + } + + return NULL; +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi.h b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi.h new file mode 100644 index 00000000..a39f58e7 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi.h @@ -0,0 +1,120 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +#ifndef XVPHY_HDMI_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_HDMI_H_ + +/************************** Constant Definitions ******************************/ + +#define XVPHY_HDMI_GTHE3_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTHE3_PLL_SCALE 1000 +#define XVPHY_HDMI_GTHE3_QPLL0_REFCLK_MIN 61250000LL +#define XVPHY_HDMI_GTHE3_QPLL1_REFCLK_MIN 50000000LL +#define XVPHY_HDMI_GTHE3_CPLL_REFCLK_MIN 100000000LL +#define XVPHY_HDMI_GTHE3_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MAX 1200000000U +#define XVPHY_HDMI_GTHE3_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MAX 1200000000U + +#define XVPHY_HDMI_GTHE2_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTHE2_PLL_SCALE 1000 +#define XVPHY_HDMI_GTHE2_QPLL_REFCLK_MIN 61250000LL +#define XVPHY_HDMI_GTHE2_CPLL_REFCLK_MIN 80000000LL +#define XVPHY_HDMI_GTHE2_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MAX 1200000000U +#define XVPHY_HDMI_GTHE2_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MAX 1200000000U + +#define XVPHY_HDMI_GTXE2_DRU_LRATE 2000000000U +#define XVPHY_HDMI_GTXE2_PLL_SCALE 1000 +#define XVPHY_HDMI_GTXE2_QPLL_REFCLK_MIN 74125000LL +#define XVPHY_HDMI_GTXE2_CPLL_REFCLK_MIN 80000000LL +#define XVPHY_HDMI_GTXE2_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MIN 800000000U +#define XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MAX 1866000000U +#define XVPHY_HDMI_GTXE2_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MAX 1200000000U + +/**************************** Function Prototypes *****************************/ + +u32 XVphy_HdmiQpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_HdmiCpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +void XVphy_TxAlignReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset); +void XVphy_TxAlignStart(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Start); +void XVphy_ClkDetEnable(XVphy *InstancePtr, u8 Enable); +void XVphy_ClkDetTimerClear(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +void XVphy_ClkDetSetFreqLockThreshold(XVphy *InstancePtr, u16 ThresholdVal); +u8 XVphy_ClkDetCheckFreqZero(XVphy *InstancePtr, XVphy_DirectionType Dir); +void XVphy_ClkDetSetFreqTimeout(XVphy *InstancePtr, u32 TimeoutVal); +void XVphy_ClkDetTimerLoad(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, u32 TimeoutVal); +void XVphy_DruReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset); +void XVphy_DruEnable(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Enable); +u16 XVphy_DruGetVersion(XVphy *InstancePtr); +void XVphy_DruSetCenterFreqHz(XVphy *InstancePtr, XVphy_ChannelId ChId, + u64 CenterFreqHz); +void XVphy_DruSetGain(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 G1, u8 G1_P, + u8 G2); +u64 XVphy_DruCalcCenterFreqHz(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +void XVphy_HdmiGtDruModeEnable(XVphy *InstancePtr, u8 Enable); +void XVphy_HdmiIntrHandlerCallbackInit(XVphy *InstancePtr); + +#endif /* XVPHY_HDMI_H_ */ diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi_intr.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi_intr.c new file mode 100644 index 00000000..f2b498e8 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hdmi_intr.c @@ -0,0 +1,954 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi_intr.c + * + * This file contains video PHY functionality specific to the HDMI protocol + * related to interrupts. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xparameters.h" +#include "xintc.h" +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_hdmi.h" +# include "xvphy_gt.h" + +/************************** Function Prototypes ******************************/ + +extern void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1); + +static void XVphy_HdmiGtHandler(XVphy *InstancePtr); +static void XVphy_ClkDetHandler(XVphy *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** +* This function installs an HDMI callback function for the specified handler +* type +* +* @param InstancePtr is a pointer to the XVPhy instance. +* @param HandlerType is the interrupt handler type which specifies which +* interrupt event to attach the callback for. +* @param CallbackFunc is the address to the callback function. +* @param CallbackRef is the user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void XVphy_SetHdmiCallback(XVphy *InstancePtr, + XVphy_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((HandlerType == XVPHY_HDMI_HANDLER_TXINIT) || + (HandlerType == XVPHY_HDMI_HANDLER_TXREADY) || + (HandlerType == XVPHY_HDMI_HANDLER_RXINIT) || + (HandlerType == XVPHY_HDMI_HANDLER_RXREADY)); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + switch (HandlerType) { + case XVPHY_HDMI_HANDLER_TXINIT: + InstancePtr->HdmiTxInitCallback = CallbackFunc; + InstancePtr->HdmiTxInitRef = CallbackRef; + break; + + case XVPHY_HDMI_HANDLER_TXREADY: + InstancePtr->HdmiTxReadyCallback = CallbackFunc; + InstancePtr->HdmiTxReadyRef = CallbackRef; + break; + + case XVPHY_HDMI_HANDLER_RXINIT: + InstancePtr->HdmiRxInitCallback = CallbackFunc; + InstancePtr->HdmiRxInitRef = CallbackRef; + break; + + case XVPHY_HDMI_HANDLER_RXREADY: + InstancePtr->HdmiRxReadyCallback = CallbackFunc; + InstancePtr->HdmiRxReadyRef = CallbackRef; + break; + + default: + break; + } +} + +/*****************************************************************************/ +/** +* This function sets the appropriate HDMI interupt handlers. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiIntrHandlerCallbackInit(XVphy *InstancePtr) +{ + /* GT Interrupts */ + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + /* Clock Detector Interrupts */ + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by QPLL lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiQpllLockHandler(XVphy *InstancePtr) +{ + XVphy_GtState *TxStatePtr; + XVphy_GtState *RxStatePtr; + XVphy_PllType TxPllType; + XVphy_PllType RxPllType; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_QPLL_LOCK, 1); + + TxStatePtr = &InstancePtr->Quads[0].Plls[0].TxState; + RxStatePtr = &InstancePtr->Quads[0].Plls[0].RxState; + + /* Determine PLL type. */ + TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + /* Check if we are really waiting for a QPLL lock. */ + if (!((((RxPllType == XVPHY_PLL_TYPE_QPLL) || + (RxPllType == XVPHY_PLL_TYPE_QPLL0) || + (RxPllType == XVPHY_PLL_TYPE_QPLL1)) && + (*RxStatePtr == XVPHY_GT_STATE_LOCK)) || + (((TxPllType == XVPHY_PLL_TYPE_QPLL) || + (TxPllType == XVPHY_PLL_TYPE_QPLL0) || + (TxPllType == XVPHY_PLL_TYPE_QPLL1)) && + (*TxStatePtr == XVPHY_GT_STATE_LOCK)))) { + return; + } + + /* RX is using QPLL. */ + if ((RxPllType == XVPHY_PLL_TYPE_QPLL) || + (RxPllType == XVPHY_PLL_TYPE_QPLL0) || + (RxPllType == XVPHY_PLL_TYPE_QPLL1)) { + /* GT RX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_RESET; + } + + /* If the GT TX and RX are coupled, then update the GT TX state + * as well. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + } + /* TX is using QPLL. */ + else { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_RESET; + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by CPLL lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiCpllLockHandler(XVphy *InstancePtr) +{ + XVphy_GtState *TxStatePtr; + XVphy_GtState *RxStatePtr; + XVphy_PllType TxPllType; + XVphy_PllType RxPllType; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_CPLL_LOCK, 1); + + TxStatePtr = &InstancePtr->Quads[0].Plls[0].TxState; + RxStatePtr = &InstancePtr->Quads[0].Plls[0].RxState; + + /* Determine PLL type. */ + TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + /* Check if we are really waiting for a CPLL lock. */ + if (!(((RxPllType == XVPHY_PLL_TYPE_CPLL) && + (*RxStatePtr == XVPHY_GT_STATE_LOCK)) || + ((TxPllType == XVPHY_PLL_TYPE_CPLL) && + (*TxStatePtr == XVPHY_GT_STATE_LOCK)))) { + return; + } + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + + /* RX is using CPLL. */ + if (RxPllType == XVPHY_PLL_TYPE_CPLL) { + /* GT RX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_RESET; + } + + /* If the GT TX and RX are coupled, then update the GT TX state + * as well. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + } + /* TX is using CPLL. */ + else { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_RESET; + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT TX reset lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtTxResetDoneLockHandler(XVphy *InstancePtr) +{ + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_RST_DONE, 0); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_TxAlignReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_TxAlignReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + } + + /* GT alignment. */ + XVphy_TxAlignStart(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_TxAlignStart(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_ALIGN; + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT TX alignment done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtTxAlignDoneLockHandler(XVphy *InstancePtr) +{ + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_ALIGN, 1); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_READY; + } + + /* TX ready callback. */ + if (InstancePtr->HdmiTxReadyCallback) { + InstancePtr->HdmiTxReadyCallback(InstancePtr->HdmiTxReadyRef); + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT RX reset lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtRxResetDoneLockHandler(XVphy *InstancePtr) +{ + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RX_RST_DONE, 0); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_READY; + } + + /* If DRU is use/d, release its reset. */ + if (InstancePtr->HdmiRxDruIsEnabled) { + XVphy_DruReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + } + + /* RX ready callback. */ + if (InstancePtr->HdmiRxReadyCallback) { + InstancePtr->HdmiRxReadyCallback(InstancePtr->HdmiRxReadyRef); + } + + /* If the GT TX and RX are coupled, then update the GT TX state + * as well. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_RESET; + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by a change in TX frequency +* as detected by the HDMI clock detector logic. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiTxClkDetFreqChangeHandler(XVphy *InstancePtr) +{ + XVphy_PllType PllType; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_FREQ, 0); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + + /* Assert GT TX reset. */ + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + } + + /* If the TX frequency has changed, the PLL is always disabled. */ + XVphy_PowerDownGtPll(InstancePtr, 0, (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, TRUE); + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_BufgGtReset(InstancePtr, XVPHY_DIR_TX,TRUE); + } + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX, + TRUE); + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_GtUserRdyEnable(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + } + + + /* Disable TX MMCM. */ + XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_TX, TRUE); + + /* Clear TX timer. */ + XVphy_ClkDetTimerClear(InstancePtr, 0, XVPHY_DIR_TX); + + /* Clear GT alignment. */ + XVphy_TxAlignStart(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + + /* De-assert GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_IDLE; + } + + /* If there is no reference clock, load TX timer in usec. */ + if (XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_TX)) { + XVphy_ClkDetTimerLoad(InstancePtr, 0, XVPHY_DIR_TX, 100000); + } + + /* Callback to re-initialize. */ + if (InstancePtr->HdmiTxInitCallback) { + InstancePtr->HdmiTxInitCallback(InstancePtr->HdmiTxInitRef); + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by a change in RX frequency +* as detected by the HDMI clock detector logic. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiRxClkDetFreqChangeHandler(XVphy *InstancePtr) +{ + XVphy_PllType PllType; + u32 RxRefClkHz; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RX_FREQ, 0); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + } + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + } + + /* Determine PLL type and RX reference clock selection. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + /* Fetch New RX Reference Clock Frequency */ + RxRefClkHz = XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_RX); + + /* Round input frequency to 10 kHz. */ + RxRefClkHz = RxRefClkHz / 10000; + RxRefClkHz = RxRefClkHz * 10000; + + /* Store RX reference clock. */ + InstancePtr->HdmiRxRefClkHz = RxRefClkHz; + + /* If the RX frequency has changed, the PLL is always disabled. */ + XVphy_PowerDownGtPll(InstancePtr, 0, (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, TRUE); + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, 1); + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + XVphy_BufgGtReset(InstancePtr, XVPHY_DIR_RX,TRUE); + } + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_GtUserRdyEnable(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + } + + /* When the GT TX and RX are coupled, then disable the QPLL. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + XVphy_PowerDownGtPll(InstancePtr, 0, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CMNA : XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, 1); + } + + /* Disable RX MMCM */ + XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_RX, TRUE); + /* When the GT TX and RX are coupled, then disable the TX MMCM. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_TX, TRUE); + } + + /* If DRU is present, disable it and assert reset. */ + if (InstancePtr->Config.DruIsPresent) { + XVphy_DruReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_DruEnable(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + } + + /* Clear RX timer. */ + XVphy_ClkDetTimerClear(InstancePtr, 0, XVPHY_DIR_RX); + + /* If there is reference clock, load RX timer in usec. */ + if (XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_RX)) { + XVphy_ClkDetTimerLoad(InstancePtr, 0, XVPHY_DIR_RX, 100000); + } + else { + return; + } + + /* Callback to re-initialize. */ + if (InstancePtr->HdmiRxInitCallback) { + InstancePtr->HdmiRxInitCallback(InstancePtr->HdmiRxInitRef); + } +} + +/*****************************************************************************/ +/** +* This function is the handler for TX timer timeout events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiTxTimerTimeoutHandler(XVphy *InstancePtr) +{ + XVphy_ChannelId ChId; + XVphy_PllType PllType; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_TMR, 1); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + switch (PllType) { + case XVPHY_PLL_TYPE_QPLL: + case XVPHY_PLL_TYPE_QPLL0: + ChId = XVPHY_CHANNEL_ID_CMN0; + break; + case XVPHY_PLL_TYPE_QPLL1: + ChId = XVPHY_CHANNEL_ID_CMN1; + break; + default: + ChId = XVPHY_CHANNEL_ID_CHA; + break; + } + + /* Start TX MMCM. */ + XVphy_MmcmStart(InstancePtr, 0, XVPHY_DIR_TX); + + /* Enable PLL. */ + XVphy_PowerDownGtPll(InstancePtr, 0, (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, FALSE); + + if (PllType != XVPHY_PLL_TYPE_CPLL) { + /* Set QPLL Selection in PIO. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, 0); + } + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_GtUserRdyEnable(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + } + XVphy_ClkReconfig(InstancePtr, 0, ChId); + XVphy_OutDivReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX); + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_TX, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + InstancePtr->Quads[0].Plls[0].TxOutDiv : + InstancePtr->Quads[0].Plls[0].TxOutDiv / 2); + } + XVphy_DirReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX); + + /* Assert PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + /* Assert GT TX reset. */ + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + } + + /* De-assert PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_BufgGtReset(InstancePtr, XVPHY_DIR_TX,FALSE); + + /* Clear GT alignment. */ + XVphy_TxAlignStart(InstancePtr, ChId, FALSE); + } + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_LOCK; + } +} + +/*****************************************************************************/ +/** +* This function is the handler for RX timer timeout events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiRxTimerTimeoutHandler(XVphy *InstancePtr) +{ + XVphy_ChannelId ChId; + XVphy_PllType PllType; + u32 Status; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RX_TMR, 1); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + switch (PllType) { + case XVPHY_PLL_TYPE_QPLL: + case XVPHY_PLL_TYPE_QPLL0: + ChId = XVPHY_CHANNEL_ID_CMN0; + break; + case XVPHY_PLL_TYPE_QPLL1: + ChId = XVPHY_CHANNEL_ID_CMN1; + break; + default: + ChId = XVPHY_CHANNEL_ID_CHA; + break; + } + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + + /* Set RX parameters. */ + Status = XVphy_SetHdmiRxParam(InstancePtr, 0, ChId); + if (Status != XST_SUCCESS) { + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + xil_printf("\n\rCouldn't find the correct GT " + "parameters for this video resolution.\n\r"); + xil_printf("Try another GT PLL layout.\n\r"); + } + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + if (XVphy_IsBonded(InstancePtr, 0, + XVPHY_CHANNEL_ID_CH1)) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_IDLE; + } + } + + return; + } + + /* Enable PLL. */ + XVphy_PowerDownGtPll(InstancePtr, 0, (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, FALSE); + + /* Enable DRU to set the clock muxes. */ + XVphy_DruEnable(InstancePtr, XVPHY_CHANNEL_ID_CHA, + InstancePtr->HdmiRxDruIsEnabled); + + /* Update reference clock election. */ + XVphy_CfgPllRefClkSel(InstancePtr, 0, + ((PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA), + ((InstancePtr->HdmiRxDruIsEnabled) ? + InstancePtr->Config.DruRefClkSel : + InstancePtr->Config.RxRefClkSel)); + + /* Update GT DRU mode. */ + XVphy_HdmiGtDruModeEnable(InstancePtr, InstancePtr->HdmiRxDruIsEnabled); + + /* Update RefClk selection. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, 0); + + XVphy_ClkReconfig(InstancePtr, 0, ChId); + XVphy_OutDivReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX); + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + XVphy_OutDivReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX); + } + + XVphy_DirReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + XVphy_BufgGtReset(InstancePtr, XVPHY_DIR_RX,FALSE); + } + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_GtUserRdyEnable(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + } + + /* Assert RX PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + TRUE); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + } + + /* De-assert RX PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + /* When the TX and RX are coupled, clear GT alignment. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + if (InstancePtr->HdmiRxDruIsEnabled) { + xil_printf("WARNING: " + "Transmitter cannot be used on\r\n"); + xil_printf(" " + "bonded mode when DRU is enabled\r\n"); + xil_printf("Switch to unbonded PLL layout\r\n"); + } + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, 0); + XVphy_TxAlignStart(InstancePtr, ChId, FALSE); + } + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_LOCK; + } +} + +/*****************************************************************************/ +/** +* This function is the interrupt handler for the GT events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtHandler(XVphy *InstancePtr) +{ + u32 Event; + u32 EventMask; + u32 EventAck; + XVphy_GtState *TxStatePtr; + XVphy_GtState *RxStatePtr; + + EventMask = XVPHY_INTR_QPLL0_LOCK_MASK | XVPHY_INTR_CPLL_LOCK_MASK | + XVPHY_INTR_QPLL1_LOCK_MASK | XVPHY_INTR_TXRESETDONE_MASK | + XVPHY_INTR_TXALIGNDONE_MASK | XVPHY_INTR_RXRESETDONE_MASK; + + u8 QuadId = 0; + + /* Read Interrupt Status register */ + Event = XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG); + + EventAck = EventMask & Event; + + /* Read States for Quad=0 Ch1 */ + TxStatePtr = &InstancePtr->Quads[QuadId].Ch1.TxState; + RxStatePtr = &InstancePtr->Quads[QuadId].Ch1.RxState; + + if ((Event & XVPHY_INTR_QPLL0_LOCK_MASK) || + (Event & XVPHY_INTR_QPLL1_LOCK_MASK)){ + XVphy_WaitUs(InstancePtr, 10 * 1000); //de-bounce lock + XVphy_HdmiQpllLockHandler(InstancePtr); + } + if (Event & XVPHY_INTR_CPLL_LOCK_MASK) { + XVphy_WaitUs(InstancePtr, 10 * 1000); //de-bounce lock + XVphy_HdmiCpllLockHandler(InstancePtr); + } + if ((Event & XVPHY_INTR_TXRESETDONE_MASK) + && (*TxStatePtr == XVPHY_GT_STATE_RESET)) { + XVphy_HdmiGtTxResetDoneLockHandler(InstancePtr); + } + if ((Event & XVPHY_INTR_TXALIGNDONE_MASK) + && (*TxStatePtr == XVPHY_GT_STATE_ALIGN)) { + XVphy_HdmiGtTxAlignDoneLockHandler(InstancePtr); + } + if ((Event & XVPHY_INTR_RXRESETDONE_MASK) + && (*RxStatePtr == XVPHY_GT_STATE_RESET)) { + XVphy_HdmiGtRxResetDoneLockHandler(InstancePtr); + } + + /* Clear event flags by writing to Interrupt Status register */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + EventAck); +} + +/*****************************************************************************/ +/** +* This function is the interrupt handler for the clock detector events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetHandler(XVphy *InstancePtr) +{ + u32 Event; + u32 EventMask; + u32 EventAck; + + EventMask = XVPHY_INTR_TXCLKDETFREQCHANGE_MASK | + XVPHY_INTR_RXCLKDETFREQCHANGE_MASK | + XVPHY_INTR_TXTMRTIMEOUT_MASK | + XVPHY_INTR_RXTMRTIMEOUT_MASK; + + /* Read Interrupt Status register */ + Event = XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG); + + EventAck = EventMask & Event; + + if (Event & XVPHY_INTR_TXCLKDETFREQCHANGE_MASK) { + XVphy_HdmiTxClkDetFreqChangeHandler(InstancePtr); + } + if (Event & XVPHY_INTR_RXCLKDETFREQCHANGE_MASK) { + XVphy_HdmiRxClkDetFreqChangeHandler(InstancePtr); + } + if (Event & XVPHY_INTR_TXTMRTIMEOUT_MASK) { + XVphy_HdmiTxTimerTimeoutHandler(InstancePtr); + } + if (Event & XVPHY_INTR_RXTMRTIMEOUT_MASK) { + XVphy_HdmiRxTimerTimeoutHandler(InstancePtr); + } + + /* Clear event flags by writing to Interrupt Status register */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + EventAck); +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hw.h b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hw.h new file mode 100644 index 00000000..dd2e2611 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_hw.h @@ -0,0 +1,560 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hw.h + * + * This header file contains the identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xvphy.h. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +#ifndef XVPHY_HW_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_HW_H_ + +/***************************** Include Files **********************************/ + +#include "xil_io.h" +#include "xil_types.h" + +/************************** Constant Definitions ******************************/ + +/******************************************************************************/ +/** + * Address mapping for the Video PHY core. + * +*******************************************************************************/ +/** @name VPHY core registers: General registers. + * @{ + */ +#define XVPHY_VERSION_REG 0x000 +#define XVPHY_BANK_SELECT_REG 0x00C +#define XVPHY_REF_CLK_SEL_REG 0x010 +#define XVPHY_PLL_RESET_REG 0x014 +#define XVPHY_PLL_LOCK_STATUS_REG 0x018 +#define XVPHY_TX_INIT_REG 0x01C +#define XVPHY_TX_INIT_STATUS_REG 0x020 +#define XVPHY_RX_INIT_REG 0x024 +#define XVPHY_RX_INIT_STATUS_REG 0x028 +#define XVPHY_IBUFDS_GTXX_CTRL_REG 0x02C +#define XVPHY_POWERDOWN_CONTROL_REG 0x030 +#define XVPHY_LOOPBACK_CONTROL_REG 0x038 +/* @} */ + +/** @name VPHY core registers: Dynamic reconfiguration port (DRP) registers. + * @{ + */ +#define XVPHY_DRP_CONTROL_CH1_REG 0x040 +#define XVPHY_DRP_CONTROL_CH2_REG 0x044 +#define XVPHY_DRP_CONTROL_CH3_REG 0x048 +#define XVPHY_DRP_CONTROL_CH4_REG 0x04C +#define XVPHY_DRP_STATUS_CH1_REG 0x050 +#define XVPHY_DRP_STATUS_CH2_REG 0x054 +#define XVPHY_DRP_STATUS_CH3_REG 0x058 +#define XVPHY_DRP_STATUS_CH4_REG 0x05C +#define XVPHY_DRP_CONTROL_COMMON_REG 0x060 +#define XVPHY_DRP_STATUS_COMMON_REG 0x064 +/* @} */ + +/** @name VPHY core registers: Transmitter function registers. + * @{ + */ +#define XVPHY_TX_CONTROL_REG 0x070 +#define XVPHY_TX_BUFFER_BYPASS_REG 0x074 +#define XVPHY_TX_STATUS_REG 0x078 +#define XVPHY_TX_DRIVER_CH12_REG 0x07C +#define XVPHY_TX_DRIVER_CH34_REG 0x080 +/* @} */ + +/** @name VPHY core registers: Receiver function registers. + * @{ + */ +#define XVPHY_RX_CONTROL_REG 0x100 +#define XVPHY_RX_STATUS_REG 0x104 +#define XVPHY_RX_EQ_CDR_REG 0x108 +#define XVPHY_RX_TDLOCK_REG 0x10C +/* @} */ + +/** @name VPHY core registers: Interrupt registers. + * @{ + */ +#define XVPHY_INTR_EN_REG 0x110 +#define XVPHY_INTR_DIS_REG 0x114 +#define XVPHY_INTR_MASK_REG 0x118 +#define XVPHY_INTR_STS_REG 0x11C +/* @} */ + +/** @name User clocking registers: MMCM and BUFGGT registers. + * @{ + */ +#define XVPHY_MMCM_TXUSRCLK_CTRL_REG 0x0120 +#define XVPHY_MMCM_TXUSRCLK_REG1 0x0124 +#define XVPHY_MMCM_TXUSRCLK_REG2 0x0128 +#define XVPHY_MMCM_TXUSRCLK_REG3 0x012C +#define XVPHY_MMCM_TXUSRCLK_REG4 0x0130 +#define XVPHY_BUFGGT_TXUSRCLK_REG 0x0134 +#define XVPHY_MISC_TXUSRCLK_REG 0x0138 + +#define XVPHY_MMCM_RXUSRCLK_CTRL_REG 0x0140 +#define XVPHY_MMCM_RXUSRCLK_REG1 0x0144 +#define XVPHY_MMCM_RXUSRCLK_REG2 0x0148 +#define XVPHY_MMCM_RXUSRCLK_REG3 0x014C +#define XVPHY_MMCM_RXUSRCLK_REG4 0x0150 +#define XVPHY_BUFGGT_RXUSRCLK_REG 0x0154 +#define XVPHY_MISC_RXUSRCLK_REG 0x0158 +/* @} */ + +/** @name Clock detector (HDMI) registers. + * @{ + */ +#define XVPHY_CLKDET_CTRL_REG 0x0200 +#define XVPHY_CLKDET_STAT_REG 0x0204 +#define XVPHY_CLKDET_FREQ_TMR_TO_REG 0x0208 +#define XVPHY_CLKDET_FREQ_TX_REG 0x020C +#define XVPHY_CLKDET_FREQ_RX_REG 0x0210 +#define XVPHY_CLKDET_TMR_TX_REG 0x0214 +#define XVPHY_CLKDET_TMR_RX_REG 0x0218 +#define XVPHY_CLKDET_FREQ_DRU_REG 0x021C +/* @} */ + +/** @name Data recovery unit registers (HDMI). + * @{ + */ +#define XVPHY_DRU_CTRL_REG 0x0300 +#define XVPHY_DRU_STAT_REG 0x0304 + +#define XVPHY_DRU_CFREQ_L_REG(Ch) (0x0308 + (12 * (Ch - 1))) +#define XVPHY_DRU_CFREQ_H_REG(Ch) (0x030C + (12 * (Ch - 1))) +#define XVPHY_DRU_GAIN_REG(Ch) (0x0310 + (12 * (Ch - 1))) +/* @} */ + +/******************************************************************************/ + +/** @name VPHY core masks, shifts, and register values. + * @{ + */ +/* 0x0F8: VERSION */ +#define XVPHY_VERSION_INTER_REV_MASK \ + 0x000000FF /**< Internal revision. */ +#define XVPHY_VERSION_CORE_PATCH_MASK \ + 0x00000F00 /**< Core patch details. */ +#define XVPHY_VERSION_CORE_PATCH_SHIFT 8 /**< Shift bits for core patch + details. */ +#define XVPHY_VERSION_CORE_VER_REV_MASK \ + 0x0000F000 /**< Core version revision. */ +#define XVPHY_VERSION_CORE_VER_REV_SHIFT 12 /**< Shift bits for core version + revision. */ +#define XVPHY_VERSION_CORE_VER_MNR_MASK \ + 0x00FF0000 /**< Core minor version. */ +#define XVPHY_VERSION_CORE_VER_MNR_SHIFT 16 /**< Shift bits for core minor + version. */ +#define XVPHY_VERSION_CORE_VER_MJR_MASK \ + 0xFF000000 /**< Core major version. */ +#define XVPHY_VERSION_CORE_VER_MJR_SHIFT 24 /**< Shift bits for core major + version. */ +/* 0x00C: BANK_SELECT_REG */ +#define XVPHY_BANK_SELECT_TX_MASK 0x00F +#define XVPHY_BANK_SELECT_RX_MASK 0xF00 +#define XVPHY_BANK_SELECT_RX_SHIFT 8 +/* 0x010: REF_CLK_SEL */ +#define XVPHY_REF_CLK_SEL_QPLL0_MASK 0x0000000F +#define XVPHY_REF_CLK_SEL_CPLL_MASK 0x000000F0 +#define XVPHY_REF_CLK_SEL_CPLL_SHIFT 4 +#define XVPHY_REF_CLK_SEL_QPLL1_MASK 0x00000F00 +#define XVPHY_REF_CLK_SEL_QPLL1_SHIFT 8 +#define XVPHY_REF_CLK_SEL_XPLL_GTREFCLK0 1 +#define XVPHY_REF_CLK_SEL_XPLL_GTREFCLK1 2 +#define XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK0 3 +#define XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK1 4 +#define XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0 5 +#define XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1 6 +#define XVPHY_REF_CLK_SEL_XPLL_GTGREFCLK 7 +#define XVPHY_REF_CLK_SEL_SYSCLKSEL_MASK 0x0F000000 +#define XVPHY_REF_CLK_SEL_SYSCLKSEL_SHIFT 24 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0 3 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1 2 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0 2 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1 3 +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 0x03000000 : 0x02000000) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 0x0C000000 : 0x08000000) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 0x30000000 : 0x01000000) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 0xC0000000 : 0x04000000) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 24 : 25) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 26 : 27) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 28 : 24) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(G) \ + (((G) == XVPHY_GT_TYPE_GTHE3) ? 30 : 26) +/* 0x014: PLL_RESET */ +#define XVPHY_PLL_RESET_CPLL_MASK 0x1 +#define XVPHY_PLL_RESET_QPLL0_MASK 0x2 +#define XVPHY_PLL_RESET_QPLL1_MASK 0x4 +/* 0x018: PLL_LOCK_STATUS */ +#define XVPHY_PLL_LOCK_STATUS_CPLL_MASK(Ch) \ + (0x01 << (Ch - 1)) +#define XVPHY_PLL_LOCK_STATUS_QPLL0_MASK 0x10 +#define XVPHY_PLL_LOCK_STATUS_QPLL1_MASK 0x20 +#define XVPHY_PLL_LOCK_STATUS_CPLL_ALL_MASK \ + (XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x01C, 0x024: TX_INIT, RX_INIT */ +#define XVPHY_TXRX_INIT_GTRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PMARESET_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PCSRESET_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_INIT_USERRDY_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_INIT_USERRDY_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PLLGTRESET_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_GTRESET_ALL_MASK \ + (XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TX_INIT_USERRDY_ALL_MASK \ + (XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_RX_INIT_USERRDY_ALL_MASK \ + (XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TXRX_INIT_PLLGTRESET_ALL_MASK \ + (XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x020, 0x028: TX_STATUS, RX_STATUS */ +#define XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_POWERGOOD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_RESETDONE_ALL_MASK \ + (XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TXRX_INIT_STATUS_PMARESETDONE_ALL_MASK \ + (XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x02C: IBUFDS_GTXX_CTRL */ +#define XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK 0x1 +#define XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK 0x2 +/* 0x030: POWERDOWN_CONTROL */ +#define XVPHY_POWERDOWN_CONTROL_CPLLPD_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_RXPD_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_RXPD_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_TXPD_MASK(Ch) \ + (0x60 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_TXPD_SHIFT(Ch) \ + (5 + (8 * (Ch - 1))) +/* 0x038: LOOPBACK_CONTROL */ +#define XVPHY_LOOPBACK_CONTROL_CH_MASK(Ch) \ + (0x03 << (8 * (Ch - 1))) +#define XVPHY_LOOPBACK_CONTROL_CH_SHIFT(Ch) \ + (8 * (Ch - 1)) +/* 0x040, 0x044, 0x048, 0x04C, 0x060: DRP_CONTROL_CH[1-4], DRP_CONTROL_COMMON */ +#define XVPHY_DRP_CONTROL_DRPADDR_MASK 0x00000FFF +#define XVPHY_DRP_CONTROL_DRPEN_MASK 0x00001000 +#define XVPHY_DRP_CONTROL_DRPWE_MASK 0x00002000 +#define XVPHY_DRP_CONTROL_DRPRESET_MASK 0x00004000 +#define XVPHY_DRP_CONTROL_DRPDI_MASK 0xFFFF0000 +#define XVPHY_DRP_CONTROL_DRPDI_SHIFT 16 +/* 0x050, 0x054, 0x058, 0x05C, 0x064: DRP_STATUS_CH[1-4], DRP_STATUS_COMMON */ +#define XVPHY_DRP_STATUS_DRPO_MASK 0x0FFFF +#define XVPHY_DRP_STATUS_DRPRDY_MASK 0x10000 +#define XVPHY_DRP_STATUS_DRPBUSY_MASK 0x20000 +/* 0x070: TX_CONTROL */ +#define XVPHY_TX_CONTROL_TX8B10BEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TX8B10BEN_ALL_MASK \ + (XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TX_CONTROL_TXPOLARITY_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSSEL_MASK(Ch) \ + (0x1C << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSSEL_SHIFT(Ch) \ + (2 + (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSFORCEERR_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +/* 0x074: TX_BUFFER_BYPASS */ +#define XVPHY_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHALIGNEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHDLYPD_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHINIT_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYRESET_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYBYPASS_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYEN_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +/* 0x078: TX_STATUS */ +#define XVPHY_TX_STATUS_TXPHALIGNDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXPHINITDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXDLYRESETDONE_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXBUFSTATUS_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXBUFSTATUS_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +/* 0x07C, 0x080: TX_DRIVER_CH12, TX_DRIVER_CH34 */ +#define XVPHY_TX_DRIVER_TXDIFFCTRL_MASK(Ch) \ + (0x000F << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXDIFFCTRL_SHIFT(Ch) \ + (16 * ((Ch - 1) % 2)) +#define XVPHY_TX_DRIVER_TXELECIDLE_MASK(Ch) \ + (0x0010 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXELECIDLE_SHIFT(Ch) \ + (4 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXINHIBIT_MASK(Ch) \ + (0x0020 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXINHIBIT_SHIFT(Ch) \ + (5 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPOSTCURSOR_MASK(Ch) \ + (0x07C0 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPOSTCURSOR_SHIFT(Ch) \ + (6 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPRECURSOR_MASK(Ch) \ + (0xF800 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPRECURSOR_SHIFT(Ch) \ + (11 + (16 * ((Ch - 1) % 2))) +/* 0x100: RX_CONTROL */ +#define XVPHY_RX_CONTROL_RX8B10BEN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RX8B10BEN_ALL_MASK \ + (XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_RX_CONTROL_RXPOLARITY_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSCNTRESET_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSSEL_MASK(Ch) \ + (0x70 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSSEL_SHIFT(Ch) \ + (4 + (8 * (Ch - 1))) +/* 0x104: RX_STATUS */ +#define XVPHY_RX_STATUS_RXCDRLOCK_MASK(Ch) \ + (0x1 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXBUFSTATUS_MASK(Ch) \ + (0xE << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXBUFSTATUS_SHIFT(Ch) \ + (1 + (8 * (Ch - 1))) +/* 0x104: RX_EQ_CDR */ +#define XVPHY_RX_CONTROL_RXLPMEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXCDRHOLD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXOSOVRDEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXLPMHFOVRDEN_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXLPMEN_ALL_MASK \ + (XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x110, 0x114, 0x118, 0x11C: INTR_EN, INTR_DIS, INTR_MASK, INTR_STS */ +#define XVPHY_INTR_TXRESETDONE_MASK 0x00000001 +#define XVPHY_INTR_RXRESETDONE_MASK 0x00000002 +#define XVPHY_INTR_CPLL_LOCK_MASK 0x00000004 +#define XVPHY_INTR_QPLL0_LOCK_MASK 0x00000008 +#define XVPHY_INTR_TXALIGNDONE_MASK 0x00000010 +#define XVPHY_INTR_QPLL1_LOCK_MASK 0x00000020 +#define XVPHY_INTR_TXCLKDETFREQCHANGE_MASK 0x00000040 +#define XVPHY_INTR_RXCLKDETFREQCHANGE_MASK 0x00000080 +#define XVPHY_INTR_TXTMRTIMEOUT_MASK 0x40000000 +#define XVPHY_INTR_RXTMRTIMEOUT_MASK 0x80000000 +#define XVPHY_INTR_QPLL_LOCK_MASK XVPHY_INTR_QPLL0_LOCK_MASK +/* 0x120, 0x140: MMCM_TXUSRCLK_CTRL, MMCM_RXUSRCLK_CTRL */ +#define XVPHY_MMCM_USRCLK_CTRL_CFG_NEW_MASK 0x01 +#define XVPHY_MMCM_USRCLK_CTRL_RST_MASK 0x02 +#define XVPHY_MMCM_USRCLK_CTRL_CFG_SUCCESS_MASK 0x10 +#define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK 0x20 +#define XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK 0x400 +/* 0x124, 0x144: MMCM_TXUSRCLK_REG1, MMCM_RXUSRCLK_REG1 */ +#define XVPHY_MMCM_USRCLK_REG1_DIVCLK_MASK \ + 0x00000FF +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_MASK \ + 0x000FF00 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_SHIFT \ + 8 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_MASK \ + 0x3FF0000 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_SHIFT \ + 16 +/* 0x128, 0x148: MMCM_TXUSRCLK_REG2, MMCM_RXUSRCLK_REG2 */ +#define XVPHY_MMCM_USRCLK_REG2_DIVCLK_MASK \ + 0x00000FF +#define XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_MASK \ + 0x3FF0000 +#define XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_SHIFT \ + 16 +/* 0x12C, 0x130, 0x14C, 0x150: MMCM_TXUSRCLK_REG[3,4], MMCM_RXUSRCLK_REG[3,4] */ +#define XVPHY_MMCM_USRCLK_REG34_DIVCLK_MASK \ + 0x00000FF +/* 0x134, 0x154: BUFGT_TXUSRCLK, BUFGT_RXUSRCLK */ +#define XVPHY_BUFGGT_XXUSRCLK_CLR_MASK 0x1 +#define XVPHY_BUFGGT_XXUSRCLK_DIV_MASK 0xE +#define XVPHY_BUFGGT_XXUSRCLK_DIV_SHIFT 1 +/* 0x138, 0x158: MISC_TXUSRCLK_REG, MISC_RXUSERCLK_REG */ +#define XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK 0x1 +/* 0x200: CLKDET_CTRL */ +#define XVPHY_CLKDET_CTRL_RUN_MASK 0x1 +#define XVPHY_CLKDET_CTRL_TX_TMR_CLR_MASK 0x2 +#define XVPHY_CLKDET_CTRL_RX_TMR_CLR_MASK 0x4 +#define XVPHY_CLKDET_CTRL_TX_FREQ_RST_MASK 0x8 +#define XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK 0x10 +#define XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_MASK 0x1FE0 +#define XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT 5 +/* 0x204: CLKDET_STAT */ +#define XVPHY_CLKDET_STAT_TX_FREQ_ZERO_MASK 0x1 +#define XVPHY_CLKDET_STAT_RX_FREQ_ZERO_MASK 0x2 +#define XVPHY_CLKDET_STAT_TX_REFCLK_LOCK_MASK 0x3 +#define XVPHY_CLKDET_STAT_TX_REFCLK_LOCK_CAP_MASK 0x4 +/* 0x300: DRU_CTRL */ +#define XVPHY_DRU_CTRL_RST_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XVPHY_DRU_CTRL_EN_MASK(Ch) (0x02 << (8 * (Ch - 1))) +/* 0x304: DRU_STAT */ +#define XVPHY_DRU_STAT_ACTIVE_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XVPHY_DRU_STAT_VERSION_MASK 0xFF000000 +#define XVPHY_DRU_STAT_VERSION_SHIFT 24 +/* 0x30C, 0x318, 0x324, 0x330: DRU_CFREQ_H_CH[1-4] */ +#define XVPHY_DRU_CFREQ_H_MASK 0x1F +/* 0x310, 0x31C, 0x328, 0x334: DRU_GAIN_CH[1-4] */ +#define XVPHY_DRU_GAIN_G1_MASK 0x00001F +#define XVPHY_DRU_GAIN_G1_SHIFT 0 +#define XVPHY_DRU_GAIN_G1_P_MASK 0x001F00 +#define XVPHY_DRU_GAIN_G1_P_SHIFT 8 +#define XVPHY_DRU_GAIN_G2_MASK 0x1F0000 +#define XVPHY_DRU_GAIN_G2_SHIFT 16 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +/** @name Register access macro definitions. + * @{ + */ +#define XVphy_In32 Xil_In32 +#define XVphy_Out32 Xil_Out32 +/* @} */ + +/******************************************************************************/ +/** + * This is a low-level function that reads from the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to be read from. + * + * @return The 32-bit value of the specified register. + * + * @note C-style signature: + * u32 XVphy_ReadReg(u32 BaseAddress, u32 RegOffset) + * +*******************************************************************************/ +#define XVphy_ReadReg(BaseAddress, RegOffset) \ + XVphy_In32((BaseAddress) + (RegOffset)) + +/******************************************************************************/ +/** + * This is a low-level function that writes to the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to write to. + * @param Data is the 32-bit data to write to the specified register. + * + * @return None. + * + * @note C-style signature: + * void XVphy_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) + * +*******************************************************************************/ +#define XVphy_WriteReg(BaseAddress, RegOffset, Data) \ + XVphy_Out32((BaseAddress) + (RegOffset), (Data)) + +#endif /* XVPHY_HW_H_ */ diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_intr.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_intr.c new file mode 100644 index 00000000..8ed22436 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_intr.c @@ -0,0 +1,253 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_intr.c + * + * This file contains functions related to XVphy interrupt handling. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function enables interrupts associated with the specified interrupt type. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param Intr is the interrupt type/mask to enable. + * + * @return None. + * + * @note None. +* +*******************************************************************************/ +void XVphy_IntrEnable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr) +{ + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_EN_REG); + RegVal |= Intr; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_EN_REG, RegVal); +} + +/******************************************************************************/ +/** + * This function disabled interrupts associated with the specified interrupt + * type. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param Intr is the interrupt type/mask to disable. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_IntrDisable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr) +{ + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_INTR_DIS_REG); + RegVal |= Intr; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_DIS_REG, + RegVal); +} + +/******************************************************************************/ +/** + * This function installs a callback function for the specified handler type. + * + * @param InstancePtr is a pointer to the XVPhy instance. + * @param HandlerType is the interrupt handler type which specifies which + * interrupt event to attach the callback for. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_SetIntrHandler(XVphy *InstancePtr, XVphy_IntrHandlerType HandlerType, + XVphy_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((HandlerType == XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK) || + (HandlerType == + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE) || + (HandlerType == + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT)); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + switch (HandlerType) { + case XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE: + InstancePtr->IntrTxResetDoneHandler = CallbackFunc; + InstancePtr->IntrTxResetDoneCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE: + InstancePtr->IntrRxResetDoneHandler = CallbackFunc; + InstancePtr->IntrRxResetDoneCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK: + InstancePtr->IntrCpllLockHandler = CallbackFunc; + InstancePtr->IntrCpllLockCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK: + InstancePtr->IntrQpllLockHandler = CallbackFunc; + InstancePtr->IntrQpllLockCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE: + InstancePtr->IntrTxAlignDoneHandler = CallbackFunc; + InstancePtr->IntrTxAlignDoneCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK: + InstancePtr->IntrQpll1LockHandler = CallbackFunc; + InstancePtr->IntrQpll1LockCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE: + InstancePtr->IntrTxClkDetFreqChangeHandler = + CallbackFunc; + InstancePtr->IntrTxClkDetFreqChangeCallbackRef = + CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE: + InstancePtr->IntrRxClkDetFreqChangeHandler = + CallbackFunc; + InstancePtr->IntrRxClkDetFreqChangeCallbackRef = + CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT: + InstancePtr->IntrTxTmrTimeoutHandler = CallbackFunc; + InstancePtr->IntrTxTmrTimeoutCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT: + InstancePtr->IntrRxTmrTimeoutHandler = CallbackFunc; + InstancePtr->IntrRxTmrTimeoutCallbackRef = CallbackRef; + break; + default: + break; + } +} + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XVphy driver. It will detect + * what kind of interrupt has happened, and will invoke the appropriate callback + * function. + * + * @param InstancePtr is a pointer to the XVphy instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_InterruptHandler(XVphy *InstancePtr) +{ + u32 IntrStatus; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Determine what kind of interrupts have occurred. */ + IntrStatus = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_INTR_STS_REG); + + if (IntrStatus & XVPHY_INTR_CPLL_LOCK_MASK) { + InstancePtr->IntrCpllLockHandler( + InstancePtr->IntrCpllLockCallbackRef); + } + if (IntrStatus & XVPHY_INTR_QPLL_LOCK_MASK) { + InstancePtr->IntrQpllLockHandler( + InstancePtr->IntrQpllLockCallbackRef); + } + if (IntrStatus & XVPHY_INTR_QPLL1_LOCK_MASK) { + InstancePtr->IntrQpll1LockHandler( + InstancePtr->IntrQpll1LockCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXRESETDONE_MASK) { + InstancePtr->IntrTxResetDoneHandler( + InstancePtr->IntrTxResetDoneCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXALIGNDONE_MASK) { + InstancePtr->IntrTxAlignDoneHandler( + InstancePtr->IntrTxAlignDoneCallbackRef); + } + if (IntrStatus & XVPHY_INTR_RXRESETDONE_MASK) { + InstancePtr->IntrRxResetDoneHandler( + InstancePtr->IntrRxResetDoneCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXCLKDETFREQCHANGE_MASK) { + InstancePtr->IntrTxClkDetFreqChangeHandler( + InstancePtr->IntrTxClkDetFreqChangeCallbackRef); + } + if (IntrStatus & XVPHY_INTR_RXCLKDETFREQCHANGE_MASK) { + InstancePtr->IntrRxClkDetFreqChangeHandler( + InstancePtr->IntrRxClkDetFreqChangeCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXTMRTIMEOUT_MASK) { + InstancePtr->IntrTxTmrTimeoutHandler( + InstancePtr->IntrTxTmrTimeoutCallbackRef); + } + if (IntrStatus & XVPHY_INTR_RXTMRTIMEOUT_MASK) { + InstancePtr->IntrRxTmrTimeoutHandler( + InstancePtr->IntrRxTmrTimeoutCallbackRef); + } +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_log.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_log.c new file mode 100644 index 00000000..379062ad --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_log.c @@ -0,0 +1,362 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" + +/**************************** Function Prototypes *****************************/ + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will reset the driver's logginc mechanism. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_LogReset(XVphy *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + InstancePtr->Log.HeadIndex = 0; + InstancePtr->Log.TailIndex = 0; +} + +/*****************************************************************************/ +/** +* This function will insert an event in the driver's logginc mechanism. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Evt is the event type to log. +* @param Data is the associated data for the event. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Evt <= (XVPHY_LOG_EVT_RX_FREQ)); + Xil_AssertVoid(Data < 0xFF); + + /* Write data and event into log buffer */ + InstancePtr->Log.DataBuffer[InstancePtr->Log.HeadIndex] = + (Data << 8) | Evt; + + /* Update head pointer if reached to end of the buffer */ + if (InstancePtr->Log.HeadIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { + /* Clear pointer */ + InstancePtr->Log.HeadIndex = 0; + } + else { + /* Increment pointer */ + InstancePtr->Log.HeadIndex++; + } + + /* Check tail pointer. When the two pointer are equal, then the buffer + * is full. In this case then increment the tail pointer as well to + * remove the oldest entry from the buffer. */ + if (InstancePtr->Log.TailIndex == InstancePtr->Log.HeadIndex) { + if (InstancePtr->Log.TailIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { + InstancePtr->Log.TailIndex = 0; + } + else { + InstancePtr->Log.TailIndex++; + } + } +} + +/*****************************************************************************/ +/** +* This function will read the last event from the log. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The log data. +* +* @note None. +* +******************************************************************************/ +u16 XVphy_LogRead(XVphy *InstancePtr) +{ + u16 Log; + + /* Verify argument. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check if there is any data in the log */ + if (InstancePtr->Log.TailIndex == InstancePtr->Log.HeadIndex) { + Log = 0; + } + else { + Log = InstancePtr->Log.DataBuffer[InstancePtr->Log.TailIndex]; + + /* Increment tail pointer */ + if (InstancePtr->Log.TailIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { + InstancePtr->Log.TailIndex = 0; + } + else { + InstancePtr->Log.TailIndex++; + } + } + + return Log; +} + +/*****************************************************************************/ +/** +* This function will print the entire log. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_LogDisplay(XVphy *InstancePtr) +{ + u16 Log; + u8 Evt; + u8 Data; + + /* Verify argument. */ + Xil_AssertVoid(InstancePtr != NULL); + + xil_printf("\r\n\n\nVPHY log\r\n"); + xil_printf("------\r\n"); + + do { + /* Read log data */ + Log = XVphy_LogRead(InstancePtr); + + /* Event */ + Evt = Log & 0xff; + + /* Data */ + Data = (Log >> 8) & 0xFF; + + switch (Evt) { + case (XVPHY_LOG_EVT_NONE): + xil_printf("GT log end\r\n-------\r\n"); + break; + case (XVPHY_LOG_EVT_QPLL_EN): + xil_printf("QPLL enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_QPLL_RST): + xil_printf("QPLL reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_CPLL_EN): + xil_printf("CPLL enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_CPLL_RST): + xil_printf("CPLL reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_TXPLL_EN): + xil_printf("TX MMCM enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_TXPLL_RST): + xil_printf("TX MMCM reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_RXPLL_EN): + xil_printf("RX MMCM enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_RXPLL_RST): + xil_printf("RX MMCM reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_GTRX_RST): + xil_printf("GT RX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_GTTX_RST): + xil_printf("GT TX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_VID_TX_RST): + xil_printf("Video TX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_VID_RX_RST): + xil_printf("Video RX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_TX_ALIGN): + if (Data == 1) { + xil_printf("done\r\n"); + } + else { + xil_printf("TX alignment start.\r\n."); + } + break; + case (XVPHY_LOG_EVT_TX_TMR): + if (Data == 1) { + xil_printf("TX timer event\r\n"); + } + else { + xil_printf("TX timer load\r\n"); + } + break; + case (XVPHY_LOG_EVT_RX_TMR): + if (Data == 1) { + xil_printf("RX timer event\r\n"); + } + else { + xil_printf("RX timer load\r\n"); + } + break; + case (XVPHY_LOG_EVT_CPLL_RECONFIG): + if (Data == 1) { + xil_printf("done\r\n"); + } + else { + xil_printf("CPLL reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_GT_RECONFIG): + if (Data == 1) { + xil_printf("done\r\n"); + } + else { + xil_printf("GT reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_QPLL_RECONFIG): + if (Data == 1) { + xil_printf("done\r\n"); + } + else { + xil_printf("QPLL reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_INIT): + if (Data == 1) { + xil_printf("GT init done\r\n"); + } + else { + xil_printf("GT Init start\r\n"); + } + break; + case (XVPHY_LOG_EVT_TXPLL_RECONFIG): + if (Data == 1) { + xil_printf("done\r\n"); + } + else { + xil_printf("TX MMCM reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_RXPLL_RECONFIG): + if (Data == 1) { + xil_printf("done\r\n"); + } + else { + xil_printf("RX MMCM reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_QPLL_LOCK): + if (Data == 1) { + xil_printf("QPLL lock\r\n"); + } + else { + xil_printf("QPLL lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_CPLL_LOCK): + if (Data == 1) { + xil_printf("CPLL lock\r\n"); + } + else { + xil_printf("CPLL lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_RXPLL_LOCK): + if (Data == 1) { + xil_printf("RX MMCM lock\r\n"); + } + else { + xil_printf("RX MMCM lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_TXPLL_LOCK): + if (Data == 1) { + xil_printf("TX MMCM lock\r\n"); + } + else { + xil_printf("TX MMCM lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_TX_RST_DONE): + xil_printf("TX reset done\r\n"); + break; + case (XVPHY_LOG_EVT_RX_RST_DONE): + xil_printf("RX reset done\r\n"); + break; + case (XVPHY_LOG_EVT_TX_FREQ): + xil_printf("TX frequency event\r\n"); + break; + case (XVPHY_LOG_EVT_RX_FREQ): + xil_printf("RX frequency event\r\n"); + break; + default: + xil_printf("Unknown event\r\n"); + break; + } + } while (Log != 0); +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_selftest.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_selftest.c new file mode 100644 index 00000000..d2a97fe0 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_selftest.c @@ -0,0 +1,102 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_selftest.c + * + * This file contains a diagnostic self-test function for the XVphy driver. It + * will check many of the Video PHY's register values against the default + * reset values as a sanity-check that the core is ready to be used. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" +#include "xstatus.h" + +/**************************** Variable Definitions ****************************/ + +/** + * This table contains the default values for the Video PHY core's registers. + */ +static u32 ResetValues[1][2] = +{ + {XVPHY_VERSION_REG, 0} +}; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function runs a self-test on the XVphy driver/device. The sanity test + * checks whether or not all tested registers hold their default reset values. + * + * @param InstancePtr is a pointer to the XVphy instance. + * + * @return + * - XST_SUCCESS if the self-test passed - all tested registers + * hold their default reset values. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XVphy_SelfTest(XVphy *InstancePtr) +{ + u8 Index; + u32 Val; + + /* Compare general usage registers with their default values. */ + for (Index = 0; Index < 1; Index++) { + Val = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + ResetValues[Index][0]); + /* Fail if register does not hold default value. */ + if (Val != ResetValues[Index][1]) { + return XST_FAILURE; + } + } + + /* All tested registers hold their default reset values. */ + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/vphy/src/xvphy_sinit.c b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_sinit.c new file mode 100644 index 00000000..c31ef81c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vphy/src/xvphy_sinit.c @@ -0,0 +1,97 @@ +/******************************************************************************* + * + * Copyright (C) 2015 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_sinit.c + * + * This file contains static initialization methods for the XVphy driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  10/19/15 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xparameters.h" +#include "xvphy.h" + +/*************************** Variable Declarations ****************************/ + +#ifndef XPAR_XVPHY_NUM_INSTANCES +#define XPAR_XVPHY_NUM_INSTANCES 0 +#endif + +/** + * A table of configuration structures containing the configuration information + * for each Video PHY core in the system. + */ +extern XVphy_Config XVphy_ConfigTable[XPAR_XVPHY_NUM_INSTANCES]; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function looks for the device configuration based on the unique device + * ID. The table XVphy_ConfigTable[] contains the configuration information for + * each device in the system. + * + * @param DeviceId is the unique device ID of the device being looked up. + * + * @return A pointer to the configuration table entry corresponding to the + * given device ID, or NULL if no match is found. + * + * @note None. + * +*******************************************************************************/ +XVphy_Config *XVphy_LookupConfig(u16 DeviceId) +{ + XVphy_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0; Index < XPAR_XVPHY_NUM_INSTANCES; Index++) { + if (XVphy_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XVphy_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +}