Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame^] | 1 | /** @file
|
| 2 |
|
| 3 | Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
| 4 | Copyright (c) 2011, ARM Limited. All rights reserved.
|
| 5 |
|
| 6 | This program and the accompanying materials
|
| 7 | are licensed and made available under the terms and conditions of the BSD License
|
| 8 | which accompanies this distribution. The full text of the license may be found at
|
| 9 | http://opensource.org/licenses/bsd-license.php
|
| 10 |
|
| 11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 13 |
|
| 14 | **/
|
| 15 |
|
| 16 | #include "CpuDxe.h"
|
| 17 |
|
| 18 | #include <Guid/IdleLoopEvent.h>
|
| 19 |
|
| 20 | BOOLEAN mInterruptState = FALSE;
|
| 21 |
|
| 22 |
|
| 23 | /**
|
| 24 | This function flushes the range of addresses from Start to Start+Length
|
| 25 | from the processor's data cache. If Start is not aligned to a cache line
|
| 26 | boundary, then the bytes before Start to the preceding cache line boundary
|
| 27 | are also flushed. If Start+Length is not aligned to a cache line boundary,
|
| 28 | then the bytes past Start+Length to the end of the next cache line boundary
|
| 29 | are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
| 30 | supported. If the data cache is fully coherent with all DMA operations, then
|
| 31 | this function can just return EFI_SUCCESS. If the processor does not support
|
| 32 | flushing a range of the data cache, then the entire data cache can be flushed.
|
| 33 |
|
| 34 | @param This The EFI_CPU_ARCH_PROTOCOL instance.
|
| 35 | @param Start The beginning physical address to flush from the processor's data
|
| 36 | cache.
|
| 37 | @param Length The number of bytes to flush from the processor's data cache. This
|
| 38 | function may flush more bytes than Length specifies depending upon
|
| 39 | the granularity of the flush operation that the processor supports.
|
| 40 | @param FlushType Specifies the type of flush operation to perform.
|
| 41 |
|
| 42 | @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
| 43 | the processor's data cache.
|
| 44 | @retval EFI_UNSUPPORTEDT The processor does not support the cache flush type specified
|
| 45 | by FlushType.
|
| 46 | @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
| 47 | from the processor's data cache.
|
| 48 |
|
| 49 | **/
|
| 50 | EFI_STATUS
|
| 51 | EFIAPI
|
| 52 | CpuFlushCpuDataCache (
|
| 53 | IN EFI_CPU_ARCH_PROTOCOL *This,
|
| 54 | IN EFI_PHYSICAL_ADDRESS Start,
|
| 55 | IN UINT64 Length,
|
| 56 | IN EFI_CPU_FLUSH_TYPE FlushType
|
| 57 | )
|
| 58 | {
|
| 59 |
|
| 60 | switch (FlushType) {
|
| 61 | case EfiCpuFlushTypeWriteBack:
|
| 62 | WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
|
| 63 | break;
|
| 64 | case EfiCpuFlushTypeInvalidate:
|
| 65 | InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
|
| 66 | break;
|
| 67 | case EfiCpuFlushTypeWriteBackInvalidate:
|
| 68 | WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
|
| 69 | break;
|
| 70 | default:
|
| 71 | return EFI_INVALID_PARAMETER;
|
| 72 | }
|
| 73 |
|
| 74 | return EFI_SUCCESS;
|
| 75 | }
|
| 76 |
|
| 77 |
|
| 78 | /**
|
| 79 | This function enables interrupt processing by the processor.
|
| 80 |
|
| 81 | @param This The EFI_CPU_ARCH_PROTOCOL instance.
|
| 82 |
|
| 83 | @retval EFI_SUCCESS Interrupts are enabled on the processor.
|
| 84 | @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
|
| 85 |
|
| 86 | **/
|
| 87 | EFI_STATUS
|
| 88 | EFIAPI
|
| 89 | CpuEnableInterrupt (
|
| 90 | IN EFI_CPU_ARCH_PROTOCOL *This
|
| 91 | )
|
| 92 | {
|
| 93 | ArmEnableInterrupts ();
|
| 94 |
|
| 95 | mInterruptState = TRUE;
|
| 96 | return EFI_SUCCESS;
|
| 97 | }
|
| 98 |
|
| 99 |
|
| 100 | /**
|
| 101 | This function disables interrupt processing by the processor.
|
| 102 |
|
| 103 | @param This The EFI_CPU_ARCH_PROTOCOL instance.
|
| 104 |
|
| 105 | @retval EFI_SUCCESS Interrupts are disabled on the processor.
|
| 106 | @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
|
| 107 |
|
| 108 | **/
|
| 109 | EFI_STATUS
|
| 110 | EFIAPI
|
| 111 | CpuDisableInterrupt (
|
| 112 | IN EFI_CPU_ARCH_PROTOCOL *This
|
| 113 | )
|
| 114 | {
|
| 115 | ArmDisableInterrupts ();
|
| 116 |
|
| 117 | mInterruptState = FALSE;
|
| 118 | return EFI_SUCCESS;
|
| 119 | }
|
| 120 |
|
| 121 |
|
| 122 | /**
|
| 123 | This function retrieves the processor's current interrupt state a returns it in
|
| 124 | State. If interrupts are currently enabled, then TRUE is returned. If interrupts
|
| 125 | are currently disabled, then FALSE is returned.
|
| 126 |
|
| 127 | @param This The EFI_CPU_ARCH_PROTOCOL instance.
|
| 128 | @param State A pointer to the processor's current interrupt state. Set to TRUE if
|
| 129 | interrupts are enabled and FALSE if interrupts are disabled.
|
| 130 |
|
| 131 | @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
|
| 132 | @retval EFI_INVALID_PARAMETER State is NULL.
|
| 133 |
|
| 134 | **/
|
| 135 | EFI_STATUS
|
| 136 | EFIAPI
|
| 137 | CpuGetInterruptState (
|
| 138 | IN EFI_CPU_ARCH_PROTOCOL *This,
|
| 139 | OUT BOOLEAN *State
|
| 140 | )
|
| 141 | {
|
| 142 | if (State == NULL) {
|
| 143 | return EFI_INVALID_PARAMETER;
|
| 144 | }
|
| 145 |
|
| 146 | *State = mInterruptState;
|
| 147 | return EFI_SUCCESS;
|
| 148 | }
|
| 149 |
|
| 150 |
|
| 151 | /**
|
| 152 | This function generates an INIT on the processor. If this function succeeds, then the
|
| 153 | processor will be reset, and control will not be returned to the caller. If InitType is
|
| 154 | not supported by this processor, or the processor cannot programmatically generate an
|
| 155 | INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
|
| 156 | occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
|
| 157 |
|
| 158 | @param This The EFI_CPU_ARCH_PROTOCOL instance.
|
| 159 | @param InitType The type of processor INIT to perform.
|
| 160 |
|
| 161 | @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
|
| 162 | @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
|
| 163 | by this processor.
|
| 164 | @retval EFI_DEVICE_ERROR The processor INIT failed.
|
| 165 |
|
| 166 | **/
|
| 167 | EFI_STATUS
|
| 168 | EFIAPI
|
| 169 | CpuInit (
|
| 170 | IN EFI_CPU_ARCH_PROTOCOL *This,
|
| 171 | IN EFI_CPU_INIT_TYPE InitType
|
| 172 | )
|
| 173 | {
|
| 174 | return EFI_UNSUPPORTED;
|
| 175 | }
|
| 176 |
|
| 177 | EFI_STATUS
|
| 178 | EFIAPI
|
| 179 | CpuRegisterInterruptHandler (
|
| 180 | IN EFI_CPU_ARCH_PROTOCOL *This,
|
| 181 | IN EFI_EXCEPTION_TYPE InterruptType,
|
| 182 | IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
| 183 | )
|
| 184 | {
|
| 185 | return RegisterInterruptHandler (InterruptType, InterruptHandler);
|
| 186 | }
|
| 187 |
|
| 188 | EFI_STATUS
|
| 189 | EFIAPI
|
| 190 | CpuGetTimerValue (
|
| 191 | IN EFI_CPU_ARCH_PROTOCOL *This,
|
| 192 | IN UINT32 TimerIndex,
|
| 193 | OUT UINT64 *TimerValue,
|
| 194 | OUT UINT64 *TimerPeriod OPTIONAL
|
| 195 | )
|
| 196 | {
|
| 197 | return EFI_UNSUPPORTED;
|
| 198 | }
|
| 199 |
|
| 200 | /**
|
| 201 | Callback function for idle events.
|
| 202 |
|
| 203 | @param Event Event whose notification function is being invoked.
|
| 204 | @param Context The pointer to the notification function's context,
|
| 205 | which is implementation-dependent.
|
| 206 |
|
| 207 | **/
|
| 208 | VOID
|
| 209 | EFIAPI
|
| 210 | IdleLoopEventCallback (
|
| 211 | IN EFI_EVENT Event,
|
| 212 | IN VOID *Context
|
| 213 | )
|
| 214 | {
|
| 215 | CpuSleep ();
|
| 216 | }
|
| 217 |
|
| 218 | //
|
| 219 | // Globals used to initialize the protocol
|
| 220 | //
|
| 221 | EFI_HANDLE mCpuHandle = NULL;
|
| 222 | EFI_CPU_ARCH_PROTOCOL mCpu = {
|
| 223 | CpuFlushCpuDataCache,
|
| 224 | CpuEnableInterrupt,
|
| 225 | CpuDisableInterrupt,
|
| 226 | CpuGetInterruptState,
|
| 227 | CpuInit,
|
| 228 | CpuRegisterInterruptHandler,
|
| 229 | CpuGetTimerValue,
|
| 230 | CpuSetMemoryAttributes,
|
| 231 | 0, // NumberOfTimers
|
| 232 | 4, // DmaBufferAlignment
|
| 233 | };
|
| 234 |
|
| 235 | EFI_STATUS
|
| 236 | CpuDxeInitialize (
|
| 237 | IN EFI_HANDLE ImageHandle,
|
| 238 | IN EFI_SYSTEM_TABLE *SystemTable
|
| 239 | )
|
| 240 | {
|
| 241 | EFI_STATUS Status;
|
| 242 | EFI_EVENT IdleLoopEvent;
|
| 243 |
|
| 244 | InitializeExceptions (&mCpu);
|
| 245 |
|
| 246 | Status = gBS->InstallMultipleProtocolInterfaces (
|
| 247 | &mCpuHandle,
|
| 248 | &gEfiCpuArchProtocolGuid, &mCpu,
|
| 249 | &gVirtualUncachedPagesProtocolGuid, &gVirtualUncachedPages,
|
| 250 | NULL
|
| 251 | );
|
| 252 |
|
| 253 | //
|
| 254 | // Make sure GCD and MMU settings match. This API calls gDS->SetMemorySpaceAttributes ()
|
| 255 | // and that calls EFI_CPU_ARCH_PROTOCOL.SetMemoryAttributes, so this code needs to go
|
| 256 | // after the protocol is installed
|
| 257 | //
|
| 258 | SyncCacheConfig (&mCpu);
|
| 259 |
|
| 260 | // If the platform is a MPCore system then install the Configuration Table describing the
|
| 261 | // secondary core states
|
| 262 | if (ArmIsMpCore()) {
|
| 263 | PublishArmProcessorTable();
|
| 264 | }
|
| 265 |
|
| 266 | //
|
| 267 | // Setup a callback for idle events
|
| 268 | //
|
| 269 | Status = gBS->CreateEventEx (
|
| 270 | EVT_NOTIFY_SIGNAL,
|
| 271 | TPL_NOTIFY,
|
| 272 | IdleLoopEventCallback,
|
| 273 | NULL,
|
| 274 | &gIdleLoopEventGuid,
|
| 275 | &IdleLoopEvent
|
| 276 | );
|
| 277 | ASSERT_EFI_ERROR (Status);
|
| 278 |
|
| 279 | return Status;
|
| 280 | }
|