梳理UEFI的Rtc的Driver

初识CSDN

本人小白一枚,最近在看Rtc管理这一块,也是第一次写博客,请多多指教哦~
下面以MIPS平台的龙芯3A4000为例,以及掌握的固件为例进行梳理.

自我认识的Rtc时钟

关于这一章后期会补上.

剖析代码

Driver的入口函数
InitializePcRtc 这个函数是PcRtc module的入口点函数.
首先介绍下Rtc上电初始化的代码:

EFI_STATUS
PcRtcInit (                                                                                                                                                                                                                                  
  IN PC_RTC_MODULE_GLOBALS  *Global
  )
{
  EFI_STATUS      Status;
  EFI_TIME        Time;
  UINTN           DataSize;
  UINT32  year, month, date, hour, min, sec;
  LS7A_TOY_REG0   RTC_READ0;
  //
  // Acquire RTC Lock to make access to RTC atomic
  //
  if (!EfiAtRuntime ()) {
    EfiAcquireLock (&Global->RtcLock);
  }
  outl(LS7A_RTC_CTRL_REG, LS7A_RTC_CTRL_INIT_DATA);//Enable Rtc
  outl(LS7A_TOY_TRIM_REG, 0);//0x20
  outl(LS7A_RTC_TRIM_REG, 0);//0x60 must init 0

  RTC_READ0.Data = inl (LS7A_TOY_READ0_REG);

  year  = inl(LS7A_TOY_READ1_REG);
  month = RTC_READ0.Bits.TOY_MONTH;
  date  = RTC_READ0.Bits.TOY_DAY;
  hour  = RTC_READ0.Bits.TOY_HOUR;
  min   = RTC_READ0.Bits.TOY_MIN;
  sec   = RTC_READ0.Bits.TOY_SEC;
//init read reg

  if ((year < 0 || year > 16383)
__|| (month < 1 || month > 12)
__|| (date < 1 || date > 31)
__|| (hour > 23) || (min > 59)
__|| (sec > 59)) {

    /* 2000-01-01 00:00:00 */
    RTC_READ0.Bits.TOY_MONTH = 1;
    RTC_READ0.Bits.TOY_DAY = 1;
    outl(LS7A_TOY_WRITE1_REG, 0x64);
    outl(LS7A_TOY_WRITE0_REG, RTC_READ0.Data);
  }//if it is error ,reset Rtc reg.
    
  //
  // Get the Time/Date/Daylight Savings values.
  //
  RTC_READ0.Data = inl (LS7A_TOY_READ0_REG);
                                                                                                                                                                                                                                             
  year = (inl(LS7A_TOY_READ1_REG) & 0x3fff) + 1900;
  month = RTC_READ0.Bits.TOY_MONTH;
  date  = RTC_READ0.Bits.TOY_DAY;
  hour  = RTC_READ0.Bits.TOY_HOUR;
  min   = RTC_READ0.Bits.TOY_MIN;
  sec   = RTC_READ0.Bits.TOY_SEC;
  Time.Second = sec;
  Time.Minute = min;
  Time.Hour   = hour;
  Time.Day    = date;
  Time.Month  = month;
  Time.Year   = year;

  //
  // Release RTC Lock.
  //
  if (!EfiAtRuntime ()) {
    EfiReleaseLock (&Global->RtcLock);
  }

  //
  // Get the data of Daylight saving and time zone, if they have been
  // stored in NV variable during previous boot.
  //
  DataSize = sizeof (UINT32);
  Status = EfiGetVariable (
             L"RTC",
             &gEfiCallerIdGuid,
             NULL,
             &DataSize,
             (VOID *) &RTC_READ0.Data
       );
  if (!EFI_ERROR (Status)) {
    Time.TimeZone = (INT16) RTC_READ0.Data;
    Time.Daylight = (UINT8) (RTC_READ0.Data >> 16);
  } else {
    Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
    Time.Daylight = 0;
  }

  //
  // Reset time value according to new RTC configuration
  //
#ifndef LS7A1000
  Status = PcRtcSetTime (&Time, Global);
#else
  /*
   * If PcRtcSetTime is called at this time on the Ls7A1000 platform, the RTC time will be
   * faster than real time. So now call the NULL funciton to fix it, but this bug needs to
   * find real results in the future.
   */
  Status = NullFunction (&Time, Global);// TODO
#endif
  if(!EFI_ERROR (Status)) {
    return EFI_SUCCESS;
  } else {
    return EFI_DEVICE_ERROR;
  }
}


