embeddedsw/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.c
Andrei-Liviu Simion 71c5daf609 hdcp1x: cipher: No need to use a wrapper function around enable/disable.
Signed-off-by: Andrei-Liviu Simion <andrei.simion@xilinx.com>
Acked by: Rohit Consul <rohitco@xilinx.com>
2015-08-19 23:17:24 +05:30

1252 lines
36 KiB
C

/******************************************************************************
*
* 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
* 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 xhdcp1x_cipher.c
* @addtogroup hdcp1x_v1_0
* @{
*
* This file contains the main implementation of the driver associated with
* the Xilinx HDCP Cipher core.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- --------------------------------------------------
* 1.00 fidus 07/16/15 Initial release.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdlib.h>
#include <string.h>
#include "xhdcp1x.h"
#include "xhdcp1x_cipher.h"
#include "xil_assert.h"
#include "xil_types.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/*************************** Function Prototypes *****************************/
/************************** Function Definitions *****************************/
/*****************************************************************************/
/**
* This function initializes an HDCP cipher.
*
* @param InstancePtr is the device to initialize.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XHdcp1x_CipherInit(XHdcp1x *InstancePtr)
{
u32 Value = 0;
/* Reset it */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_RESET;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_RESET;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Ensure all interrupts are disabled and cleared */
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_INTERRUPT_MASK, (u32)(-1));
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_INTERRUPT_STATUS, (u32)(-1));
/* Check for DP */
if (XHdcp1x_IsDP(InstancePtr)) {
/* Configure for four lanes SST */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES;
Value |= (4u << 4);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
}
/* Ensure that the register update bit is set */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
}
/*****************************************************************************/
/**
* This function queries the link state of a cipher device.
*
* @param InstancePtr is the device to query.
*
* @return Truth value.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherIsLinkUp(const XHdcp1x *InstancePtr)
{
u32 Value;
int IsUp = FALSE;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check for currently enabled */
if (XHdcp1x_CipherIsEnabled(InstancePtr)) {
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_STATUS);
if ((Value & XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL) != 0) {
IsUp = TRUE;
}
}
return (IsUp);
}
/*****************************************************************************/
/**
* This function enables a HDCP cipher.
*
* @param InstancePtr is the device to enable.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherEnable(XHdcp1x *InstancePtr)
{
u32 Value = 0;
int Status = XST_SUCCESS;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check for currently disabled */
if (XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_FAILURE);
}
/* Clear the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Ensure that all encryption is disabled for now */
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, 0x00ul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, 0x00ul);
/* Ensure that XOR is disabled on tx and enabled for rx to start */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE;
if (XHdcp1x_IsRX(InstancePtr)) {
Value |= XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE;
}
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value);
/* Enable it */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_ENABLE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Ensure that the register update bit is set */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
*
* This function disables a HDCP cipher.
*
* @param InstancePtr is the device to disable.
*
* @return
* - XST_SUCCESS if successful.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherDisable(XHdcp1x *InstancePtr)
{
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Ensure all interrupts are disabled */
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_INTERRUPT_MASK, 0xFFFFFFFFul);
/* Enable bypass operation */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_ENABLE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Ensure that all encryption is disabled for now */
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, 0x00ul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, 0x00ul);
/* Ensure that XOR is disabled */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value);
/* Ensure that the register update bit is set */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Wait until the XOR has actually stopped */
while (XHdcp1x_CipherXorInProgress(InstancePtr));
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function configures the key selection value.
*
* @param InstancePtr is the device to configure.
* @param KeySelect is the desired key select value.
*
* @return
* - XST_SUCCESS if successful.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherSetKeySelect(XHdcp1x *InstancePtr, u8 KeySelect)
{
int Status = XST_SUCCESS;
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(KeySelect < 8);
/* Update the device */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_SET_SELECT;
Value |= (KeySelect << 16);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Value);
return (Status);
}
/*****************************************************************************/
/**
* This function initiates a request within the HDCP cipher.
*
* @param InstancePtr is the device to submit the request to.
* @param Request is the request to submit.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLE if the core is disabled.
* - XST_DEVICE_BUSY if the core is busy.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherDoRequest(XHdcp1x *InstancePtr,
XHdcp1x_CipherRequestType Request)
{
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Request >= (XHDCP1X_CIPHER_REQUEST_BLOCK));
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Determine if there is a request in progress */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_STATUS);
Value &= XHDCP1X_CIPHER_BITMASK_CIPHER_STATUS_REQUEST_IN_PROG;
/* Check that it is not busy */
if (Value != 0) {
return (XST_DEVICE_BUSY);
}
/* Ensure that the register update bit is set */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Set the appropriate request bit and ensure that Km is always used */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_REQUEST;
Value |= (XHDCP1X_CIPHER_VALUE_CIPHER_CONTROL_REQUEST_BLOCK << Request);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value);
/* Ensure that the request bit(s) get cleared for next time */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_REQUEST;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value);
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function queries the progress of the current request.
*
* @param InstancePtr is the device to query.
*
* @return Truth value.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherIsRequestComplete(const XHdcp1x *InstancePtr)
{
u32 Value = 0;
int IsComplete = TRUE;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Determine Value */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_STATUS);
Value &= XHDCP1X_CIPHER_BITMASK_CIPHER_STATUS_REQUEST_IN_PROG;
/* Update IsComplete */
if (Value != 0) {
IsComplete = FALSE;
}
return (IsComplete);
}
/*****************************************************************************/
/**
* This function retrieves the current number of lanes of the HDCP cipher.
*
* @param InstancePtr is the device to query.
*
* @return The current number of lanes.
*
* @note None.
*
******************************************************************************/
u32 XHdcp1x_CipherGetNumLanes(const XHdcp1x *InstancePtr)
{
u32 NumLanes = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check for currently enabled */
if (XHdcp1x_CipherIsEnabled(InstancePtr)) {
/* Determine NumLanes */
NumLanes = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
NumLanes &= XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES;
NumLanes >>= 4;
}
return (NumLanes);
}
/*****************************************************************************/
/**
* This function configures the number of lanes of the HDCP cipher.
*
* @param InstancePtr is the device to configure.
* @param NumLanes is the number of lanes to configure.
*
* @return
* - XST_SUCCESS if successful.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherSetNumLanes(XHdcp1x *InstancePtr, u32 NumLanes)
{
int Status = XST_SUCCESS;
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(NumLanes > 0);
Xil_AssertNonvoid(NumLanes <= 4);
/* Check for HDMI */
if (XHdcp1x_IsHDMI(InstancePtr)) {
/* Verify NumLanes (again) */
Xil_AssertNonvoid(NumLanes == 1);
/* Update the control register */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES;
Value |= (NumLanes << 4);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
}
/* Otherwise - must be DP */
else {
/* Verify NumLanes (again) */
Xil_AssertNonvoid(NumLanes != 3);
/* Update the control register */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES;
Value |= (NumLanes << 4);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
}
return (Status);
}
/*****************************************************************************/
/**
* This function retrieves the current encryption stream map.
*
* @param InstancePtr is the device to query.
*
* @return The current encryption stream map.
*
* @note In the case of the receiver version of this core, the XOR in
* progress bit needs to be checked as well as the encryption map
* to fully determine if encryption is enabled for the SST case.
* This is the reason for the additional check in this code.
*
******************************************************************************/
u64 XHdcp1x_CipherGetEncryption(const XHdcp1x *InstancePtr)
{
u64 StreamMap = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (StreamMap);
}
/* Determine StreamMap */
StreamMap = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H);
StreamMap <<= 32;
StreamMap |= XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L);
/* Check for special case of just XOR in progress */
if ((StreamMap == 0) && (XHdcp1x_CipherXorInProgress(InstancePtr))) {
StreamMap = 0x01ul;
}
return (StreamMap);
}
/*****************************************************************************/
/**
* This function enables encryption on a set of streams.
*
* @param InstancePtr is the device to configure.
* @param StreamMap is the bit map of streams to enable encryption on.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLE if the core is not enabled.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherEnableEncryption(XHdcp1x *InstancePtr, u64 StreamMap)
{
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Check that it is not a receiver */
if (XHdcp1x_IsRX(InstancePtr)) {
return (XST_FAILURE);
}
/* Check for nothing to do */
if (StreamMap == 0) {
return (XST_SUCCESS);
}
/* Clear the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Update the LS 32-bits */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L);
Value |= ((u32) (StreamMap & 0xFFFFFFFFul));
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, Value);
/* Write the MS 32-bits */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H);
Value |= ((u32) ((StreamMap >> 32) & 0xFFFFFFFFul));
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, Value);
/* Ensure that the XOR is enabled */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value);
/* Set the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Wait until the XOR has actually started */
while (!XHdcp1x_CipherXorInProgress(InstancePtr));
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
*
* This function disables encryption on a set of streams.
*
* @param InstancePtr is the device to configure.
* @param StreamMap is the bit map of streams to disable encryption on.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLE if the core is not enabled.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherDisableEncryption(XHdcp1x *InstancePtr, u64 StreamMap)
{
u32 Val = 0;
int DisableXor = TRUE;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Check that it is not a receiver */
if (XHdcp1x_IsRX(InstancePtr)) {
return (XST_FAILURE);
}
/* Check for nothing to do */
if (StreamMap == 0) {
return (XST_SUCCESS);
}
/* Clear the register update bit */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Val &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Val);
/* Update the LS 32-bits */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L);
Val &= ~((u32) (StreamMap & 0xFFFFFFFFul));
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, Val);
if (Val != 0) {
DisableXor = FALSE;
}
/* Write the MS 32-bits */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H);
Val &= ~((u32) ((StreamMap >> 32) & 0xFFFFFFFFul));
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, Val);
if (Val != 0) {
DisableXor = FALSE;
}
/* Check HDMI special case */
if (XHdcp1x_IsHDMI(InstancePtr)) {
DisableXor = TRUE;
}
/* Check for XOR disable */
if (DisableXor) {
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL);
Val &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Val);
}
/* Set the register update bit */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Val |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Val);
/* If disabling the XOR, wait until no longer in progress */
if (DisableXor) {
while (XHdcp1x_CipherXorInProgress(InstancePtr));
}
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function reads the local KSV value from the cipher.
*
* @param InstancePtr is the device to query.
*
* @return The local KSV value.
*
* @note None.
*
******************************************************************************/
u64 XHdcp1x_CipherGetLocalKsv(const XHdcp1x *InstancePtr)
{
u32 Val = 0;
u32 Guard = 0x400ul;
u64 Ksv = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (Ksv);
}
/* Check if the local ksv is not available */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_STATUS);
Val &= XHDCP1X_CIPHER_BITMASK_KEYMGMT_STATUS_KSV_READY;
if (Val == 0) {
/* Abort any running Km calculation just in case */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL);
Val |= XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_ABORT_Km;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val);
Val &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_ABORT_Km;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val);
/* Load the local ksv */
Val = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL);
Val |= XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_LOCAL_KSV;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val);
Val &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_LOCAL_KSV;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val);
/* Wait until local KSV available */
while ((!XHdcp1x_CipherLocalKsvReady(InstancePtr)) &&
(--Guard > 0));
}
/* Confirm no timeout */
if (Guard != 0) {
/* Update Ksv */
Ksv = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KSV_LOCAL_H);
Ksv &= 0xFFul;
Ksv <<= 32;
Ksv |= XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KSV_LOCAL_L);
}
return (Ksv);
}
/*****************************************************************************/
/**
* This function reads the remote KSV value from the cipher.
*
* @param InstancePtr is the device to query.
*
* @return The remote KSV value.
*
* @note None.
*
******************************************************************************/
u64 XHdcp1x_CipherGetRemoteKsv(const XHdcp1x *InstancePtr)
{
u64 Ksv = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Determine Ksv */
Ksv = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KSV_REMOTE_H);
Ksv <<= 32;
Ksv |= XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KSV_REMOTE_L);
return (Ksv);
}
/*****************************************************************************/
/**
* This function writes the remote KSV value to the cipher.
*
* @param InstancePtr is the device to write to.
* @param Ksv is the remote KSV value to write.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLED otherwise.
*
* @note Whenever this function is called, the underlying driver will
* initiate the calculation of the Km value and wait for it to
* complete.
*
******************************************************************************/
int XHdcp1x_CipherSetRemoteKsv(XHdcp1x *InstancePtr, u64 Ksv)
{
u32 Value = 0;
u32 Guard = 0x400ul;
int Status = XST_SUCCESS;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Read local ksv to put things into a known state */
XHdcp1x_CipherGetLocalKsv(InstancePtr);
/* Clear the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Write the LS 32-bits */
Value = (u32)(Ksv & 0xFFFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KSV_REMOTE_L, Value);
/* Write the MS 8-bits */
Value = (u32)((Ksv >> 32) & 0xFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KSV_REMOTE_H, Value);
/* Set the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Trigger the calculation of theKm */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL);
Value &= 0xFFFFFFF0ul;
Value |= XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_BEGIN_Km;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Value);
Value &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_BEGIN_Km;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Value);
/* Wait until Km is available */
while ((!XHdcp1x_CipherKmReady(InstancePtr)) && (--Guard > 0));
/* Check for timeout */
if (Guard == 0) {
Status = XST_FAILURE;
}
return (Status);
}
/*****************************************************************************/
/**
* This function reads the contents of the B register in BM0.
*
* @param InstancePtr is the device to query.
* @param X is to be loaded with the contents of Bx.
* @param Y is to be loaded with the contents of By.
* @param Z is to be loaded with the contents of Bz.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLED otherwise.
*
* @note A NULL pointer can be passed in any of X, Y and Z. If so, then
* this portion of the B register is not returned to the caller.
*
******************************************************************************/
int XHdcp1x_CipherGetB(const XHdcp1x *InstancePtr, u32 *X, u32 *Y, u32 *Z)
{
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Get X if requested */
if (X != NULL) {
*X = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Bx);
*X &= 0x0FFFFFFFul;
}
/* Get Y if requested */
if (Y != NULL) {
*Y = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_By);
*Y &= 0x0FFFFFFFul;
}
/* Get Z if requested */
if (Z != NULL) {
*Z = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Bz);
*Z &= 0x0FFFFFFFul;
}
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function writes the contents of the B register in BM0.
*
* @param InstancePtr is the device to write to.
* @param X is the value to be written to Bx.
* @param Y is the value to be written to By.
* @param Z is the value to be written to Bz.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLED otherwise.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherSetB(XHdcp1x *InstancePtr, u32 X, u32 Y, u32 Z)
{
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Clear the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Update the Bx */
Value = (X & 0x0FFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Bx, Value);
/* Update the By */
Value = (Y & 0x0FFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_By, Value);
/* Update the Bz */
Value = (Z & 0x0FFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Bz, Value);
/* Set the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function reads the contents of the K register in BM0.
*
* @param InstancePtr is the device to query.
* @param X is to be loaded with the contents of Kx.
* @param Y is to be loaded with the contents of Ky.
* @param Z is to be loaded with the contents of Kz.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLED otherwise.
*
* @note A NULL pointer can be passed in any of X, Y and Z. If so, then
* this portion of the K register is not returned to the caller.
*
******************************************************************************/
int XHdcp1x_CipherGetK(const XHdcp1x *InstancePtr, u32 *X, u32 *Y, u32 *Z)
{
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Get X if requested */
if (X != NULL) {
*X = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Kx);
*X &= 0x0FFFFFFFul;
}
/* Get Y if requested */
if (Y != NULL) {
*Y = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Ky);
*Y &= 0x0FFFFFFFul;
}
/* Get Z if requested */
if (Z != NULL) {
*Z = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Kz);
*Z &= 0x0FFFFFFFul;
}
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function writes the contents of the K register in BM0.
*
* @param InstancePtr is the device to write to.
* @param X is the value to be written to Kx.
* @param Y is the value to be written to Ky.
* @param Z is the value to be written to Kz.
*
* @return
* - XST_SUCCESS if successful.
* - XST_NOT_ENABLED otherwise.
*
* @note None.
*
******************************************************************************/
int XHdcp1x_CipherSetK(XHdcp1x *InstancePtr, u32 X, u32 Y, u32 Z)
{
u32 Value = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Clear the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
/* Update the Kx */
Value = (X & 0x0FFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Kx, Value);
/* Update the Ky */
Value = (Y & 0x0FFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Ky, Value);
/* Update the Kz */
Value = (Z & 0x0FFFFFFFul);
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Kz, Value);
/* Set the register update bit */
Value = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL);
Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE;
XHdcp1x_WriteReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CONTROL, Value);
return (XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function reads the contents of the Mi/An register of BM0.
*
* @param InstancePtr is the device to query.
*
* @return The contents of the register.
*
* @note None.
*
******************************************************************************/
u64 XHdcp1x_CipherGetMi(const XHdcp1x *InstancePtr)
{
u64 Mi = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Update Mi */
Mi = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Mi_H);
Mi <<= 32;
Mi |= XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Mi_L);
return (Mi);
}
/*****************************************************************************/
/**
* This function reads the contents of the Ri register of BM0.
*
* @param InstancePtr is the device to query.
*
* @return The contents of the register.
*
* @note None.
*
******************************************************************************/
u16 XHdcp1x_CipherGetRi(const XHdcp1x *InstancePtr)
{
u16 Ri = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Determine Ri */
Ri = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Ri);
return (Ri);
}
/*****************************************************************************/
/**
*
* This function reads the contents of the Mo register of the device.
*
* @param InstancePtr is the device to query.
*
* @return The contents of the Mo register.
*
* @note None.
*
******************************************************************************/
u64 XHdcp1x_CipherGetMo(const XHdcp1x *InstancePtr)
{
u64 Mo = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Determine Mo */
Mo = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Mo_H);
Mo <<= 32;
Mo |= XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Mo_L);
return (Mo);
}
/*****************************************************************************/
/**
*
* This function reads the contents of the Ro register of the device.
*
* @param InstancePtr is the device to query.
*
* @return The contents of the Ro register.
*
* @note None.
*
******************************************************************************/
u16 XHdcp1x_CipherGetRo(const XHdcp1x *InstancePtr)
{
u16 Ro = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check that it is not disabled */
if (!XHdcp1x_CipherIsEnabled(InstancePtr)) {
return (XST_NOT_ENABLED);
}
/* Determine Ro */
Ro = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_CIPHER_Ro);
return (Ro);
}
/*****************************************************************************/
/**
* This function reads the version of the HDCP cipher core.
*
* @param InstancePtr is the device to query.
*
* @return The version of the HDCP cipher device.
*
* @note None.
*
******************************************************************************/
u32 XHdcp1x_CipherGetVersion(const XHdcp1x *InstancePtr)
{
u32 Version = 0;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
/* Determine Version */
Version = XHdcp1x_ReadReg(InstancePtr->Config.BaseAddress,
XHDCP1X_CIPHER_REG_VERSION);
return (Version);
}