ARM Packages: Fixed line endings
This large code change only modifies the line endings to be CRLF to be compliant with the EDK2 coding convention document. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14088 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,376 +1,376 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#include <Guid/GlobalVariable.h>
|
||||
|
||||
#include "LcdGraphicsOutputDxe.h"
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* This file implements the Graphics Output protocol on ArmVersatileExpress
|
||||
* using the Lcd controller
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
|
||||
BOOLEAN mDisplayInitialized = FALSE;
|
||||
|
||||
LCD_INSTANCE mLcdTemplate = {
|
||||
LCD_INSTANCE_SIGNATURE,
|
||||
NULL, // Handle
|
||||
{ // ModeInfo
|
||||
0, // Version
|
||||
0, // HorizontalResolution
|
||||
0, // VerticalResolution
|
||||
PixelBltOnly, // PixelFormat
|
||||
0, // PixelInformation
|
||||
0, // PixelsPerScanLine
|
||||
},
|
||||
{
|
||||
0, // MaxMode;
|
||||
0, // Mode;
|
||||
NULL, // Info;
|
||||
0, // SizeOfInfo;
|
||||
0, // FrameBufferBase;
|
||||
0 // FrameBufferSize;
|
||||
},
|
||||
{ // Gop
|
||||
LcdGraphicsQueryMode, // QueryMode
|
||||
LcdGraphicsSetMode, // SetMode
|
||||
LcdGraphicsBlt, // Blt
|
||||
NULL // *Mode
|
||||
},
|
||||
{ // DevicePath
|
||||
{
|
||||
{
|
||||
HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
|
||||
(UINT8) (sizeof(VENDOR_DEVICE_PATH)),
|
||||
(UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8),
|
||||
},
|
||||
// Hardware Device Path for Lcd
|
||||
EFI_CALLER_ID_GUID // Use the driver's GUID
|
||||
},
|
||||
|
||||
{
|
||||
END_DEVICE_PATH_TYPE,
|
||||
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
||||
sizeof(EFI_DEVICE_PATH_PROTOCOL),
|
||||
0
|
||||
}
|
||||
},
|
||||
(EFI_EVENT) NULL // ExitBootServicesEvent
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
LcdInstanceContructor (
|
||||
OUT LCD_INSTANCE** NewInstance
|
||||
)
|
||||
{
|
||||
LCD_INSTANCE* Instance;
|
||||
|
||||
Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);
|
||||
if (Instance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Instance->Gop.Mode = &Instance->Mode;
|
||||
Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
|
||||
Instance->Mode.Info = &Instance->ModeInfo;
|
||||
|
||||
*NewInstance = Instance;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Function Definitions
|
||||
//
|
||||
|
||||
EFI_STATUS
|
||||
InitializeDisplay (
|
||||
IN LCD_INSTANCE* Instance
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_PHYSICAL_ADDRESS VramBaseAddress;
|
||||
UINTN VramSize;
|
||||
|
||||
Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Setup the LCD
|
||||
Status = LcdInitialize (VramBaseAddress);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT_ERROR_LCD_SHUTDOWN;
|
||||
}
|
||||
|
||||
Status = LcdPlatformInitializeDisplay (Instance->Handle);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT_ERROR_LCD_SHUTDOWN;
|
||||
}
|
||||
|
||||
// Setup all the relevant mode information
|
||||
Instance->Gop.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
|
||||
Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
|
||||
Instance->Gop.Mode->FrameBufferSize = VramSize;
|
||||
|
||||
// Set the flag before changing the mode, to avoid infinite loops
|
||||
mDisplayInitialized = TRUE;
|
||||
|
||||
// All is ok, so don't deal with any errors
|
||||
goto EXIT;
|
||||
|
||||
EXIT_ERROR_LCD_SHUTDOWN:
|
||||
DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
|
||||
LcdShutdown ();
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LcdGraphicsOutputDxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
LCD_INSTANCE* Instance;
|
||||
|
||||
Status = LcdInstanceContructor (&Instance);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Install the Graphics Output Protocol and the Device Path
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Instance->Handle,
|
||||
&gEfiGraphicsOutputProtocolGuid, &Instance->Gop,
|
||||
&gEfiDevicePathProtocolGuid, &Instance->DevicePath,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
// When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,
|
||||
// i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_NOTIFY,
|
||||
LcdGraphicsExitBootServicesEvent, NULL,
|
||||
&Instance->ExitBootServicesEvent
|
||||
);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
|
||||
goto EXIT_ERROR_UNINSTALL_PROTOCOL;
|
||||
}
|
||||
|
||||
// To get here, everything must be fine, so just exit
|
||||
goto EXIT;
|
||||
|
||||
EXIT_ERROR_UNINSTALL_PROTOCOL:
|
||||
/* The following function could return an error message,
|
||||
* however, to get here something must have gone wrong already,
|
||||
* so preserve the original error, i.e. don't change
|
||||
* the Status variable, even it fails to uninstall the protocol.
|
||||
*/
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol
|
||||
&gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path
|
||||
NULL
|
||||
);
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* This function should be called
|
||||
* on Event: ExitBootServices
|
||||
* to free up memory, stop the driver
|
||||
* and uninstall the protocols
|
||||
***************************************/
|
||||
VOID
|
||||
LcdGraphicsExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
//TODO: Implement me
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* GraphicsOutput Protocol function, mapping to
|
||||
* EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
|
||||
***************************************/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LcdGraphicsQueryMode (
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN UINT32 ModeNumber,
|
||||
OUT UINTN *SizeOfInfo,
|
||||
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
LCD_INSTANCE *Instance;
|
||||
|
||||
Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
|
||||
|
||||
// Setup the hardware if not already done
|
||||
if( !mDisplayInitialized ) {
|
||||
Status = InitializeDisplay(Instance);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Error checking
|
||||
if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {
|
||||
DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
|
||||
if (*Info == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
|
||||
|
||||
Status = LcdPlatformQueryMode (ModeNumber,*Info);
|
||||
if (EFI_ERROR(Status)) {
|
||||
FreePool(*Info);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* GraphicsOutput Protocol function, mapping to
|
||||
* EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
|
||||
***************************************/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LcdGraphicsSetMode (
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN UINT32 ModeNumber
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;
|
||||
LCD_INSTANCE* Instance;
|
||||
|
||||
Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
|
||||
|
||||
// Setup the hardware if not already done
|
||||
if(!mDisplayInitialized) {
|
||||
Status = InitializeDisplay (Instance);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this mode is supported
|
||||
if( ModeNumber >= This->Mode->MaxMode ) {
|
||||
DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Set the oscillator frequency to support the new mode
|
||||
Status = LcdPlatformSetMode (ModeNumber);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Update the UEFI mode information
|
||||
This->Mode->Mode = ModeNumber;
|
||||
LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);
|
||||
|
||||
// Set the hardware to the new mode
|
||||
Status = LcdSetMode (ModeNumber);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// The UEFI spec requires that we now clear the visible portions of the output display to black.
|
||||
|
||||
// Set the fill colour to black
|
||||
SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
|
||||
|
||||
// Fill the entire visible area with the same colour.
|
||||
Status = This->Blt (
|
||||
This,
|
||||
&FillColour,
|
||||
EfiBltVideoFill,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
This->Mode->Info->HorizontalResolution,
|
||||
This->Mode->Info->VerticalResolution,
|
||||
0);
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
UINTN
|
||||
GetBytesPerPixel (
|
||||
IN LCD_BPP Bpp
|
||||
)
|
||||
{
|
||||
switch(Bpp) {
|
||||
case LCD_BITS_PER_PIXEL_24:
|
||||
return 4;
|
||||
|
||||
case LCD_BITS_PER_PIXEL_16_565:
|
||||
case LCD_BITS_PER_PIXEL_16_555:
|
||||
case LCD_BITS_PER_PIXEL_12_444:
|
||||
return 2;
|
||||
|
||||
case LCD_BITS_PER_PIXEL_8:
|
||||
case LCD_BITS_PER_PIXEL_4:
|
||||
case LCD_BITS_PER_PIXEL_2:
|
||||
case LCD_BITS_PER_PIXEL_1:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#include <Guid/GlobalVariable.h>
|
||||
|
||||
#include "LcdGraphicsOutputDxe.h"
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* This file implements the Graphics Output protocol on ArmVersatileExpress
|
||||
* using the Lcd controller
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
//
|
||||
// Global variables
|
||||
//
|
||||
|
||||
BOOLEAN mDisplayInitialized = FALSE;
|
||||
|
||||
LCD_INSTANCE mLcdTemplate = {
|
||||
LCD_INSTANCE_SIGNATURE,
|
||||
NULL, // Handle
|
||||
{ // ModeInfo
|
||||
0, // Version
|
||||
0, // HorizontalResolution
|
||||
0, // VerticalResolution
|
||||
PixelBltOnly, // PixelFormat
|
||||
0, // PixelInformation
|
||||
0, // PixelsPerScanLine
|
||||
},
|
||||
{
|
||||
0, // MaxMode;
|
||||
0, // Mode;
|
||||
NULL, // Info;
|
||||
0, // SizeOfInfo;
|
||||
0, // FrameBufferBase;
|
||||
0 // FrameBufferSize;
|
||||
},
|
||||
{ // Gop
|
||||
LcdGraphicsQueryMode, // QueryMode
|
||||
LcdGraphicsSetMode, // SetMode
|
||||
LcdGraphicsBlt, // Blt
|
||||
NULL // *Mode
|
||||
},
|
||||
{ // DevicePath
|
||||
{
|
||||
{
|
||||
HARDWARE_DEVICE_PATH, HW_VENDOR_DP,
|
||||
(UINT8) (sizeof(VENDOR_DEVICE_PATH)),
|
||||
(UINT8) ((sizeof(VENDOR_DEVICE_PATH)) >> 8),
|
||||
},
|
||||
// Hardware Device Path for Lcd
|
||||
EFI_CALLER_ID_GUID // Use the driver's GUID
|
||||
},
|
||||
|
||||
{
|
||||
END_DEVICE_PATH_TYPE,
|
||||
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
||||
sizeof(EFI_DEVICE_PATH_PROTOCOL),
|
||||
0
|
||||
}
|
||||
},
|
||||
(EFI_EVENT) NULL // ExitBootServicesEvent
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
LcdInstanceContructor (
|
||||
OUT LCD_INSTANCE** NewInstance
|
||||
)
|
||||
{
|
||||
LCD_INSTANCE* Instance;
|
||||
|
||||
Instance = AllocateCopyPool (sizeof(LCD_INSTANCE), &mLcdTemplate);
|
||||
if (Instance == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Instance->Gop.Mode = &Instance->Mode;
|
||||
Instance->Gop.Mode->MaxMode = LcdPlatformGetMaxMode ();
|
||||
Instance->Mode.Info = &Instance->ModeInfo;
|
||||
|
||||
*NewInstance = Instance;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Function Definitions
|
||||
//
|
||||
|
||||
EFI_STATUS
|
||||
InitializeDisplay (
|
||||
IN LCD_INSTANCE* Instance
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_PHYSICAL_ADDRESS VramBaseAddress;
|
||||
UINTN VramSize;
|
||||
|
||||
Status = LcdPlatformGetVram (&VramBaseAddress, &VramSize);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Setup the LCD
|
||||
Status = LcdInitialize (VramBaseAddress);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT_ERROR_LCD_SHUTDOWN;
|
||||
}
|
||||
|
||||
Status = LcdPlatformInitializeDisplay (Instance->Handle);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT_ERROR_LCD_SHUTDOWN;
|
||||
}
|
||||
|
||||
// Setup all the relevant mode information
|
||||
Instance->Gop.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
|
||||
Instance->Gop.Mode->FrameBufferBase = VramBaseAddress;
|
||||
Instance->Gop.Mode->FrameBufferSize = VramSize;
|
||||
|
||||
// Set the flag before changing the mode, to avoid infinite loops
|
||||
mDisplayInitialized = TRUE;
|
||||
|
||||
// All is ok, so don't deal with any errors
|
||||
goto EXIT;
|
||||
|
||||
EXIT_ERROR_LCD_SHUTDOWN:
|
||||
DEBUG((DEBUG_ERROR, "InitializeDisplay: ERROR - Can not initialise the display. Exit Status=%r\n", Status));
|
||||
LcdShutdown ();
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LcdGraphicsOutputDxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
LCD_INSTANCE* Instance;
|
||||
|
||||
Status = LcdInstanceContructor (&Instance);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Install the Graphics Output Protocol and the Device Path
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Instance->Handle,
|
||||
&gEfiGraphicsOutputProtocolGuid, &Instance->Gop,
|
||||
&gEfiDevicePathProtocolGuid, &Instance->DevicePath,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the protocol. Exit Status=%r\n", Status));
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
// When ExitBootServices starts, this function here will make sure that the graphics driver will shut down properly,
|
||||
// i.e. it will free up all allocated memory and perform any necessary hardware re-configuration.
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_NOTIFY,
|
||||
LcdGraphicsExitBootServicesEvent, NULL,
|
||||
&Instance->ExitBootServicesEvent
|
||||
);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG((DEBUG_ERROR, "GraphicsOutputDxeInitialize: Can not install the ExitBootServicesEvent handler. Exit Status=%r\n", Status));
|
||||
goto EXIT_ERROR_UNINSTALL_PROTOCOL;
|
||||
}
|
||||
|
||||
// To get here, everything must be fine, so just exit
|
||||
goto EXIT;
|
||||
|
||||
EXIT_ERROR_UNINSTALL_PROTOCOL:
|
||||
/* The following function could return an error message,
|
||||
* however, to get here something must have gone wrong already,
|
||||
* so preserve the original error, i.e. don't change
|
||||
* the Status variable, even it fails to uninstall the protocol.
|
||||
*/
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Instance->Handle,
|
||||
&gEfiGraphicsOutputProtocolGuid, &Instance->Gop, // Uninstall Graphics Output protocol
|
||||
&gEfiDevicePathProtocolGuid, &Instance->DevicePath, // Uninstall device path
|
||||
NULL
|
||||
);
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* This function should be called
|
||||
* on Event: ExitBootServices
|
||||
* to free up memory, stop the driver
|
||||
* and uninstall the protocols
|
||||
***************************************/
|
||||
VOID
|
||||
LcdGraphicsExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
//TODO: Implement me
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* GraphicsOutput Protocol function, mapping to
|
||||
* EFI_GRAPHICS_OUTPUT_PROTOCOL.QueryMode
|
||||
***************************************/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LcdGraphicsQueryMode (
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN UINT32 ModeNumber,
|
||||
OUT UINTN *SizeOfInfo,
|
||||
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
LCD_INSTANCE *Instance;
|
||||
|
||||
Instance = LCD_INSTANCE_FROM_GOP_THIS(This);
|
||||
|
||||
// Setup the hardware if not already done
|
||||
if( !mDisplayInitialized ) {
|
||||
Status = InitializeDisplay(Instance);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Error checking
|
||||
if ( (This == NULL) || (Info == NULL) || (SizeOfInfo == NULL) || (ModeNumber >= This->Mode->MaxMode) ) {
|
||||
DEBUG((DEBUG_ERROR, "LcdGraphicsQueryMode: ERROR - For mode number %d : Invalid Parameter.\n", ModeNumber ));
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
|
||||
if (*Info == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
*SizeOfInfo = sizeof( EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
|
||||
|
||||
Status = LcdPlatformQueryMode (ModeNumber,*Info);
|
||||
if (EFI_ERROR(Status)) {
|
||||
FreePool(*Info);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* GraphicsOutput Protocol function, mapping to
|
||||
* EFI_GRAPHICS_OUTPUT_PROTOCOL.SetMode
|
||||
***************************************/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LcdGraphicsSetMode (
|
||||
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
||||
IN UINT32 ModeNumber
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL FillColour;
|
||||
LCD_INSTANCE* Instance;
|
||||
|
||||
Instance = LCD_INSTANCE_FROM_GOP_THIS (This);
|
||||
|
||||
// Setup the hardware if not already done
|
||||
if(!mDisplayInitialized) {
|
||||
Status = InitializeDisplay (Instance);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this mode is supported
|
||||
if( ModeNumber >= This->Mode->MaxMode ) {
|
||||
DEBUG((DEBUG_ERROR, "LcdGraphicsSetMode: ERROR - Unsupported mode number %d .\n", ModeNumber ));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Set the oscillator frequency to support the new mode
|
||||
Status = LcdPlatformSetMode (ModeNumber);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Update the UEFI mode information
|
||||
This->Mode->Mode = ModeNumber;
|
||||
LcdPlatformQueryMode (ModeNumber,&Instance->ModeInfo);
|
||||
|
||||
// Set the hardware to the new mode
|
||||
Status = LcdSetMode (ModeNumber);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// The UEFI spec requires that we now clear the visible portions of the output display to black.
|
||||
|
||||
// Set the fill colour to black
|
||||
SetMem (&FillColour, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
|
||||
|
||||
// Fill the entire visible area with the same colour.
|
||||
Status = This->Blt (
|
||||
This,
|
||||
&FillColour,
|
||||
EfiBltVideoFill,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
This->Mode->Info->HorizontalResolution,
|
||||
This->Mode->Info->VerticalResolution,
|
||||
0);
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
UINTN
|
||||
GetBytesPerPixel (
|
||||
IN LCD_BPP Bpp
|
||||
)
|
||||
{
|
||||
switch(Bpp) {
|
||||
case LCD_BITS_PER_PIXEL_24:
|
||||
return 4;
|
||||
|
||||
case LCD_BITS_PER_PIXEL_16_565:
|
||||
case LCD_BITS_PER_PIXEL_16_555:
|
||||
case LCD_BITS_PER_PIXEL_12_444:
|
||||
return 2;
|
||||
|
||||
case LCD_BITS_PER_PIXEL_8:
|
||||
case LCD_BITS_PER_PIXEL_4:
|
||||
case LCD_BITS_PER_PIXEL_2:
|
||||
case LCD_BITS_PER_PIXEL_1:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -1,56 +1,56 @@
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for PL111LcdGraphicsOutputDxe module
|
||||
#
|
||||
# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PL111LcdGraphicsDxe
|
||||
FILE_GUID = 407B4008-BF5B-11DF-9547-CF16E0D72085
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = LcdGraphicsOutputDxeInitialize
|
||||
|
||||
[Sources.common]
|
||||
LcdGraphicsOutputDxe.c
|
||||
LcdGraphicsOutputBlt.c
|
||||
PL111Lcd.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
UefiLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
TimerLib
|
||||
UefiDriverEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
IoLib
|
||||
BaseMemoryLib
|
||||
LcdPlatformLib
|
||||
|
||||
[Protocols]
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
|
||||
[FixedPcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdPL111LcdBase
|
||||
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for PL111LcdGraphicsOutputDxe module
|
||||
#
|
||||
# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PL111LcdGraphicsDxe
|
||||
FILE_GUID = 407B4008-BF5B-11DF-9547-CF16E0D72085
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = LcdGraphicsOutputDxeInitialize
|
||||
|
||||
[Sources.common]
|
||||
LcdGraphicsOutputDxe.c
|
||||
LcdGraphicsOutputBlt.c
|
||||
PL111Lcd.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
UefiLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
TimerLib
|
||||
UefiDriverEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
IoLib
|
||||
BaseMemoryLib
|
||||
LcdPlatformLib
|
||||
|
||||
[Protocols]
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiGraphicsOutputProtocolGuid
|
||||
|
||||
[FixedPcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdPL111LcdBase
|
||||
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
||||
|
@@ -1,119 +1,119 @@
|
||||
/** @file NorFlashBlockIoDxe.c
|
||||
|
||||
Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#include "NorFlashDxe.h"
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
NOR_FLASH_INSTANCE *Instance;
|
||||
|
||||
Instance = INSTANCE_FROM_BLKIO_THIS(This);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
|
||||
|
||||
return NorFlashReset (Instance);
|
||||
}
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
NOR_FLASH_INSTANCE *Instance;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Instance = INSTANCE_FROM_BLKIO_THIS(This);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
|
||||
|
||||
if( !This->Media->MediaPresent ) {
|
||||
Status = EFI_NO_MEDIA;
|
||||
} else if( This->Media->MediaId != MediaId ) {
|
||||
Status = EFI_MEDIA_CHANGED;
|
||||
} else {
|
||||
Status = NorFlashReadBlocks (Instance,Lba,BufferSizeInBytes,Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
NOR_FLASH_INSTANCE *Instance;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Instance = INSTANCE_FROM_BLKIO_THIS(This);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
|
||||
|
||||
if( !This->Media->MediaPresent ) {
|
||||
Status = EFI_NO_MEDIA;
|
||||
} else if( This->Media->MediaId != MediaId ) {
|
||||
Status = EFI_MEDIA_CHANGED;
|
||||
} else if( This->Media->ReadOnly ) {
|
||||
Status = EFI_WRITE_PROTECTED;
|
||||
} else {
|
||||
Status = NorFlashWriteBlocks (Instance,Lba,BufferSizeInBytes,Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
// No Flush required for the NOR Flash driver
|
||||
// because cache operations are not permitted.
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
|
||||
|
||||
// Nothing to do so just return without error
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
/** @file NorFlashBlockIoDxe.c
|
||||
|
||||
Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#include "NorFlashDxe.h"
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
NOR_FLASH_INSTANCE *Instance;
|
||||
|
||||
Instance = INSTANCE_FROM_BLKIO_THIS(This);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
|
||||
|
||||
return NorFlashReset (Instance);
|
||||
}
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
NOR_FLASH_INSTANCE *Instance;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Instance = INSTANCE_FROM_BLKIO_THIS(This);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
|
||||
|
||||
if( !This->Media->MediaPresent ) {
|
||||
Status = EFI_NO_MEDIA;
|
||||
} else if( This->Media->MediaId != MediaId ) {
|
||||
Status = EFI_MEDIA_CHANGED;
|
||||
} else {
|
||||
Status = NorFlashReadBlocks (Instance,Lba,BufferSizeInBytes,Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
NOR_FLASH_INSTANCE *Instance;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Instance = INSTANCE_FROM_BLKIO_THIS(This);
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
|
||||
|
||||
if( !This->Media->MediaPresent ) {
|
||||
Status = EFI_NO_MEDIA;
|
||||
} else if( This->Media->MediaId != MediaId ) {
|
||||
Status = EFI_MEDIA_CHANGED;
|
||||
} else if( This->Media->ReadOnly ) {
|
||||
Status = EFI_WRITE_PROTECTED;
|
||||
} else {
|
||||
Status = NorFlashWriteBlocks (Instance,Lba,BufferSizeInBytes,Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
// No Flush required for the NOR Flash driver
|
||||
// because cache operations are not permitted.
|
||||
|
||||
DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
|
||||
|
||||
// Nothing to do so just return without error
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,316 +1,316 @@
|
||||
/** @file NorFlashDxe.h
|
||||
|
||||
Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __NOR_FLASH_DXE_H__
|
||||
#define __NOR_FLASH_DXE_H__
|
||||
|
||||
|
||||
#include <Base.h>
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/NorFlashPlatformLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#define NOR_FLASH_ERASE_RETRY 10
|
||||
|
||||
// Device access macros
|
||||
// These are necessary because we use 2 x 16bit parts to make up 32bit data
|
||||
|
||||
#define HIGH_16_BITS 0xFFFF0000
|
||||
#define LOW_16_BITS 0x0000FFFF
|
||||
#define LOW_8_BITS 0x000000FF
|
||||
|
||||
#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
|
||||
|
||||
#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
|
||||
#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
|
||||
|
||||
// Each command must be sent simultaneously to both chips,
|
||||
// i.e. at the lower 16 bits AND at the higher 16 bits
|
||||
#define CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
|
||||
#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
|
||||
#define SEND_NOR_COMMAND(BaseAddr,Offset,Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
|
||||
#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)((Lba) * LbaSize) )
|
||||
|
||||
// Status Register Bits
|
||||
#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
|
||||
#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
|
||||
#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
|
||||
#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
|
||||
#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
|
||||
#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
|
||||
#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
|
||||
#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
|
||||
|
||||
// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
|
||||
|
||||
// On chip buffer size for buffered programming operations
|
||||
// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
|
||||
// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
|
||||
#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
|
||||
#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
|
||||
#define MAX_BUFFERED_PROG_ITERATIONS 10000000
|
||||
#define BOUNDARY_OF_32_WORDS 0x7F
|
||||
|
||||
// CFI Addresses
|
||||
#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
|
||||
#define P30_CFI_ADDR_VENDOR_ID 0x13
|
||||
|
||||
// CFI Data
|
||||
#define CFI_QRY 0x00595251
|
||||
|
||||
// READ Commands
|
||||
#define P30_CMD_READ_DEVICE_ID 0x0090
|
||||
#define P30_CMD_READ_STATUS_REGISTER 0x0070
|
||||
#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
|
||||
#define P30_CMD_READ_ARRAY 0x00FF
|
||||
#define P30_CMD_READ_CFI_QUERY 0x0098
|
||||
|
||||
// WRITE Commands
|
||||
#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
|
||||
#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
|
||||
#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
|
||||
#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
|
||||
#define P30_CMD_BEFP_SETUP 0x0080
|
||||
#define P30_CMD_BEFP_CONFIRM 0x00D0
|
||||
|
||||
// ERASE Commands
|
||||
#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
|
||||
#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
|
||||
|
||||
// SUSPEND Commands
|
||||
#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
|
||||
#define P30_CMD_SUSPEND_RESUME 0x00D0
|
||||
|
||||
// BLOCK LOCKING / UNLOCKING Commands
|
||||
#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
|
||||
#define P30_CMD_LOCK_BLOCK 0x0001
|
||||
#define P30_CMD_UNLOCK_BLOCK 0x00D0
|
||||
#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
|
||||
|
||||
// PROTECTION Commands
|
||||
#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
|
||||
|
||||
// CONFIGURATION Commands
|
||||
#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
|
||||
#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
|
||||
|
||||
#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
|
||||
#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
|
||||
#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
|
||||
|
||||
typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
|
||||
|
||||
typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) (NOR_FLASH_INSTANCE* Instance);
|
||||
|
||||
typedef struct {
|
||||
VENDOR_DEVICE_PATH Vendor;
|
||||
EFI_DEVICE_PATH_PROTOCOL End;
|
||||
} NOR_FLASH_DEVICE_PATH;
|
||||
|
||||
struct _NOR_FLASH_INSTANCE {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
BOOLEAN Initialized;
|
||||
NOR_FLASH_INITIALIZE Initialize;
|
||||
|
||||
UINTN DeviceBaseAddress;
|
||||
UINTN RegionBaseAddress;
|
||||
UINTN Size;
|
||||
EFI_LBA StartLba;
|
||||
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
|
||||
EFI_BLOCK_IO_MEDIA Media;
|
||||
|
||||
BOOLEAN SupportFvb;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
|
||||
|
||||
NOR_FLASH_DEVICE_PATH DevicePath;
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashReadCfiData (
|
||||
IN UINTN DeviceBaseAddress,
|
||||
IN UINTN CFI_Offset,
|
||||
IN UINT32 NumberOfBytes,
|
||||
OUT UINT32 *Data
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashWriteBuffer (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN UINTN TargetAddress,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN UINT32 *Buffer
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// NorFlashFvbDxe.c
|
||||
//
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashFvbInitialize (
|
||||
IN NOR_FLASH_INSTANCE* Instance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbGetAttributes(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
OUT EFI_FVB_ATTRIBUTES_2 *Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbSetAttributes(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbGetPhysicalAddress(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Address
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbGetBlockSize(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
OUT UINTN *BlockSize,
|
||||
OUT UINTN *NumberOfBlocks
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbRead(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN OUT UINTN *NumBytes,
|
||||
IN OUT UINT8 *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbWrite(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN OUT UINTN *NumBytes,
|
||||
IN UINT8 *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbEraseBlocks(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
...
|
||||
);
|
||||
|
||||
//
|
||||
// NorFlashDxe.c
|
||||
//
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashUnlockAndEraseSingleBlock (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN UINTN BlockAddress
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashWriteSingleBlock (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINT32 *DataBuffer,
|
||||
IN UINT32 BlockSizeInWords
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashWriteBlocks (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashReadBlocks (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashReset (
|
||||
IN NOR_FLASH_INSTANCE *Instance
|
||||
);
|
||||
|
||||
#endif /* __NOR_FLASH_DXE_H__ */
|
||||
/** @file NorFlashDxe.h
|
||||
|
||||
Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __NOR_FLASH_DXE_H__
|
||||
#define __NOR_FLASH_DXE_H__
|
||||
|
||||
|
||||
#include <Base.h>
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/NorFlashPlatformLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#define NOR_FLASH_ERASE_RETRY 10
|
||||
|
||||
// Device access macros
|
||||
// These are necessary because we use 2 x 16bit parts to make up 32bit data
|
||||
|
||||
#define HIGH_16_BITS 0xFFFF0000
|
||||
#define LOW_16_BITS 0x0000FFFF
|
||||
#define LOW_8_BITS 0x000000FF
|
||||
|
||||
#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
|
||||
|
||||
#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )
|
||||
#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )
|
||||
|
||||
// Each command must be sent simultaneously to both chips,
|
||||
// i.e. at the lower 16 bits AND at the higher 16 bits
|
||||
#define CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr) ((BaseAddr) + ((OffsetAddr) << 2))
|
||||
#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
|
||||
#define SEND_NOR_COMMAND(BaseAddr,Offset,Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))
|
||||
#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)((Lba) * LbaSize) )
|
||||
|
||||
// Status Register Bits
|
||||
#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)
|
||||
#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)
|
||||
#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)
|
||||
#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)
|
||||
#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)
|
||||
#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)
|
||||
#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)
|
||||
#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)
|
||||
|
||||
// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
|
||||
|
||||
// On chip buffer size for buffered programming operations
|
||||
// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
|
||||
// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
|
||||
#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)
|
||||
#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
|
||||
#define MAX_BUFFERED_PROG_ITERATIONS 10000000
|
||||
#define BOUNDARY_OF_32_WORDS 0x7F
|
||||
|
||||
// CFI Addresses
|
||||
#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10
|
||||
#define P30_CFI_ADDR_VENDOR_ID 0x13
|
||||
|
||||
// CFI Data
|
||||
#define CFI_QRY 0x00595251
|
||||
|
||||
// READ Commands
|
||||
#define P30_CMD_READ_DEVICE_ID 0x0090
|
||||
#define P30_CMD_READ_STATUS_REGISTER 0x0070
|
||||
#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050
|
||||
#define P30_CMD_READ_ARRAY 0x00FF
|
||||
#define P30_CMD_READ_CFI_QUERY 0x0098
|
||||
|
||||
// WRITE Commands
|
||||
#define P30_CMD_WORD_PROGRAM_SETUP 0x0040
|
||||
#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010
|
||||
#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8
|
||||
#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0
|
||||
#define P30_CMD_BEFP_SETUP 0x0080
|
||||
#define P30_CMD_BEFP_CONFIRM 0x00D0
|
||||
|
||||
// ERASE Commands
|
||||
#define P30_CMD_BLOCK_ERASE_SETUP 0x0020
|
||||
#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0
|
||||
|
||||
// SUSPEND Commands
|
||||
#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0
|
||||
#define P30_CMD_SUSPEND_RESUME 0x00D0
|
||||
|
||||
// BLOCK LOCKING / UNLOCKING Commands
|
||||
#define P30_CMD_LOCK_BLOCK_SETUP 0x0060
|
||||
#define P30_CMD_LOCK_BLOCK 0x0001
|
||||
#define P30_CMD_UNLOCK_BLOCK 0x00D0
|
||||
#define P30_CMD_LOCK_DOWN_BLOCK 0x002F
|
||||
|
||||
// PROTECTION Commands
|
||||
#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
|
||||
|
||||
// CONFIGURATION Commands
|
||||
#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
|
||||
#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003
|
||||
|
||||
#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
|
||||
#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
|
||||
#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
|
||||
|
||||
typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
|
||||
|
||||
typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) (NOR_FLASH_INSTANCE* Instance);
|
||||
|
||||
typedef struct {
|
||||
VENDOR_DEVICE_PATH Vendor;
|
||||
EFI_DEVICE_PATH_PROTOCOL End;
|
||||
} NOR_FLASH_DEVICE_PATH;
|
||||
|
||||
struct _NOR_FLASH_INSTANCE {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
BOOLEAN Initialized;
|
||||
NOR_FLASH_INITIALIZE Initialize;
|
||||
|
||||
UINTN DeviceBaseAddress;
|
||||
UINTN RegionBaseAddress;
|
||||
UINTN Size;
|
||||
EFI_LBA StartLba;
|
||||
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
|
||||
EFI_BLOCK_IO_MEDIA Media;
|
||||
|
||||
BOOLEAN SupportFvb;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
|
||||
|
||||
NOR_FLASH_DEVICE_PATH DevicePath;
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashReadCfiData (
|
||||
IN UINTN DeviceBaseAddress,
|
||||
IN UINTN CFI_Offset,
|
||||
IN UINT32 NumberOfBytes,
|
||||
OUT UINT32 *Data
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashWriteBuffer (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN UINTN TargetAddress,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN UINT32 *Buffer
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
//
|
||||
// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashBlockIoFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// NorFlashFvbDxe.c
|
||||
//
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
NorFlashFvbInitialize (
|
||||
IN NOR_FLASH_INSTANCE* Instance
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbGetAttributes(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
OUT EFI_FVB_ATTRIBUTES_2 *Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbSetAttributes(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbGetPhysicalAddress(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Address
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbGetBlockSize(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
OUT UINTN *BlockSize,
|
||||
OUT UINTN *NumberOfBlocks
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbRead(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN OUT UINTN *NumBytes,
|
||||
IN OUT UINT8 *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbWrite(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN OUT UINTN *NumBytes,
|
||||
IN UINT8 *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FvbEraseBlocks(
|
||||
IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
|
||||
...
|
||||
);
|
||||
|
||||
//
|
||||
// NorFlashDxe.c
|
||||
//
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashUnlockAndEraseSingleBlock (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN UINTN BlockAddress
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashWriteSingleBlock (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINT32 *DataBuffer,
|
||||
IN UINT32 BlockSizeInWords
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashWriteBlocks (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashReadBlocks (
|
||||
IN NOR_FLASH_INSTANCE *Instance,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSizeInBytes,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
NorFlashReset (
|
||||
IN NOR_FLASH_INSTANCE *Instance
|
||||
);
|
||||
|
||||
#endif /* __NOR_FLASH_DXE_H__ */
|
||||
|
@@ -1,68 +1,68 @@
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for NorFlashDxe module
|
||||
#
|
||||
# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmVeNorFlashDxe
|
||||
FILE_GUID = 93E34C7E-B50E-11DF-9223-2443DFD72085
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = NorFlashInitialise
|
||||
|
||||
[Sources.common]
|
||||
NorFlashDxe.c
|
||||
NorFlashFvbDxe.c
|
||||
NorFlashBlockIoDxe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
IoLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
HobLib
|
||||
NorFlashPlatformLib
|
||||
UefiLib
|
||||
UefiDriverEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
|
||||
[Guids]
|
||||
gEfiSystemNvDataFvGuid
|
||||
gEfiVariableGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiFirmwareVolumeBlockProtocolGuid
|
||||
|
||||
[Pcd.common]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
|
||||
|
||||
gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked
|
||||
|
||||
[Depex]
|
||||
#
|
||||
# NorFlashDxe must be loaded before VariableRuntimeDxe in case empty flash needs populating with default values
|
||||
#
|
||||
BEFORE gVariableRuntimeDxeFileGuid
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for NorFlashDxe module
|
||||
#
|
||||
# Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmVeNorFlashDxe
|
||||
FILE_GUID = 93E34C7E-B50E-11DF-9223-2443DFD72085
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = NorFlashInitialise
|
||||
|
||||
[Sources.common]
|
||||
NorFlashDxe.c
|
||||
NorFlashFvbDxe.c
|
||||
NorFlashBlockIoDxe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
IoLib
|
||||
BaseLib
|
||||
DebugLib
|
||||
HobLib
|
||||
NorFlashPlatformLib
|
||||
UefiLib
|
||||
UefiDriverEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
|
||||
[Guids]
|
||||
gEfiSystemNvDataFvGuid
|
||||
gEfiVariableGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
gEfiFirmwareVolumeBlockProtocolGuid
|
||||
|
||||
[Pcd.common]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
|
||||
|
||||
gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked
|
||||
|
||||
[Depex]
|
||||
#
|
||||
# NorFlashDxe must be loaded before VariableRuntimeDxe in case empty flash needs populating with default values
|
||||
#
|
||||
BEFORE gVariableRuntimeDxeFileGuid
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,344 +1,344 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include <Protocol/EmbeddedGpio.h>
|
||||
#include <Drivers/PL061Gpio.h>
|
||||
|
||||
BOOLEAN mPL061Initialized = FALSE;
|
||||
|
||||
/**
|
||||
Function implementations
|
||||
**/
|
||||
|
||||
EFI_STATUS
|
||||
PL061Identify (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Check if this is a PrimeCell Peripheral
|
||||
if ( (MmioRead8 (PL061_GPIO_PCELL_ID0) != 0x0D)
|
||||
|| (MmioRead8 (PL061_GPIO_PCELL_ID1) != 0xF0)
|
||||
|| (MmioRead8 (PL061_GPIO_PCELL_ID2) != 0x05)
|
||||
|| (MmioRead8 (PL061_GPIO_PCELL_ID3) != 0xB1)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Check if this PrimeCell Peripheral is the PL061 GPIO
|
||||
if ( (MmioRead8 (PL061_GPIO_PERIPH_ID0) != 0x61)
|
||||
|| (MmioRead8 (PL061_GPIO_PERIPH_ID1) != 0x10)
|
||||
|| ((MmioRead8 (PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)
|
||||
|| (MmioRead8 (PL061_GPIO_PERIPH_ID3) != 0x00)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PL061Initialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Check if the PL061 GPIO module exists on board
|
||||
Status = PL061Identify();
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Do other hardware initialisation things here as required
|
||||
|
||||
// Disable Interrupts
|
||||
//if (MmioRead8 (PL061_GPIO_IE_REG) != 0) {
|
||||
// // Ensure interrupts are disabled
|
||||
//}
|
||||
|
||||
mPL061Initialized = TRUE;
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the state of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin to read
|
||||
Value - state of the pin
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - GPIO state returned in Value
|
||||
EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Get (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
OUT UINTN *Value
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
if ( (Value == NULL)
|
||||
|| (Gpio > LAST_GPIO_PIN))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Initialize the hardware if not already done
|
||||
if (!mPL061Initialized) {
|
||||
Status = PL061Initialize();
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) {
|
||||
*Value = 1;
|
||||
} else {
|
||||
*Value = 0;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sets the state of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin to modify
|
||||
Mode - mode to set
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - GPIO set as requested
|
||||
EFI_UNSUPPORTED - Mode is not supported
|
||||
EFI_INVALID_PARAMETER - Gpio pin is out of range
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Set (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
IN EMBEDDED_GPIO_MODE Mode
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
// Check for errors
|
||||
if (Gpio > LAST_GPIO_PIN) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Initialize the hardware if not already done
|
||||
if (!mPL061Initialized) {
|
||||
Status = PL061Initialize();
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Mode)
|
||||
{
|
||||
case GPIO_MODE_INPUT:
|
||||
// Set the corresponding direction bit to LOW for input
|
||||
MmioAnd8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio));
|
||||
break;
|
||||
|
||||
case GPIO_MODE_OUTPUT_0:
|
||||
// Set the corresponding data bit to LOW for 0
|
||||
MmioAnd8 (PL061_GPIO_DATA_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio));
|
||||
// Set the corresponding direction bit to HIGH for output
|
||||
MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio));
|
||||
break;
|
||||
|
||||
case GPIO_MODE_OUTPUT_1:
|
||||
// Set the corresponding data bit to HIGH for 1
|
||||
MmioOr8 (PL061_GPIO_DATA_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio));
|
||||
// Set the corresponding direction bit to HIGH for output
|
||||
MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio));
|
||||
break;
|
||||
|
||||
default:
|
||||
// Other modes are not supported
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the mode (function) of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin
|
||||
Mode - pointer to output mode value
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - mode value retrieved
|
||||
EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetMode (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
OUT EMBEDDED_GPIO_MODE *Mode
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Check for errors
|
||||
if ( (Mode == NULL)
|
||||
|| (Gpio > LAST_GPIO_PIN)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Initialize the hardware if not already done
|
||||
if (!mPL061Initialized) {
|
||||
Status = PL061Initialize();
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it is input or output
|
||||
if (MmioRead8 (PL061_GPIO_DIR_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) {
|
||||
// Pin set to output
|
||||
if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) {
|
||||
*Mode = GPIO_MODE_OUTPUT_1;
|
||||
} else {
|
||||
*Mode = GPIO_MODE_OUTPUT_0;
|
||||
}
|
||||
} else {
|
||||
// Pin set to input
|
||||
*Mode = GPIO_MODE_INPUT;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sets the pull-up / pull-down resistor of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin
|
||||
Direction - pull-up, pull-down, or none
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_UNSUPPORTED - Can not perform the requested operation
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SetPull (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
IN EMBEDDED_GPIO_PULL Direction
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Protocol variable definition
|
||||
**/
|
||||
EMBEDDED_GPIO gGpio = {
|
||||
Get,
|
||||
Set,
|
||||
GetMode,
|
||||
SetPull
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize the state information for the Embedded Gpio protocol.
|
||||
|
||||
@param ImageHandle of the loaded driver
|
||||
@param SystemTable Pointer to the System Table
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PL061InstallProtocol (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
//
|
||||
// Make sure the Gpio protocol has not been installed in the system yet.
|
||||
//
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);
|
||||
|
||||
// Install the Embedded GPIO Protocol onto a new handle
|
||||
Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEmbeddedGpioProtocolGuid, &gGpio,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include <Protocol/EmbeddedGpio.h>
|
||||
#include <Drivers/PL061Gpio.h>
|
||||
|
||||
BOOLEAN mPL061Initialized = FALSE;
|
||||
|
||||
/**
|
||||
Function implementations
|
||||
**/
|
||||
|
||||
EFI_STATUS
|
||||
PL061Identify (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Check if this is a PrimeCell Peripheral
|
||||
if ( (MmioRead8 (PL061_GPIO_PCELL_ID0) != 0x0D)
|
||||
|| (MmioRead8 (PL061_GPIO_PCELL_ID1) != 0xF0)
|
||||
|| (MmioRead8 (PL061_GPIO_PCELL_ID2) != 0x05)
|
||||
|| (MmioRead8 (PL061_GPIO_PCELL_ID3) != 0xB1)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Check if this PrimeCell Peripheral is the PL061 GPIO
|
||||
if ( (MmioRead8 (PL061_GPIO_PERIPH_ID0) != 0x61)
|
||||
|| (MmioRead8 (PL061_GPIO_PERIPH_ID1) != 0x10)
|
||||
|| ((MmioRead8 (PL061_GPIO_PERIPH_ID2) & 0xF) != 0x04)
|
||||
|| (MmioRead8 (PL061_GPIO_PERIPH_ID3) != 0x00)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PL061Initialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Check if the PL061 GPIO module exists on board
|
||||
Status = PL061Identify();
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Do other hardware initialisation things here as required
|
||||
|
||||
// Disable Interrupts
|
||||
//if (MmioRead8 (PL061_GPIO_IE_REG) != 0) {
|
||||
// // Ensure interrupts are disabled
|
||||
//}
|
||||
|
||||
mPL061Initialized = TRUE;
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the state of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin to read
|
||||
Value - state of the pin
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - GPIO state returned in Value
|
||||
EFI_INVALID_PARAMETER - Value is NULL pointer or Gpio pin is out of range
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Get (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
OUT UINTN *Value
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
if ( (Value == NULL)
|
||||
|| (Gpio > LAST_GPIO_PIN))
|
||||
{
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Initialize the hardware if not already done
|
||||
if (!mPL061Initialized) {
|
||||
Status = PL061Initialize();
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) {
|
||||
*Value = 1;
|
||||
} else {
|
||||
*Value = 0;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sets the state of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin to modify
|
||||
Mode - mode to set
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - GPIO set as requested
|
||||
EFI_UNSUPPORTED - Mode is not supported
|
||||
EFI_INVALID_PARAMETER - Gpio pin is out of range
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Set (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
IN EMBEDDED_GPIO_MODE Mode
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
// Check for errors
|
||||
if (Gpio > LAST_GPIO_PIN) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Initialize the hardware if not already done
|
||||
if (!mPL061Initialized) {
|
||||
Status = PL061Initialize();
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Mode)
|
||||
{
|
||||
case GPIO_MODE_INPUT:
|
||||
// Set the corresponding direction bit to LOW for input
|
||||
MmioAnd8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio));
|
||||
break;
|
||||
|
||||
case GPIO_MODE_OUTPUT_0:
|
||||
// Set the corresponding data bit to LOW for 0
|
||||
MmioAnd8 (PL061_GPIO_DATA_REG, GPIO_PIN_MASK_LOW_8BIT(Gpio));
|
||||
// Set the corresponding direction bit to HIGH for output
|
||||
MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio));
|
||||
break;
|
||||
|
||||
case GPIO_MODE_OUTPUT_1:
|
||||
// Set the corresponding data bit to HIGH for 1
|
||||
MmioOr8 (PL061_GPIO_DATA_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio));
|
||||
// Set the corresponding direction bit to HIGH for output
|
||||
MmioOr8 (PL061_GPIO_DIR_REG, GPIO_PIN_MASK_HIGH_8BIT(Gpio));
|
||||
break;
|
||||
|
||||
default:
|
||||
// Other modes are not supported
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Gets the mode (function) of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin
|
||||
Mode - pointer to output mode value
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - mode value retrieved
|
||||
EFI_INVALID_PARAMETER - Mode is a null pointer or Gpio pin is out of range
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetMode (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
OUT EMBEDDED_GPIO_MODE *Mode
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Check for errors
|
||||
if ( (Mode == NULL)
|
||||
|| (Gpio > LAST_GPIO_PIN)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Initialize the hardware if not already done
|
||||
if (!mPL061Initialized) {
|
||||
Status = PL061Initialize();
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it is input or output
|
||||
if (MmioRead8 (PL061_GPIO_DIR_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) {
|
||||
// Pin set to output
|
||||
if (MmioRead8 (PL061_GPIO_DATA_REG) & GPIO_PIN_MASK_HIGH_8BIT(Gpio)) {
|
||||
*Mode = GPIO_MODE_OUTPUT_1;
|
||||
} else {
|
||||
*Mode = GPIO_MODE_OUTPUT_0;
|
||||
}
|
||||
} else {
|
||||
// Pin set to input
|
||||
*Mode = GPIO_MODE_INPUT;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sets the pull-up / pull-down resistor of a GPIO pin
|
||||
|
||||
Arguments:
|
||||
|
||||
This - pointer to protocol
|
||||
Gpio - which pin
|
||||
Direction - pull-up, pull-down, or none
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_UNSUPPORTED - Can not perform the requested operation
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SetPull (
|
||||
IN EMBEDDED_GPIO *This,
|
||||
IN EMBEDDED_GPIO_PIN Gpio,
|
||||
IN EMBEDDED_GPIO_PULL Direction
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Protocol variable definition
|
||||
**/
|
||||
EMBEDDED_GPIO gGpio = {
|
||||
Get,
|
||||
Set,
|
||||
GetMode,
|
||||
SetPull
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize the state information for the Embedded Gpio protocol.
|
||||
|
||||
@param ImageHandle of the loaded driver
|
||||
@param SystemTable Pointer to the System Table
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PL061InstallProtocol (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
//
|
||||
// Make sure the Gpio protocol has not been installed in the system yet.
|
||||
//
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEmbeddedGpioProtocolGuid);
|
||||
|
||||
// Install the Embedded GPIO Protocol onto a new handle
|
||||
Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEmbeddedGpioProtocolGuid, &gGpio,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@@ -1,50 +1,50 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PL061GpioDxe
|
||||
FILE_GUID = 5c1997d7-8d45-4f21-af3c-2206b8ed8bec
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = PL061InstallProtocol
|
||||
[Sources.common]
|
||||
PL061Gpio.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[Pcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdPL061GpioBase
|
||||
|
||||
[Protocols]
|
||||
gEmbeddedGpioProtocolGuid
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PL061GpioDxe
|
||||
FILE_GUID = 5c1997d7-8d45-4f21-af3c-2206b8ed8bec
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = PL061InstallProtocol
|
||||
[Sources.common]
|
||||
PL061Gpio.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[Pcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdPL061GpioBase
|
||||
|
||||
[Protocols]
|
||||
gEmbeddedGpioProtocolGuid
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
|
@@ -1,395 +1,395 @@
|
||||
/** @file
|
||||
Template for Timer Architecture Protocol driver of the ARM flavor
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
|
||||
#include <Protocol/Timer.h>
|
||||
#include <Protocol/HardwareInterrupt.h>
|
||||
|
||||
#include <Drivers/SP804Timer.h>
|
||||
|
||||
#define SP804_TIMER_PERIODIC_BASE ((UINTN)PcdGet32 (PcdSP804TimerPeriodicBase))
|
||||
#define SP804_TIMER_METRONOME_BASE ((UINTN)PcdGet32 (PcdSP804TimerMetronomeBase))
|
||||
#define SP804_TIMER_PERFORMANCE_BASE ((UINTN)PcdGet32 (PcdSP804TimerPerformanceBase))
|
||||
|
||||
// The notification function to call on every timer interrupt.
|
||||
EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
// The current period of the timer interrupt
|
||||
UINT64 mTimerPeriod = 0;
|
||||
|
||||
// Cached copy of the Hardware Interrupt protocol instance
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
|
||||
|
||||
// Cached interrupt vector
|
||||
UINTN gVector;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
C Interrupt Handler called in the interrupt context when Source interrupt is active.
|
||||
|
||||
|
||||
@param Source Source of the interrupt. Hardware routing off a specific platform defines
|
||||
what source means.
|
||||
|
||||
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
|
||||
update the system context after the return from the interrupt if
|
||||
modified. Don't change these values unless you know what you are doing
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TimerInterruptHandler (
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
EFI_TPL OriginalTPL;
|
||||
|
||||
//
|
||||
// DXE core uses this callback for the EFI timer tick. The DXE core uses locks
|
||||
// that raise to TPL_HIGH and then restore back to current level. Thus we need
|
||||
// to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
|
||||
//
|
||||
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
// If the interrupt is shared then we must check if this interrupt source is the one associated to this Timer
|
||||
if (MmioRead32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_MSK_INT_STS_REG) != 0) {
|
||||
// Clear the periodic interrupt
|
||||
MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_INT_CLR_REG, 0);
|
||||
|
||||
// Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers
|
||||
gInterrupt->EndOfInterrupt (gInterrupt, Source);
|
||||
|
||||
if (mTimerNotifyFunction) {
|
||||
mTimerNotifyFunction (mTimerPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OriginalTPL);
|
||||
}
|
||||
|
||||
/**
|
||||
This function registers the handler NotifyFunction so it is called every time
|
||||
the timer interrupt fires. It also passes the amount of time since the last
|
||||
handler call to the NotifyFunction. If NotifyFunction is NULL, then the
|
||||
handler is unregistered. If the handler is registered, then EFI_SUCCESS is
|
||||
returned. If the CPU does not support registering a timer interrupt handler,
|
||||
then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
|
||||
when a handler is already registered, then EFI_ALREADY_STARTED is returned.
|
||||
If an attempt is made to unregister a handler when a handler is not registered,
|
||||
then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
|
||||
register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
|
||||
is returned.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param NotifyFunction The function to call when a timer interrupt fires. This
|
||||
function executes at TPL_HIGH_LEVEL. The DXE Core will
|
||||
register a handler for the timer interrupt, so it can know
|
||||
how much time has passed. This information is used to
|
||||
signal timer based events. NULL will unregister the handler.
|
||||
@retval EFI_SUCCESS The timer handler was registered.
|
||||
@retval EFI_UNSUPPORTED The platform does not support timer interrupts.
|
||||
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
|
||||
registered.
|
||||
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
|
||||
previously registered.
|
||||
@retval EFI_DEVICE_ERROR The timer handler could not be registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverRegisterHandler (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
IN EFI_TIMER_NOTIFY NotifyFunction
|
||||
)
|
||||
{
|
||||
if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
mTimerNotifyFunction = NotifyFunction;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Make sure all Dual Timers are disabled
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
// Disable 'Periodic Operation' timer if enabled
|
||||
if (MmioRead32(SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) {
|
||||
MmioAnd32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, 0);
|
||||
}
|
||||
|
||||
// Disable 'Metronome/Delay' timer if enabled
|
||||
if (MmioRead32(SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) {
|
||||
MmioAnd32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG, 0);
|
||||
}
|
||||
|
||||
// Disable 'Performance' timer if enabled
|
||||
if (MmioRead32(SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) {
|
||||
MmioAnd32 (SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This function adjusts the period of timer interrupts to the value specified
|
||||
by TimerPeriod. If the timer period is updated, then the selected timer
|
||||
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
|
||||
If an error occurs while attempting to update the timer period, then the
|
||||
timer hardware will be put back in its state prior to this call, and
|
||||
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
|
||||
is disabled. This is not the same as disabling the CPU's interrupts.
|
||||
Instead, it must either turn off the timer hardware, or it must adjust the
|
||||
interrupt controller so that a CPU interrupt is not generated when the timer
|
||||
interrupt fires.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is
|
||||
returned. If the timer is programmable, then the timer period
|
||||
will be rounded up to the nearest timer period that is supported
|
||||
by the timer hardware. If TimerPeriod is set to 0, then the
|
||||
timer interrupts will be disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was changed.
|
||||
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
|
||||
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverSetTimerPeriod (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
IN UINT64 TimerPeriod
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 TimerTicks;
|
||||
|
||||
// always disable the timer
|
||||
MmioAnd32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, ~SP804_TIMER_CTRL_ENABLE);
|
||||
|
||||
if (TimerPeriod == 0) {
|
||||
// Leave timer disabled from above, and...
|
||||
|
||||
// Disable timer 0/1 interrupt for a TimerPeriod of 0
|
||||
Status = gInterrupt->DisableInterruptSource (gInterrupt, gVector);
|
||||
} else {
|
||||
// Convert TimerPeriod into 1MHz clock counts (us units = 100ns units * 10)
|
||||
TimerTicks = DivU64x32 (TimerPeriod, 10);
|
||||
TimerTicks = MultU64x32 (TimerTicks, PcdGet32(PcdSP804TimerFrequencyInMHz));
|
||||
|
||||
// if it's larger than 32-bits, pin to highest value
|
||||
if (TimerTicks > 0xffffffff) {
|
||||
TimerTicks = 0xffffffff;
|
||||
}
|
||||
|
||||
// Program the SP804 timer with the new count value
|
||||
MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_LOAD_REG, TimerTicks);
|
||||
|
||||
// enable the timer
|
||||
MmioOr32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE);
|
||||
|
||||
// enable timer 0/1 interrupts
|
||||
Status = gInterrupt->EnableInterruptSource (gInterrupt, gVector);
|
||||
}
|
||||
|
||||
// Save the new timer period
|
||||
mTimerPeriod = TimerPeriod;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the period of timer interrupts in 100 ns units,
|
||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
||||
returned, then the timer is currently disabled.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
|
||||
0 is returned, then the timer is currently disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverGetTimerPeriod (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
OUT UINT64 *TimerPeriod
|
||||
)
|
||||
{
|
||||
if (TimerPeriod == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*TimerPeriod = mTimerPeriod;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function generates a soft timer interrupt. If the platform does not support soft
|
||||
timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
|
||||
If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
|
||||
service, then a soft timer interrupt will be generated. If the timer interrupt is
|
||||
enabled when this service is called, then the registered handler will be invoked. The
|
||||
registered handler should not be able to distinguish a hardware-generated timer
|
||||
interrupt from a software-generated timer interrupt.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The soft timer interrupt was generated.
|
||||
@retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverGenerateSoftInterrupt (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Interface structure for the Timer Architectural Protocol.
|
||||
|
||||
@par Protocol Description:
|
||||
This protocol provides the services to initialize a periodic timer
|
||||
interrupt, and to register a handler that is called each time the timer
|
||||
interrupt fires. It may also provide a service to adjust the rate of the
|
||||
periodic timer interrupt. When a timer interrupt occurs, the handler is
|
||||
passed the amount of time that has passed since the previous timer
|
||||
interrupt.
|
||||
|
||||
@param RegisterHandler
|
||||
Registers a handler that will be called each time the
|
||||
timer interrupt fires. TimerPeriod defines the minimum
|
||||
time between timer interrupts, so TimerPeriod will also
|
||||
be the minimum time between calls to the registered
|
||||
handler.
|
||||
|
||||
@param SetTimerPeriod
|
||||
Sets the period of the timer interrupt in 100 nS units.
|
||||
This function is optional, and may return EFI_UNSUPPORTED.
|
||||
If this function is supported, then the timer period will
|
||||
be rounded up to the nearest supported timer period.
|
||||
|
||||
|
||||
@param GetTimerPeriod
|
||||
Retrieves the period of the timer interrupt in 100 nS units.
|
||||
|
||||
@param GenerateSoftInterrupt
|
||||
Generates a soft timer interrupt that simulates the firing of
|
||||
the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for
|
||||
a period of time.
|
||||
|
||||
**/
|
||||
EFI_TIMER_ARCH_PROTOCOL gTimer = {
|
||||
TimerDriverRegisterHandler,
|
||||
TimerDriverSetTimerPeriod,
|
||||
TimerDriverGetTimerPeriod,
|
||||
TimerDriverGenerateSoftInterrupt
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the state information for the Timer Architectural Protocol and
|
||||
the Timer Debug support protocol that allows the debugger to break into a
|
||||
running program.
|
||||
|
||||
@param ImageHandle of the loaded driver
|
||||
@param SystemTable Pointer to the System Table
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_HANDLE Handle = NULL;
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Set the interrupt timer number
|
||||
gVector = PcdGet32(PcdSP804TimerPeriodicInterruptNum);
|
||||
|
||||
// Find the interrupt controller protocol. ASSERT if not found.
|
||||
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Disable the timer
|
||||
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Install interrupt handler
|
||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// configure timer 0 for periodic operation, 32 bits, no prescaler, and interrupt enabled
|
||||
MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_PERIODIC | SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1 | SP804_TIMER_CTRL_INT_ENABLE);
|
||||
|
||||
// Set up default timer
|
||||
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Install the Timer Architectural Protocol onto a new handle
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEfiTimerArchProtocolGuid, &gTimer,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR(Status);
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
/** @file
|
||||
Template for Timer Architecture Protocol driver of the ARM flavor
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
|
||||
#include <Protocol/Timer.h>
|
||||
#include <Protocol/HardwareInterrupt.h>
|
||||
|
||||
#include <Drivers/SP804Timer.h>
|
||||
|
||||
#define SP804_TIMER_PERIODIC_BASE ((UINTN)PcdGet32 (PcdSP804TimerPeriodicBase))
|
||||
#define SP804_TIMER_METRONOME_BASE ((UINTN)PcdGet32 (PcdSP804TimerMetronomeBase))
|
||||
#define SP804_TIMER_PERFORMANCE_BASE ((UINTN)PcdGet32 (PcdSP804TimerPerformanceBase))
|
||||
|
||||
// The notification function to call on every timer interrupt.
|
||||
EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
// The current period of the timer interrupt
|
||||
UINT64 mTimerPeriod = 0;
|
||||
|
||||
// Cached copy of the Hardware Interrupt protocol instance
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
|
||||
|
||||
// Cached interrupt vector
|
||||
UINTN gVector;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
C Interrupt Handler called in the interrupt context when Source interrupt is active.
|
||||
|
||||
|
||||
@param Source Source of the interrupt. Hardware routing off a specific platform defines
|
||||
what source means.
|
||||
|
||||
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
|
||||
update the system context after the return from the interrupt if
|
||||
modified. Don't change these values unless you know what you are doing
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TimerInterruptHandler (
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
EFI_TPL OriginalTPL;
|
||||
|
||||
//
|
||||
// DXE core uses this callback for the EFI timer tick. The DXE core uses locks
|
||||
// that raise to TPL_HIGH and then restore back to current level. Thus we need
|
||||
// to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
|
||||
//
|
||||
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
// If the interrupt is shared then we must check if this interrupt source is the one associated to this Timer
|
||||
if (MmioRead32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_MSK_INT_STS_REG) != 0) {
|
||||
// Clear the periodic interrupt
|
||||
MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_INT_CLR_REG, 0);
|
||||
|
||||
// Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers
|
||||
gInterrupt->EndOfInterrupt (gInterrupt, Source);
|
||||
|
||||
if (mTimerNotifyFunction) {
|
||||
mTimerNotifyFunction (mTimerPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OriginalTPL);
|
||||
}
|
||||
|
||||
/**
|
||||
This function registers the handler NotifyFunction so it is called every time
|
||||
the timer interrupt fires. It also passes the amount of time since the last
|
||||
handler call to the NotifyFunction. If NotifyFunction is NULL, then the
|
||||
handler is unregistered. If the handler is registered, then EFI_SUCCESS is
|
||||
returned. If the CPU does not support registering a timer interrupt handler,
|
||||
then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
|
||||
when a handler is already registered, then EFI_ALREADY_STARTED is returned.
|
||||
If an attempt is made to unregister a handler when a handler is not registered,
|
||||
then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
|
||||
register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
|
||||
is returned.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param NotifyFunction The function to call when a timer interrupt fires. This
|
||||
function executes at TPL_HIGH_LEVEL. The DXE Core will
|
||||
register a handler for the timer interrupt, so it can know
|
||||
how much time has passed. This information is used to
|
||||
signal timer based events. NULL will unregister the handler.
|
||||
@retval EFI_SUCCESS The timer handler was registered.
|
||||
@retval EFI_UNSUPPORTED The platform does not support timer interrupts.
|
||||
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
|
||||
registered.
|
||||
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
|
||||
previously registered.
|
||||
@retval EFI_DEVICE_ERROR The timer handler could not be registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverRegisterHandler (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
IN EFI_TIMER_NOTIFY NotifyFunction
|
||||
)
|
||||
{
|
||||
if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
mTimerNotifyFunction = NotifyFunction;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Make sure all Dual Timers are disabled
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
// Disable 'Periodic Operation' timer if enabled
|
||||
if (MmioRead32(SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) {
|
||||
MmioAnd32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, 0);
|
||||
}
|
||||
|
||||
// Disable 'Metronome/Delay' timer if enabled
|
||||
if (MmioRead32(SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) {
|
||||
MmioAnd32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CONTROL_REG, 0);
|
||||
}
|
||||
|
||||
// Disable 'Performance' timer if enabled
|
||||
if (MmioRead32(SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG) & SP804_TIMER_CTRL_ENABLE) {
|
||||
MmioAnd32 (SP804_TIMER_PERFORMANCE_BASE + SP804_TIMER_CONTROL_REG, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This function adjusts the period of timer interrupts to the value specified
|
||||
by TimerPeriod. If the timer period is updated, then the selected timer
|
||||
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
|
||||
If an error occurs while attempting to update the timer period, then the
|
||||
timer hardware will be put back in its state prior to this call, and
|
||||
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
|
||||
is disabled. This is not the same as disabling the CPU's interrupts.
|
||||
Instead, it must either turn off the timer hardware, or it must adjust the
|
||||
interrupt controller so that a CPU interrupt is not generated when the timer
|
||||
interrupt fires.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is
|
||||
returned. If the timer is programmable, then the timer period
|
||||
will be rounded up to the nearest timer period that is supported
|
||||
by the timer hardware. If TimerPeriod is set to 0, then the
|
||||
timer interrupts will be disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was changed.
|
||||
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
|
||||
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverSetTimerPeriod (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
IN UINT64 TimerPeriod
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 TimerTicks;
|
||||
|
||||
// always disable the timer
|
||||
MmioAnd32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, ~SP804_TIMER_CTRL_ENABLE);
|
||||
|
||||
if (TimerPeriod == 0) {
|
||||
// Leave timer disabled from above, and...
|
||||
|
||||
// Disable timer 0/1 interrupt for a TimerPeriod of 0
|
||||
Status = gInterrupt->DisableInterruptSource (gInterrupt, gVector);
|
||||
} else {
|
||||
// Convert TimerPeriod into 1MHz clock counts (us units = 100ns units * 10)
|
||||
TimerTicks = DivU64x32 (TimerPeriod, 10);
|
||||
TimerTicks = MultU64x32 (TimerTicks, PcdGet32(PcdSP804TimerFrequencyInMHz));
|
||||
|
||||
// if it's larger than 32-bits, pin to highest value
|
||||
if (TimerTicks > 0xffffffff) {
|
||||
TimerTicks = 0xffffffff;
|
||||
}
|
||||
|
||||
// Program the SP804 timer with the new count value
|
||||
MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_LOAD_REG, TimerTicks);
|
||||
|
||||
// enable the timer
|
||||
MmioOr32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_ENABLE);
|
||||
|
||||
// enable timer 0/1 interrupts
|
||||
Status = gInterrupt->EnableInterruptSource (gInterrupt, gVector);
|
||||
}
|
||||
|
||||
// Save the new timer period
|
||||
mTimerPeriod = TimerPeriod;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the period of timer interrupts in 100 ns units,
|
||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
||||
returned, then the timer is currently disabled.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
|
||||
0 is returned, then the timer is currently disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverGetTimerPeriod (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
OUT UINT64 *TimerPeriod
|
||||
)
|
||||
{
|
||||
if (TimerPeriod == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*TimerPeriod = mTimerPeriod;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function generates a soft timer interrupt. If the platform does not support soft
|
||||
timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
|
||||
If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
|
||||
service, then a soft timer interrupt will be generated. If the timer interrupt is
|
||||
enabled when this service is called, then the registered handler will be invoked. The
|
||||
registered handler should not be able to distinguish a hardware-generated timer
|
||||
interrupt from a software-generated timer interrupt.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The soft timer interrupt was generated.
|
||||
@retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverGenerateSoftInterrupt (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Interface structure for the Timer Architectural Protocol.
|
||||
|
||||
@par Protocol Description:
|
||||
This protocol provides the services to initialize a periodic timer
|
||||
interrupt, and to register a handler that is called each time the timer
|
||||
interrupt fires. It may also provide a service to adjust the rate of the
|
||||
periodic timer interrupt. When a timer interrupt occurs, the handler is
|
||||
passed the amount of time that has passed since the previous timer
|
||||
interrupt.
|
||||
|
||||
@param RegisterHandler
|
||||
Registers a handler that will be called each time the
|
||||
timer interrupt fires. TimerPeriod defines the minimum
|
||||
time between timer interrupts, so TimerPeriod will also
|
||||
be the minimum time between calls to the registered
|
||||
handler.
|
||||
|
||||
@param SetTimerPeriod
|
||||
Sets the period of the timer interrupt in 100 nS units.
|
||||
This function is optional, and may return EFI_UNSUPPORTED.
|
||||
If this function is supported, then the timer period will
|
||||
be rounded up to the nearest supported timer period.
|
||||
|
||||
|
||||
@param GetTimerPeriod
|
||||
Retrieves the period of the timer interrupt in 100 nS units.
|
||||
|
||||
@param GenerateSoftInterrupt
|
||||
Generates a soft timer interrupt that simulates the firing of
|
||||
the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for
|
||||
a period of time.
|
||||
|
||||
**/
|
||||
EFI_TIMER_ARCH_PROTOCOL gTimer = {
|
||||
TimerDriverRegisterHandler,
|
||||
TimerDriverSetTimerPeriod,
|
||||
TimerDriverGetTimerPeriod,
|
||||
TimerDriverGenerateSoftInterrupt
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the state information for the Timer Architectural Protocol and
|
||||
the Timer Debug support protocol that allows the debugger to break into a
|
||||
running program.
|
||||
|
||||
@param ImageHandle of the loaded driver
|
||||
@param SystemTable Pointer to the System Table
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_HANDLE Handle = NULL;
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Set the interrupt timer number
|
||||
gVector = PcdGet32(PcdSP804TimerPeriodicInterruptNum);
|
||||
|
||||
// Find the interrupt controller protocol. ASSERT if not found.
|
||||
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Disable the timer
|
||||
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Install interrupt handler
|
||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// configure timer 0 for periodic operation, 32 bits, no prescaler, and interrupt enabled
|
||||
MmioWrite32 (SP804_TIMER_PERIODIC_BASE + SP804_TIMER_CONTROL_REG, SP804_TIMER_CTRL_PERIODIC | SP804_TIMER_CTRL_32BIT | SP804_PRESCALE_DIV_1 | SP804_TIMER_CTRL_INT_ENABLE);
|
||||
|
||||
// Set up default timer
|
||||
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Install the Timer Architectural Protocol onto a new handle
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEfiTimerArchProtocolGuid, &gTimer,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR(Status);
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@@ -1,59 +1,59 @@
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for Timer module
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmVeTimerDxe
|
||||
FILE_GUID = a73d663d-a491-4278-9a69-9521be3379f2
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = TimerInitialize
|
||||
|
||||
[Sources.common]
|
||||
SP804Timer.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
UefiRuntimeServicesTableLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
UefiDriverEntryPoint
|
||||
IoLib
|
||||
|
||||
[Guids]
|
||||
|
||||
[Protocols]
|
||||
gEfiTimerArchProtocolGuid
|
||||
gHardwareInterruptProtocolGuid
|
||||
|
||||
[Pcd.common]
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerFrequencyInMHz
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerPeriodicInterruptNum
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerPeriodicBase
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerPerformanceBase
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerMetronomeBase
|
||||
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
|
||||
|
||||
[Depex]
|
||||
gHardwareInterruptProtocolGuid
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for Timer module
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmVeTimerDxe
|
||||
FILE_GUID = a73d663d-a491-4278-9a69-9521be3379f2
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = TimerInitialize
|
||||
|
||||
[Sources.common]
|
||||
SP804Timer.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
UefiRuntimeServicesTableLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
UefiDriverEntryPoint
|
||||
IoLib
|
||||
|
||||
[Guids]
|
||||
|
||||
[Protocols]
|
||||
gEfiTimerArchProtocolGuid
|
||||
gHardwareInterruptProtocolGuid
|
||||
|
||||
[Pcd.common]
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerFrequencyInMHz
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerPeriodicInterruptNum
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerPeriodicBase
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerPerformanceBase
|
||||
gArmPlatformTokenSpaceGuid.PcdSP804TimerMetronomeBase
|
||||
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
|
||||
|
||||
[Depex]
|
||||
gHardwareInterruptProtocolGuid
|
||||
|
@@ -1,387 +1,387 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include <Protocol/WatchdogTimer.h>
|
||||
#include <Drivers/SP805Watchdog.h>
|
||||
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
/**
|
||||
Make sure the SP805 registers are unlocked for writing.
|
||||
|
||||
Note: The SP805 Watchdog Timer supports locking of its registers,
|
||||
i.e. it inhibits all writes to avoid rogue software accidentally
|
||||
corrupting their contents.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Unlock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if( MmioRead32(SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_LOCKED ) {
|
||||
MmioWrite32(SP805_WDOG_LOCK_REG, SP805_WDOG_SPECIAL_UNLOCK_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Make sure the SP805 registers are locked and can not be overwritten.
|
||||
|
||||
Note: The SP805 Watchdog Timer supports locking of its registers,
|
||||
i.e. it inhibits all writes to avoid rogue software accidentally
|
||||
corrupting their contents.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Lock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if( MmioRead32(SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_UNLOCKED ) {
|
||||
// To lock it, just write in any number (except the special unlock code).
|
||||
MmioWrite32(SP805_WDOG_LOCK_REG, SP805_WDOG_LOCK_IS_LOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Stop the SP805 watchdog timer from counting down by disabling interrupts.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Stop (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Disable interrupts
|
||||
if ( (MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) != 0 ) {
|
||||
MmioAnd32(SP805_WDOG_CONTROL_REG, ~SP805_WDOG_CTRL_INTEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the SP805 counting down by enabling interrupts.
|
||||
The count down will start from the value stored in the Load register,
|
||||
not from the value where it was previously stopped.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Start (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Enable interrupts
|
||||
if ( (MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) == 0 ) {
|
||||
MmioOr32(SP805_WDOG_CONTROL_REG, SP805_WDOG_CTRL_INTEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
On exiting boot services we must make sure the SP805 Watchdog Timer
|
||||
is stopped.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
SP805Unlock();
|
||||
SP805Stop();
|
||||
SP805Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
This function registers the handler NotifyFunction so it is called every time
|
||||
the watchdog timer expires. It also passes the amount of time since the last
|
||||
handler call to the NotifyFunction.
|
||||
If NotifyFunction is not NULL and a handler is not already registered,
|
||||
then the new handler is registered and EFI_SUCCESS is returned.
|
||||
If NotifyFunction is NULL, and a handler is already registered,
|
||||
then that handler is unregistered.
|
||||
If an attempt is made to register a handler when a handler is already registered,
|
||||
then EFI_ALREADY_STARTED is returned.
|
||||
If an attempt is made to unregister a handler when a handler is not registered,
|
||||
then EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param NotifyFunction The function to call when a timer interrupt fires. This
|
||||
function executes at TPL_HIGH_LEVEL. The DXE Core will
|
||||
register a handler for the timer interrupt, so it can know
|
||||
how much time has passed. This information is used to
|
||||
signal timer based events. NULL will unregister the handler.
|
||||
|
||||
@retval EFI_SUCCESS The watchdog timer handler was registered.
|
||||
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
|
||||
registered.
|
||||
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
|
||||
previously registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805RegisterHandler (
|
||||
IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction
|
||||
)
|
||||
{
|
||||
// ERROR: This function is not supported.
|
||||
// The hardware watchdog will reset the board
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This function adjusts the period of timer interrupts to the value specified
|
||||
by TimerPeriod. If the timer period is updated, then the selected timer
|
||||
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
|
||||
If an error occurs while attempting to update the timer period, then the
|
||||
timer hardware will be put back in its state prior to this call, and
|
||||
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
|
||||
is disabled. This is not the same as disabling the CPU's interrupts.
|
||||
Instead, it must either turn off the timer hardware, or it must adjust the
|
||||
interrupt controller so that a CPU interrupt is not generated when the timer
|
||||
interrupt fires.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is
|
||||
returned. If the timer is programmable, then the timer period
|
||||
will be rounded up to the nearest timer period that is supported
|
||||
by the timer hardware. If TimerPeriod is set to 0, then the
|
||||
timer interrupts will be disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was changed.
|
||||
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
|
||||
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805SetTimerPeriod (
|
||||
IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
IN UINT64 TimerPeriod // In 100ns units
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT64 Ticks64bit;
|
||||
|
||||
SP805Unlock();
|
||||
|
||||
if( TimerPeriod == 0 ) {
|
||||
// This is a watchdog stop request
|
||||
SP805Stop();
|
||||
goto EXIT;
|
||||
} else {
|
||||
// Calculate the Watchdog ticks required for a delay of (TimerTicks * 100) nanoseconds
|
||||
// The SP805 will count down to ZERO once, generate an interrupt and
|
||||
// then it will again reload the initial value and start again.
|
||||
// On the second time when it reaches ZERO, it will actually reset the board.
|
||||
// Therefore, we need to load half the required delay.
|
||||
//
|
||||
// WatchdogTicks = ((TimerPeriod * 100 * SP805_CLOCK_FREQUENCY) / 1GHz) / 2 ;
|
||||
//
|
||||
// i.e.:
|
||||
//
|
||||
// WatchdogTicks = (TimerPeriod * SP805_CLOCK_FREQUENCY) / 20 MHz ;
|
||||
|
||||
Ticks64bit = DivU64x32(MultU64x32(TimerPeriod, (UINTN)PcdGet32(PcdSP805WatchdogClockFrequencyInHz)), 20000000);
|
||||
|
||||
// The registers in the SP805 are only 32 bits
|
||||
if(Ticks64bit > (UINT64)0xFFFFFFFF) {
|
||||
// We could load the watchdog with the maximum supported value but
|
||||
// if a smaller value was requested, this could have the watchdog
|
||||
// triggering before it was intended.
|
||||
// Better generate an error to let the caller know.
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Update the watchdog with a 32-bit value.
|
||||
MmioWrite32(SP805_WDOG_LOAD_REG, (UINT32)Ticks64bit);
|
||||
|
||||
// Start the watchdog
|
||||
SP805Start();
|
||||
}
|
||||
|
||||
EXIT:
|
||||
// Ensure the watchdog is locked before exiting.
|
||||
SP805Lock();
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the period of timer interrupts in 100 ns units,
|
||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
||||
returned, then the timer is currently disabled.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
|
||||
0 is returned, then the timer is currently disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805GetTimerPeriod (
|
||||
IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
OUT UINT64 *TimerPeriod
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT64 ReturnValue;
|
||||
|
||||
if (TimerPeriod == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Check if the watchdog is stopped
|
||||
if ( (MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) == 0 ) {
|
||||
// It is stopped, so return zero.
|
||||
ReturnValue = 0;
|
||||
} else {
|
||||
// Convert the Watchdog ticks into TimerPeriod
|
||||
// Ensure 64bit arithmetic throughout because the Watchdog ticks may already
|
||||
// be at the maximum 32 bit value and we still need to multiply that by 600.
|
||||
ReturnValue = MultU64x32( MmioRead32(SP805_WDOG_LOAD_REG), 600 );
|
||||
}
|
||||
|
||||
*TimerPeriod = ReturnValue;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Interface structure for the Watchdog Architectural Protocol.
|
||||
|
||||
@par Protocol Description:
|
||||
This protocol provides a service to set the amount of time to wait
|
||||
before firing the watchdog timer, and it also provides a service to
|
||||
register a handler that is invoked when the watchdog timer fires.
|
||||
|
||||
@par When the watchdog timer fires, control will be passed to a handler
|
||||
if one has been registered. If no handler has been registered,
|
||||
or the registered handler returns, then the system will be
|
||||
reset by calling the Runtime Service ResetSystem().
|
||||
|
||||
@param RegisterHandler
|
||||
Registers a handler that will be called each time the
|
||||
watchdogtimer interrupt fires. TimerPeriod defines the minimum
|
||||
time between timer interrupts, so TimerPeriod will also
|
||||
be the minimum time between calls to the registered
|
||||
handler.
|
||||
NOTE: If the watchdog resets the system in hardware, then
|
||||
this function will not have any chance of executing.
|
||||
|
||||
@param SetTimerPeriod
|
||||
Sets the period of the timer interrupt in 100 nS units.
|
||||
This function is optional, and may return EFI_UNSUPPORTED.
|
||||
If this function is supported, then the timer period will
|
||||
be rounded up to the nearest supported timer period.
|
||||
|
||||
@param GetTimerPeriod
|
||||
Retrieves the period of the timer interrupt in 100 nS units.
|
||||
|
||||
**/
|
||||
EFI_WATCHDOG_TIMER_ARCH_PROTOCOL gWatchdogTimer = {
|
||||
(EFI_WATCHDOG_TIMER_REGISTER_HANDLER) SP805RegisterHandler,
|
||||
(EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD) SP805SetTimerPeriod,
|
||||
(EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD) SP805GetTimerPeriod
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize the state information for the Watchdog Timer Architectural Protocol.
|
||||
|
||||
@param ImageHandle of the loaded driver
|
||||
@param SystemTable Pointer to the System Table
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805Initialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
// Unlock access to the SP805 registers
|
||||
SP805Unlock ();
|
||||
|
||||
// Stop the watchdog from triggering unexpectedly
|
||||
SP805Stop ();
|
||||
|
||||
// Set the watchdog to reset the board when triggered
|
||||
if ((MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_RESEN) == 0) {
|
||||
MmioOr32 (SP805_WDOG_CONTROL_REG, SP805_WDOG_CTRL_RESEN);
|
||||
}
|
||||
|
||||
// Prohibit any rogue access to SP805 registers
|
||||
SP805Lock();
|
||||
|
||||
//
|
||||
// Make sure the Watchdog Timer Architectural Protocol has not been installed in the system yet.
|
||||
// This will avoid conflicts with the universal watchdog
|
||||
//
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid);
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Install the Timer Architectural Protocol onto a new handle
|
||||
Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEfiWatchdogTimerArchProtocolGuid, &gWatchdogTimer,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
if(EFI_ERROR(Status)) {
|
||||
// The watchdog failed to initialize
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include <Protocol/WatchdogTimer.h>
|
||||
#include <Drivers/SP805Watchdog.h>
|
||||
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
/**
|
||||
Make sure the SP805 registers are unlocked for writing.
|
||||
|
||||
Note: The SP805 Watchdog Timer supports locking of its registers,
|
||||
i.e. it inhibits all writes to avoid rogue software accidentally
|
||||
corrupting their contents.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Unlock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if( MmioRead32(SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_LOCKED ) {
|
||||
MmioWrite32(SP805_WDOG_LOCK_REG, SP805_WDOG_SPECIAL_UNLOCK_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Make sure the SP805 registers are locked and can not be overwritten.
|
||||
|
||||
Note: The SP805 Watchdog Timer supports locking of its registers,
|
||||
i.e. it inhibits all writes to avoid rogue software accidentally
|
||||
corrupting their contents.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Lock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if( MmioRead32(SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_UNLOCKED ) {
|
||||
// To lock it, just write in any number (except the special unlock code).
|
||||
MmioWrite32(SP805_WDOG_LOCK_REG, SP805_WDOG_LOCK_IS_LOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Stop the SP805 watchdog timer from counting down by disabling interrupts.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Stop (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Disable interrupts
|
||||
if ( (MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) != 0 ) {
|
||||
MmioAnd32(SP805_WDOG_CONTROL_REG, ~SP805_WDOG_CTRL_INTEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the SP805 counting down by enabling interrupts.
|
||||
The count down will start from the value stored in the Load register,
|
||||
not from the value where it was previously stopped.
|
||||
**/
|
||||
inline
|
||||
VOID
|
||||
SP805Start (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Enable interrupts
|
||||
if ( (MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) == 0 ) {
|
||||
MmioOr32(SP805_WDOG_CONTROL_REG, SP805_WDOG_CTRL_INTEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
On exiting boot services we must make sure the SP805 Watchdog Timer
|
||||
is stopped.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
SP805Unlock();
|
||||
SP805Stop();
|
||||
SP805Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
This function registers the handler NotifyFunction so it is called every time
|
||||
the watchdog timer expires. It also passes the amount of time since the last
|
||||
handler call to the NotifyFunction.
|
||||
If NotifyFunction is not NULL and a handler is not already registered,
|
||||
then the new handler is registered and EFI_SUCCESS is returned.
|
||||
If NotifyFunction is NULL, and a handler is already registered,
|
||||
then that handler is unregistered.
|
||||
If an attempt is made to register a handler when a handler is already registered,
|
||||
then EFI_ALREADY_STARTED is returned.
|
||||
If an attempt is made to unregister a handler when a handler is not registered,
|
||||
then EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param NotifyFunction The function to call when a timer interrupt fires. This
|
||||
function executes at TPL_HIGH_LEVEL. The DXE Core will
|
||||
register a handler for the timer interrupt, so it can know
|
||||
how much time has passed. This information is used to
|
||||
signal timer based events. NULL will unregister the handler.
|
||||
|
||||
@retval EFI_SUCCESS The watchdog timer handler was registered.
|
||||
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
|
||||
registered.
|
||||
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
|
||||
previously registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805RegisterHandler (
|
||||
IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction
|
||||
)
|
||||
{
|
||||
// ERROR: This function is not supported.
|
||||
// The hardware watchdog will reset the board
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This function adjusts the period of timer interrupts to the value specified
|
||||
by TimerPeriod. If the timer period is updated, then the selected timer
|
||||
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
|
||||
If an error occurs while attempting to update the timer period, then the
|
||||
timer hardware will be put back in its state prior to this call, and
|
||||
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
|
||||
is disabled. This is not the same as disabling the CPU's interrupts.
|
||||
Instead, it must either turn off the timer hardware, or it must adjust the
|
||||
interrupt controller so that a CPU interrupt is not generated when the timer
|
||||
interrupt fires.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is
|
||||
returned. If the timer is programmable, then the timer period
|
||||
will be rounded up to the nearest timer period that is supported
|
||||
by the timer hardware. If TimerPeriod is set to 0, then the
|
||||
timer interrupts will be disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was changed.
|
||||
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
|
||||
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805SetTimerPeriod (
|
||||
IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
IN UINT64 TimerPeriod // In 100ns units
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT64 Ticks64bit;
|
||||
|
||||
SP805Unlock();
|
||||
|
||||
if( TimerPeriod == 0 ) {
|
||||
// This is a watchdog stop request
|
||||
SP805Stop();
|
||||
goto EXIT;
|
||||
} else {
|
||||
// Calculate the Watchdog ticks required for a delay of (TimerTicks * 100) nanoseconds
|
||||
// The SP805 will count down to ZERO once, generate an interrupt and
|
||||
// then it will again reload the initial value and start again.
|
||||
// On the second time when it reaches ZERO, it will actually reset the board.
|
||||
// Therefore, we need to load half the required delay.
|
||||
//
|
||||
// WatchdogTicks = ((TimerPeriod * 100 * SP805_CLOCK_FREQUENCY) / 1GHz) / 2 ;
|
||||
//
|
||||
// i.e.:
|
||||
//
|
||||
// WatchdogTicks = (TimerPeriod * SP805_CLOCK_FREQUENCY) / 20 MHz ;
|
||||
|
||||
Ticks64bit = DivU64x32(MultU64x32(TimerPeriod, (UINTN)PcdGet32(PcdSP805WatchdogClockFrequencyInHz)), 20000000);
|
||||
|
||||
// The registers in the SP805 are only 32 bits
|
||||
if(Ticks64bit > (UINT64)0xFFFFFFFF) {
|
||||
// We could load the watchdog with the maximum supported value but
|
||||
// if a smaller value was requested, this could have the watchdog
|
||||
// triggering before it was intended.
|
||||
// Better generate an error to let the caller know.
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Update the watchdog with a 32-bit value.
|
||||
MmioWrite32(SP805_WDOG_LOAD_REG, (UINT32)Ticks64bit);
|
||||
|
||||
// Start the watchdog
|
||||
SP805Start();
|
||||
}
|
||||
|
||||
EXIT:
|
||||
// Ensure the watchdog is locked before exiting.
|
||||
SP805Lock();
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the period of timer interrupts in 100 ns units,
|
||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
||||
returned, then the timer is currently disabled.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
|
||||
0 is returned, then the timer is currently disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805GetTimerPeriod (
|
||||
IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
OUT UINT64 *TimerPeriod
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT64 ReturnValue;
|
||||
|
||||
if (TimerPeriod == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Check if the watchdog is stopped
|
||||
if ( (MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_INTEN) == 0 ) {
|
||||
// It is stopped, so return zero.
|
||||
ReturnValue = 0;
|
||||
} else {
|
||||
// Convert the Watchdog ticks into TimerPeriod
|
||||
// Ensure 64bit arithmetic throughout because the Watchdog ticks may already
|
||||
// be at the maximum 32 bit value and we still need to multiply that by 600.
|
||||
ReturnValue = MultU64x32( MmioRead32(SP805_WDOG_LOAD_REG), 600 );
|
||||
}
|
||||
|
||||
*TimerPeriod = ReturnValue;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Interface structure for the Watchdog Architectural Protocol.
|
||||
|
||||
@par Protocol Description:
|
||||
This protocol provides a service to set the amount of time to wait
|
||||
before firing the watchdog timer, and it also provides a service to
|
||||
register a handler that is invoked when the watchdog timer fires.
|
||||
|
||||
@par When the watchdog timer fires, control will be passed to a handler
|
||||
if one has been registered. If no handler has been registered,
|
||||
or the registered handler returns, then the system will be
|
||||
reset by calling the Runtime Service ResetSystem().
|
||||
|
||||
@param RegisterHandler
|
||||
Registers a handler that will be called each time the
|
||||
watchdogtimer interrupt fires. TimerPeriod defines the minimum
|
||||
time between timer interrupts, so TimerPeriod will also
|
||||
be the minimum time between calls to the registered
|
||||
handler.
|
||||
NOTE: If the watchdog resets the system in hardware, then
|
||||
this function will not have any chance of executing.
|
||||
|
||||
@param SetTimerPeriod
|
||||
Sets the period of the timer interrupt in 100 nS units.
|
||||
This function is optional, and may return EFI_UNSUPPORTED.
|
||||
If this function is supported, then the timer period will
|
||||
be rounded up to the nearest supported timer period.
|
||||
|
||||
@param GetTimerPeriod
|
||||
Retrieves the period of the timer interrupt in 100 nS units.
|
||||
|
||||
**/
|
||||
EFI_WATCHDOG_TIMER_ARCH_PROTOCOL gWatchdogTimer = {
|
||||
(EFI_WATCHDOG_TIMER_REGISTER_HANDLER) SP805RegisterHandler,
|
||||
(EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD) SP805SetTimerPeriod,
|
||||
(EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD) SP805GetTimerPeriod
|
||||
};
|
||||
|
||||
/**
|
||||
Initialize the state information for the Watchdog Timer Architectural Protocol.
|
||||
|
||||
@param ImageHandle of the loaded driver
|
||||
@param SystemTable Pointer to the System Table
|
||||
|
||||
@retval EFI_SUCCESS Protocol registered
|
||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
||||
@retval EFI_DEVICE_ERROR Hardware problems
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SP805Initialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
// Unlock access to the SP805 registers
|
||||
SP805Unlock ();
|
||||
|
||||
// Stop the watchdog from triggering unexpectedly
|
||||
SP805Stop ();
|
||||
|
||||
// Set the watchdog to reset the board when triggered
|
||||
if ((MmioRead32(SP805_WDOG_CONTROL_REG) & SP805_WDOG_CTRL_RESEN) == 0) {
|
||||
MmioOr32 (SP805_WDOG_CONTROL_REG, SP805_WDOG_CTRL_RESEN);
|
||||
}
|
||||
|
||||
// Prohibit any rogue access to SP805 registers
|
||||
SP805Lock();
|
||||
|
||||
//
|
||||
// Make sure the Watchdog Timer Architectural Protocol has not been installed in the system yet.
|
||||
// This will avoid conflicts with the universal watchdog
|
||||
//
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid);
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
// Install the Timer Architectural Protocol onto a new handle
|
||||
Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEfiWatchdogTimerArchProtocolGuid, &gWatchdogTimer,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
EXIT:
|
||||
if(EFI_ERROR(Status)) {
|
||||
// The watchdog failed to initialize
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
@@ -1,52 +1,52 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SP805WatchdogDxe
|
||||
FILE_GUID = ebd705fb-fa92-46a7-b32b-7f566d944614
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = SP805Initialize
|
||||
|
||||
[Sources.common]
|
||||
SP805Watchdog.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[Pcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdSP805WatchdogBase
|
||||
gArmPlatformTokenSpaceGuid.PcdSP805WatchdogClockFrequencyInHz
|
||||
|
||||
[Protocols]
|
||||
gEfiWatchdogTimerArchProtocolGuid
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials
|
||||
* are licensed and made available under the terms and conditions of the BSD License
|
||||
* which accompanies this distribution. The full text of the license may be found at
|
||||
* http://opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
*
|
||||
**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SP805WatchdogDxe
|
||||
FILE_GUID = ebd705fb-fa92-46a7-b32b-7f566d944614
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = SP805Initialize
|
||||
|
||||
[Sources.common]
|
||||
SP805Watchdog.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[Pcd]
|
||||
gArmPlatformTokenSpaceGuid.PcdSP805WatchdogBase
|
||||
gArmPlatformTokenSpaceGuid.PcdSP805WatchdogClockFrequencyInHz
|
||||
|
||||
[Protocols]
|
||||
gEfiWatchdogTimerArchProtocolGuid
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
|
Reference in New Issue
Block a user