VOID BoardInformation(void) { UINT8 tCPLD_LOGIC_VERSION; UINT8 tPRODUCT_VERSION; UINT8 tCPLD_LOGIC_COMPLIER_YEAR; UINT8 tCPLD_LOGIC_COMPLIER_MONTH; UINT8 tCPLD_LOGIC_COMPLIER_DAY; UINT8 tCPLD_LOGIC_COMPLIER_HOUR; UINT8 tCPLD_LOGIC_COMPLIER_MINUTE; UINT8 tBOARD_ID; UINT8 tBOM_VERSION; DEBUG((EFI_D_ERROR, "------------------------------------------------------\n")); tCPLD_LOGIC_VERSION = ReadCpldReg(CPLD_LOGIC_VERSION); tPRODUCT_VERSION = ReadCpldReg(PRODUCT_VERSION); tCPLD_LOGIC_COMPLIER_YEAR = ReadCpldReg(CPLD_LOGIC_COMPLIER_YEAR); tCPLD_LOGIC_COMPLIER_MONTH = ReadCpldReg(CPLD_LOGIC_COMPLIER_MONTH); tCPLD_LOGIC_COMPLIER_DAY = ReadCpldReg(CPLD_LOGIC_COMPLIER_DAY); tCPLD_LOGIC_COMPLIER_HOUR = ReadCpldReg(CPLD_LOGIC_COMPLIER_HOUR); tCPLD_LOGIC_COMPLIER_MINUTE = ReadCpldReg(CPLD_LOGIC_COMPLIER_MINUTE); tBOARD_ID = ReadCpldReg(BOARD_ID); tBOM_VERSION = ReadCpldReg(BOM_VERSION); DEBUG((EFI_D_ERROR, "Logic Version: %02d\n",tCPLD_LOGIC_VERSION)); DEBUG((EFI_D_ERROR, "Product Version: %02d\n",tPRODUCT_VERSION)); DEBUG((EFI_D_ERROR, "CPLD Logic Build time: 20%02d-%02d-%02d %02d:%02d\n",tCPLD_LOGIC_COMPLIER_YEAR,tCPLD_LOGIC_COMPLIER_MONTH, tCPLD_LOGIC_COMPLIER_DAY,tCPLD_LOGIC_COMPLIER_HOUR,tCPLD_LOGIC_COMPLIER_MINUTE)); DEBUG((EFI_D_ERROR, "Board ID: %02d\n",tBOARD_ID)); DEBUG((EFI_D_ERROR, "BOM Version: %02d\n",tBOM_VERSION)); return; }
EFI_STATUS SwitchRtcI2cChannelAndLock ( VOID ) { UINT8 Temp; UINT8 Count; for (Count = 0; Count < 20; Count++) { Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); if ((Temp & BMC_I2C_STATUS) != 0) { //The I2C channel is shared with BMC, //Check if BMC has taken ownership of I2C. //If so, wait 30ms, then try again. //If not, start using I2C. //And the CPLD_I2C_SWITCH_FLAG will be set to CPU_GET_I2C_CONTROL //BMC will check this flag to decide to use I2C or not. MicroSecondDelay (30000); continue; } Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); Temp = Temp | CPU_GET_I2C_CONTROL; WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); //This is empirical value,give cpld some time to make sure the //value is wrote in MicroSecondDelay (2); Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); if ((Temp & CPU_GET_I2C_CONTROL) == CPU_GET_I2C_CONTROL) { return EFI_SUCCESS; } //There need 30ms to keep consistent with the previous loops if the CPU failed //to get control of I2C MicroSecondDelay (30000); } Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); Temp = Temp & ~CPU_GET_I2C_CONTROL; WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); return EFI_NOT_READY; }
UINT32 OemGetCurrentBiosChannel(VOID) { UINTN RegAddr = CPLD_BIOS_CURRENT_CHANNEL_REG_D02; UINT8 Value; Value = ReadCpldReg(RegAddr); if (1==(Value&0x01)) { return 1; } else { return 0; } }
/** Sets the current local time and date information. @param Time A pointer to the current time. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER A time field is out of range. @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. **/ EFI_STATUS EFIAPI LibSetTime ( IN EFI_TIME *Time ) { EFI_STATUS Status = EFI_SUCCESS; I2C_DEVICE Dev; UINT8 Temp; UINT16 BaseYear = 1900; // Check the input parameters are within the range specified by UEFI if(!IsTimeValid(Time)){ return EFI_INVALID_PARAMETER; } Status = SwitchRtcI2cChannelAndLock(); if(EFI_ERROR (Status)) { return Status; } // Initialize the hardware if not already done if (!mDS3231Initialized) { Status = InitializeDS3231 (); if (EFI_ERROR (Status)) { goto EXIT; } } (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev)); Temp = ((Time->Second/10)<<4) | (Time->Second%10); MicroSecondDelay(1000); Status = I2CWrite(&Dev,DS3231_REGADDR_SECONDS,1,&Temp); if(EFI_ERROR (Status)){ goto EXIT; } Temp = ((Time->Minute/10)<<4) | (Time->Minute%10); MicroSecondDelay(1000); Status = I2CWrite(&Dev,DS3231_REGADDR_MIUTES,1,&Temp); if(EFI_ERROR (Status)){ goto EXIT; } Temp = 0; if(Time->Hour > 19){ Temp = 2; } else if(Time->Hour > 9){ Temp = 1; } Temp = (Temp << 4) | (Time->Hour%10); MicroSecondDelay(1000); Status = I2CWrite(&Dev,DS3231_REGADDR_HOURS,1,&Temp); if(EFI_ERROR (Status)){ goto EXIT; } Temp = ((Time->Day/10)<<4) | (Time->Day%10); MicroSecondDelay(1000); Status = I2CWrite(&Dev,DS3231_REGADDR_DATE,1,&Temp); if(EFI_ERROR (Status)){ goto EXIT; } Temp = 0; if(Time->Year >= 2000){ Temp = 0x8; BaseYear = 2000; } if(Time->Month > 9){ Temp |= 0x1; } Temp = (Temp<<4) | (Time->Month%10); MicroSecondDelay(1000); Status = I2CWrite(&Dev,DS3231_REGADDR_MONTH,1,&Temp); if(EFI_ERROR (Status)){ goto EXIT; } Temp = (((Time->Year-BaseYear)/10)<<4) | (Time->Year%10); MicroSecondDelay(1000); Status = I2CWrite(&Dev,DS3231_REGADDR_YEAR,1,&Temp); if(EFI_ERROR (Status)){ goto EXIT; } EXIT: Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); Temp = Temp & ~CPU_GET_I2C_CONTROL; WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); return Status; }
/** Returns the current time and date information, and the time-keeping capabilities of the hardware platform. @param Time A pointer to storage to receive a snapshot of the current time. @param Capabilities An optional pointer to a buffer to receive the real time clock device's capabilities. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Time is NULL. @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. **/ EFI_STATUS EFIAPI LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 Temp; UINT8 BaseHour = 0; UINT16 BaseYear = 1900; I2C_DEVICE Dev; // Ensure Time is a valid pointer if (NULL == Time) { return EFI_INVALID_PARAMETER; } Status = SwitchRtcI2cChannelAndLock(); if(EFI_ERROR (Status)) { return Status; } // Initialize the hardware if not already done if (!mDS3231Initialized) { Status = InitializeDS3231 (); if (EFI_ERROR (Status)) { Status = EFI_NOT_READY; goto GExit; } } (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev)); Status |= I2CRead(&Dev,DS3231_REGADDR_MONTH,1,&Temp); Time->Month = ((Temp>>4)&1)*10+(Temp&0x0F); if(Temp&0x80){ BaseYear = 2000; } Status |= I2CRead(&Dev,DS3231_REGADDR_YEAR,1,&Temp); Time->Year = BaseYear+(Temp>>4) *10 + (Temp&0x0F); Status |= I2CRead(&Dev,DS3231_REGADDR_DATE,1,&Temp); Time->Day = ((Temp>>4)&3) *10 + (Temp&0x0F); Status |= I2CRead(&Dev,DS3231_REGADDR_HOURS,1,&Temp); BaseHour = 0; if((Temp&0x30) == 0x30){ Status = EFI_DEVICE_ERROR; goto GExit; }else if(Temp&0x20){ BaseHour = 20; }else if(Temp&0x10){ BaseHour = 10; } Time->Hour = BaseHour + (Temp&0x0F); Status |= I2CRead(&Dev,DS3231_REGADDR_MIUTES,1,&Temp); Time->Minute = ((Temp>>4)&7) * 10 + (Temp&0x0F); Status |= I2CRead(&Dev,DS3231_REGADDR_SECONDS,1,&Temp); Time->Second = (Temp>>4) * 10 + (Temp&0x0F); Time->Nanosecond = 0; Time->Daylight = 0; Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; if((EFI_ERROR(Status)) || (!IsTimeValid(Time)) || ((Time->Year - BaseYear) > 99)) { Status = EFI_UNSUPPORTED; } GExit: Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); Temp = Temp & ~CPU_GET_I2C_CONTROL; WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); return Status; }
/** Returns the current time and date information, and the time-keeping capabilities of the hardware platform. @param Time A pointer to storage to receive a snapshot of the current time. @param Capabilities An optional pointer to a buffer to receive the real time clock device's capabilities. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Time is NULL. @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure. **/ EFI_STATUS EFIAPI LibGetTime ( OUT EFI_TIME *Time, OUT EFI_TIME_CAPABILITIES *Capabilities ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 Temp; UINT8 BaseHour = 0; UINT16 BaseYear = 1900; I2C_DEVICE Dev; // Ensure Time is a valid pointer if (NULL == Time) { return EFI_INVALID_PARAMETER; } Temp = ReadCpldReg(0x17); while( (Temp & BIT3) != 0) { Temp = ReadCpldReg(0x17); } WriteCpldReg(0x17,0x4); // Initialize the hardware if not already done if (!mDS3231Initialized) { Status = InitializeDS3231 (); if (EFI_ERROR (Status)) { return EFI_NOT_READY; } } (VOID) CopyMem(&Dev, &gDS3231RtcDevice, sizeof(Dev)); //获取月份 Status |= I2CRead(&Dev,DS3231_REGADDR_MONTH,1,&Temp); Time->Month = ((Temp>>4)&1)*10+(Temp&0x0F); if(Temp&0x80){ BaseYear = 2000; //跨过了一个世纪 } //获取年份 Status |= I2CRead(&Dev,DS3231_REGADDR_YEAR,1,&Temp); Time->Year = BaseYear+(Temp>>4) *10 + (Temp&0x0F); //获取日期 Status |= I2CRead(&Dev,DS3231_REGADDR_DATE,1,&Temp); Time->Day = ((Temp>>4)&3) *10 + (Temp&0x0F); //获取小时 Status |= I2CRead(&Dev,DS3231_REGADDR_HOURS,1,&Temp); BaseHour = 0; if((Temp&0x30) == 0x30){ return EFI_DEVICE_ERROR; }else if(Temp&0x20){ BaseHour = 20; }else if(Temp&0x10){ BaseHour = 10; } Time->Hour = BaseHour + (Temp&0x0F); //获取分钟 Status |= I2CRead(&Dev,DS3231_REGADDR_MIUTES,1,&Temp); Time->Minute = ((Temp>>4)&7) * 10 + (Temp&0x0F); //获取秒数 Status |= I2CRead(&Dev,DS3231_REGADDR_SECONDS,1,&Temp); Time->Second = (Temp>>4) * 10 + (Temp&0x0F); Time->Nanosecond = 0; Time->Daylight = 0; Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE; if((EFI_ERROR(Status)) || (!TimeValid(Time)) || ((Time->Year - BaseYear) > 99)) { return EFI_DEVICE_ERROR; } WriteCpldReg(0x17,0x0); return EFI_SUCCESS; }