EFI_STATUS
EFIAPI
InitializePcRtc (
  IN EFI_HANDLE                            ImageHandle,
  IN EFI_SYSTEM_TABLE                      *SystemTable
  )
{
  EFI_STATUS  Status;

  EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_HIGH_LEVEL);

  Status = PcRtcInit (&mModuleGlobal);
 // if (EFI_ERROR (Status)) {
  //  return Status;
 // }

  gRT->GetTime       = PcRtcEfiGetTime;
  gRT->SetTime       = PcRtcEfiSetTime;
  gRT->GetWakeupTime = PcRtcEfiGetWakeupTime;
  gRT->SetWakeupTime = PcRtcEfiSetWakeupTime;

  Status = gBS->InstallMultipleProtocolInterfaces (                                                                                                                                                                                          
                  &mHandle,
                  &gEfiRealTimeClockArchProtocolGuid,
                  NULL,
                  NULL
                  );  
  ASSERT_EFI_ERROR (Status);

  return Status;
}

这个函数安装了UEFI的 Runtime Service中的GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().
gRT里定义的函数point 对应的CPU时钟寄存器的读写操作.
先来熟悉一下四个接口函数吧,关于Lock的操作后续再补.

typedef struct {
  EFI_LOCK  RtcLock;
  INT16     SavedTimeZone;
  UINT8     Daylight;
} PC_RTC_MODULE_GLOBALS;

EFI_STATUS
PcRtcGetTime (
  OUT  EFI_TIME               *Time,
  OUT  EFI_TIME_CAPABILITIES  *Capabilities,  OPTIONAL
  IN   PC_RTC_MODULE_GLOBALS  *Global
  )
{
  ZeroMem(Time,sizeof(EFI_TIME));
  LS7A_TOY_REG0 RTC_READ0;
//  UINT32 Val;        
  //
  // Check parameters for null pointer
  //
  if (Time == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Acquire RTC Lock to make access to RTC atomic
  //
  if (!EfiAtRuntime ()) {
    EfiAcquireLock (&Global->RtcLock);
  }

  RTC_READ0.Data = inl (LS7A_TOY_READ0_REG);

/*  Val = RTC_READ0.Data;
  Time->Second  = (Val >> TOY_SEC_SHIFT) & TOY_SEC_MASK;
  Time->Minute  = (Val >> TOY_MIN_SHIFT) & TOY_MIN_MASK;
  Time->Hour    = (Val >> TOY_HOUR_SHIFT) & TOY_HOUR_MASK;
  Time->Day     = (Val >> TOY_DAY_SHIFT) & TOY_DAY_MASK;
  Time->Month   = ((Val >> TOY_MON_SHIFT) & TOY_MON_MASK);
  Time->Year    = ((inl(LS7A_TOY_READ1_REG) & 0x3fff) + 1900);
*/

  Time->Second  = RTC_READ0.Bits.TOY_SEC;
  Time->Minute  = RTC_READ0.Bits.TOY_MIN;
  Time->Hour    = RTC_READ0.Bits.TOY_HOUR;
  Time->Day     = RTC_READ0.Bits.TOY_DAY;
  Time->Month   = RTC_READ0.Bits.TOY_MONTH;
  Time->Year    = (inl(LS7A_TOY_READ1_REG) + 1900);

  //
  // Release RTC Lock.
  //
  if (!EfiAtRuntime ()) {
    EfiReleaseLock (&Global->RtcLock);
  }

  // 
  // Get the variable that contains the TimeZone and Daylight fields
  //
  Time->TimeZone  = Global->SavedTimeZone;
  Time->Daylight  = Global->Daylight;

  return EFI_SUCCESS;
}

首先先从Rtc寄存器offset 0x2c内读取32Bit数据存储到LS7A_TOY_REG.类型如下:

typedef union {
  struct {
__  UINT32 TOY_MILLISEC_:4;
__  UINT32 TOY_SEC__:6;
__  UINT32 TOY_MIN__:6;
__  UINT32 TOY_HOUR_:5;
__  UINT32 TOY_DAY__:5;
__  UINT32 TOY_MONTH__:6;
  }Bits;
  UINT32               Data;
}LS7A_TOY_REG0 //这是一个联合类型 指保存桥片的Rtc寄存器内的数值

其实这个联合已经定义好了哪些位存取的哪些数据,很好的可以解析出来,如何以后抽象寄存器,你也可以按这种方式抽象.
7桥片内RTC寄存器数据

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来杯清咖_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值