353 lines
11 KiB
C
353 lines
11 KiB
C
/** @file
|
|
BaseEcTcss library implementation.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2017 - 2020 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains 'Framework Code' and is licensed as such under the terms
|
|
of your license agreement with Intel or your vendor. This file may not be
|
|
modified, except as allowed by additional terms of your license agreement.
|
|
|
|
@par Specification Reference:
|
|
**/
|
|
#include <Library/EcLib.h>
|
|
#include <Library/EcTcssLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Library/DebugLib.h>
|
|
|
|
/**
|
|
USBC EC Timeout Retry Message. Used to send messages to EC with predefined
|
|
timeout and retry times.
|
|
|
|
@param[in][out] DataBuffer
|
|
@param[in] Command
|
|
@param[in] Timeout
|
|
@param[in] RetryTime
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_TIMEOUT Command timeout
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
UsbcEcTimeoutRetryMessage (
|
|
IN OUT UINT8 *DataBuffer,
|
|
IN UINT8 Command,
|
|
IN UINT32 Timeout,
|
|
IN UINT32 RetryTime
|
|
)
|
|
{
|
|
UINT8 DataSize;
|
|
UINT8 DataBufferIn;
|
|
UINT32 NumRetries;
|
|
EFI_STATUS Status;
|
|
|
|
DataSize = 1;
|
|
NumRetries = Timeout / RetryTime;
|
|
DataBufferIn = *DataBuffer;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nUsbcEcTimeoutRetryMessage: %x, Timeout: %u, RetryTime: %u\n", Command, Timeout, RetryTime));
|
|
do {
|
|
//
|
|
// Send the command to EC
|
|
//
|
|
Status = EcInterface (EcId0, Command, &DataSize, DataBuffer);
|
|
if (Status != EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
//
|
|
// If USB connection status is successful (0x00) or failed (0x02) then return
|
|
// If in progress (0x01) then retry after 10 ms
|
|
//
|
|
if (*DataBuffer == 0x00 || *DataBuffer == 0x02) {
|
|
return EFI_SUCCESS;
|
|
} else if (*DataBuffer == 0x01) {
|
|
*DataBuffer = DataBufferIn;
|
|
MicroSecondDelay(RetryTime * 1000);
|
|
NumRetries--;
|
|
} else {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
} while (NumRetries != 0);
|
|
|
|
DEBUG ((DEBUG_INFO, "\nUsbcEcTimeoutRetryMessage %x timed out\n", Command));
|
|
return EFI_TIMEOUT;
|
|
}
|
|
|
|
/**
|
|
USBC IOM Ready Notify
|
|
|
|
@param[in][out] DataBuffer
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
UsbcIomReadyNotify (
|
|
IN OUT UINT8 *DataBuffer
|
|
)
|
|
{
|
|
UINT8 DataSize;
|
|
DataSize = 1;
|
|
return (EcInterface (EcId0, EC_C_USBC_IOM_READY_NOTIFY, &DataSize, DataBuffer));
|
|
}
|
|
|
|
/**
|
|
Usbc Retimer Compliance Mode
|
|
|
|
@param[in][out] DataBuffer
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
UsbcRetimerCompliancePDMessage (
|
|
IN OUT UINT8 *DataBuffer
|
|
)
|
|
{
|
|
UINT8 DataSize;
|
|
DataSize = 1;
|
|
|
|
return (EcInterface (EcId0, EC_C_USBC_RETIMER, &DataSize, DataBuffer));
|
|
}
|
|
|
|
|
|
/**
|
|
USBC Get USB Connection Status
|
|
|
|
@param[in][out] DataBuffer
|
|
@param[in] Timeout
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_TIMEOUT Command timeout
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
UsbcGetUsbConnStatus (
|
|
IN OUT UINT8 *DataBuffer,
|
|
IN UINT32 Timeout
|
|
)
|
|
{
|
|
UINT32 RetryTime;
|
|
//
|
|
// Retry after 10ms
|
|
//
|
|
RetryTime = EC_TCSS_RETRY_TIME_GET_USB_CONN_STATUS;
|
|
return (UsbcEcTimeoutRetryMessage(DataBuffer, EC_C_USBC_GET_USB_CONN_STATUS, Timeout, RetryTime));
|
|
}
|
|
|
|
/**
|
|
USBC Sx Entry Wait
|
|
|
|
@param[in][out] DataBuffer
|
|
@param[in] Timeout
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_TIMEOUT Command timeout
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
UsbcSxEntry (
|
|
IN OUT UINT8 *DataBuffer,
|
|
IN UINT32 Timeout
|
|
)
|
|
{
|
|
UINT32 RetryTime;
|
|
//
|
|
// Retry after 100ms
|
|
//
|
|
RetryTime = EC_TCSS_RETRY_TIME_SX_ENTRY_WAIT;
|
|
return (UsbcEcTimeoutRetryMessage(DataBuffer, EC_C_USBC_SX_ENTRY_WAIT, Timeout, RetryTime));
|
|
}
|
|
|
|
|
|
/**
|
|
USBC Sx Exit Wait
|
|
|
|
@param[out] DataBuffer
|
|
@param[in] Timeout
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_TIMEOUT Command timeout
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
UsbcSxExit (
|
|
OUT UINT8 *DataBuffer,
|
|
IN UINT32 Timeout
|
|
)
|
|
{
|
|
UINT32 RetryTime;
|
|
//
|
|
// Retry after 100ms
|
|
//
|
|
RetryTime = EC_TCSS_RETRY_TIME_SX_EXIT_WAIT;
|
|
return (UsbcEcTimeoutRetryMessage(DataBuffer, EC_C_USBC_SX_EXIT_WAIT, Timeout, RetryTime));
|
|
}
|
|
|
|
/**
|
|
Set PD Controller Mode
|
|
|
|
@param[in] PdControllerMode
|
|
@param[in] PdControllerNumber
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_TIMEOUT Command timeout
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
@retval EFI_INVALID_PARAMETER Command usage error.
|
|
**/
|
|
EFI_STATUS
|
|
SetPdControllerMode (
|
|
IN UINT8 PdControllerMode,
|
|
IN UINT8 PdControllerNumber
|
|
)
|
|
{
|
|
UINT8 DataSize;
|
|
UINT8 TempBuffer[2] = { 0, 0};
|
|
EFI_STATUS Status;
|
|
UINT8 MaxPdController;
|
|
UINT32 Count;
|
|
|
|
Status = EFI_SUCCESS;
|
|
MaxPdController = (UINT8)(GET_PD_MODE_STATUS_BIT_WIDTH_TOTAL / GET_PD_MODE_STATUS_BIT_WIDTH_PER_CONTROLLER);
|
|
|
|
if (PdControllerNumber != EC_C_ALL_PD_CONTROLLER_INDEX) {
|
|
DEBUG ((DEBUG_INFO, "\nSetPdControllerMode of PD Controller Number = %x", PdControllerNumber));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "\nSetPdControllerMode of ALL PD Controller"));
|
|
}
|
|
DEBUG ((DEBUG_INFO, " to Retimer FW Update Mode = %s\n", ((PdControllerMode == RetimerFirmWareUpdateEnableMode) ? L"RetimerFirmWareUpdateEnableMode" : L"RetimerFirmWareUpdateDisableMode" )));
|
|
|
|
if ((PdControllerNumber >= MaxPdController) && (PdControllerNumber != EC_C_ALL_PD_CONTROLLER_INDEX)) {
|
|
DEBUG ((DEBUG_INFO, "\nSetPdControllerMode Returning as Invalid Pd Controller Number\n"));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((PdControllerMode < RetimerFirmWareUpdateDisableMode) || (PdControllerMode >= InvalidRetimerFirmWareUpdateMode)) {
|
|
DEBUG ((DEBUG_INFO, "\nSetPdControllerMode Returning as Invalid Pd Controller Mode\n"));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
//
|
|
// Currently EC Implementation Does not support PD Controller Number as
|
|
// Parameter. It Change/Set the mode for all PD Controller. So currently
|
|
// we are only passing one parameter to EC i.e. PD Controller Mode.
|
|
//
|
|
DataSize = 1; // This should be set to two if we are passing 2 Parameter to EC
|
|
TempBuffer[0] = PdControllerMode;
|
|
TempBuffer[1] = PdControllerNumber;
|
|
|
|
// Send EC Command to Set PD Controller Mode
|
|
Status = (EcInterface (EcId0, EC_C_SET_PD_FW_UPDATE_MODE, &DataSize, &TempBuffer[0]));
|
|
|
|
// Wait (EC_SET_PD_MODE_WAIT_TIME_IN_FACTOR_OF_50_MS * 50)ms time before exiting
|
|
for (Count = 0; Count < EC_SET_PD_MODE_WAIT_TIME_IN_FACTOR_OF_50_MS; Count++) {
|
|
MicroSecondDelay( 50 * 1000); // 50ms Delay
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "\nSetPdControllerMode Returning Status =%r\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get PD Controller Mode
|
|
|
|
@param[out] *PdControllerModeBuffer
|
|
@param[in] PdControllerNumber
|
|
@param[in] TotalCountOfPdController
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_TIMEOUT Command timeout
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
@retval EFI_INVALID_PARAMETER Command usage error.
|
|
**/
|
|
EFI_STATUS
|
|
GetPdControllerMode (
|
|
OUT UINT8 *PdControllerModeBuffer,
|
|
IN UINT8 PdControllerNumber,
|
|
IN UINT32 TotalCountOfPdController
|
|
)
|
|
{
|
|
UINT8 DataSize;
|
|
UINT8 TempData8;
|
|
UINT8 TempBuffer;
|
|
EFI_STATUS Status;
|
|
UINT8 Index;
|
|
UINT8 MaxPdController;
|
|
|
|
if (PdControllerModeBuffer == NULL) {
|
|
DEBUG ((DEBUG_INFO, "\nGetPdControllerMode Returning as Null Buffer Passed\n"));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DataSize = 1;
|
|
*PdControllerModeBuffer = 0;
|
|
TempBuffer = 0;
|
|
Status = EFI_SUCCESS;
|
|
MaxPdController = (UINT8)(GET_PD_MODE_STATUS_BIT_WIDTH_TOTAL / GET_PD_MODE_STATUS_BIT_WIDTH_PER_CONTROLLER);
|
|
|
|
if (PdControllerNumber != EC_C_ALL_PD_CONTROLLER_INDEX) {
|
|
DEBUG ((DEBUG_INFO, "\nGetPdControllerMode of PD Controller Number = %x", PdControllerNumber));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "\nGetPdControllerMode of ALL PD Controller"));
|
|
}
|
|
DEBUG ((DEBUG_INFO, " with MaxPdController =%x\n", MaxPdController));
|
|
|
|
if ((PdControllerNumber >= MaxPdController) && (PdControllerNumber != EC_C_ALL_PD_CONTROLLER_INDEX)) {
|
|
DEBUG ((DEBUG_INFO, "\nGetPdControllerMode Returning as Invalid Pd Controller Number\n"));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = EcInterface (EcId0, EC_C_GET_PD_FW_UPDATE_MODE, &DataSize, &TempBuffer);
|
|
|
|
if (Status == EFI_SUCCESS) {
|
|
for (Index = 0; ((Index < MaxPdController) && (Index < TotalCountOfPdController)); Index ++) {
|
|
if ((Index != PdControllerNumber) && (PdControllerNumber != EC_C_ALL_PD_CONTROLLER_INDEX)) {
|
|
continue;
|
|
}
|
|
TempData8 = 0; // Initialize TempData8 to 0 for all PD Controller
|
|
TempData8 = (UINT8)((TempBuffer >> (Index * GET_PD_MODE_STATUS_BIT_WIDTH_PER_CONTROLLER)) & RETIMER_FW_UPDATE_MODE);
|
|
|
|
// Compare Other PD Controller Mode with 1st one
|
|
if ((Index != 0) && (PdControllerNumber == EC_C_ALL_PD_CONTROLLER_INDEX)) {
|
|
// All PD Controller Must be in same Mode.
|
|
if (*PdControllerModeBuffer != (((TempData8 & RETIMER_FW_UPDATE_MODE) >> 1) & BIT0)){
|
|
// Return Device Error if all PD controller Mode doesn't match.
|
|
Status = EFI_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
} else {
|
|
// Save 1st PD controller mode for comparing with Other
|
|
*PdControllerModeBuffer = (((TempData8 & RETIMER_FW_UPDATE_MODE) >> 1) & BIT0); // Return Retimer FW Update Mode is Enable or Disable
|
|
}
|
|
}
|
|
}
|
|
|
|
if (PdControllerNumber != EC_C_ALL_PD_CONTROLLER_INDEX) {
|
|
DEBUG ((DEBUG_INFO, "\nGetPdControllerMode of PD Controller Number = %x", PdControllerNumber));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "\nGetPdControllerMode of ALL PD Controller"));
|
|
}
|
|
DEBUG ((DEBUG_INFO, " Current Retimer FW Update Mode = %s With return Status = %r\n", ((*PdControllerModeBuffer == RetimerFirmWareUpdateEnableMode) ? L"RetimerFirmWareUpdateEnableMode" : L"RetimerFirmWareUpdateDisableMode" ), Status));
|
|
return Status;
|
|
}
|