/** @file
Copyright (c) 2020, Hisilicon Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
EFI_STATUS
SwitchRtcI2cChannelAndLock (
VOID
)
{
UINT8 Temp;
UINT8 Count;
for (Count = 0; Count < 100; Count++) {
// To get the other side's state is idle first
Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG);
if ((Temp & BIT3) != 0) {
(VOID) MicroSecondDelay (RTC_DELAY_30_MS);
// Try 100 times, if BMC has not released the bus, return preemption failed
if (Count == 99) {
if (!EfiAtRuntime ()) {
DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n",
__FUNCTION__, __LINE__));
}
return EFI_DEVICE_ERROR;
}
continue;
}
// if BMC free the bus, can be set 1 preemption
Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG);
Temp = Temp | CPU_GET_I2C_CONTROL;
// CPU occupied RTC I2C State
WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp);
(VOID)MicroSecondDelay (RTC_DELAY_2_MICROSECOND);
Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG);
// Is preempt success
if (CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) {
break;
}
if (Count == 99) {
if (!EfiAtRuntime ()) {
DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n",
__FUNCTION__, __LINE__));
}
return EFI_DEVICE_ERROR;
}
(VOID)MicroSecondDelay (RTC_DELAY_30_MS);
}
//Polling BMC RTC I2C status
for (Count = 0; Count < 100; Count++) {
Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG);
if ((Temp & BIT3) == 0) {
return EFI_SUCCESS;
}
(VOID)MicroSecondDelay (RTC_DELAY_30_MS);
}
//If the BMC occupies the RTC I2C Channel, write back the CPU side is idle
// or the subsequent BMC will not preempt
Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG);
Temp = Temp & (~CPU_GET_I2C_CONTROL);
WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp);
return EFI_NOT_READY;
}
VOID
ReleaseOwnershipOfRtc (
VOID
)
{
UINT8 Temp;
Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG);
Temp = Temp & ~CPU_GET_I2C_CONTROL;
WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp);
return ;
}