/** Detect board revision @return Board revision **/ BEAGLEBOARD_REVISION BeagleBoardGetRevision ( VOID ) { UINT32 OldPinDir; UINT32 Revision; // Read GPIO 171, 172, 173 OldPinDir = MmioRead32 (GPIO6_BASE + GPIO_OE); MmioWrite32(GPIO6_BASE + GPIO_OE, (OldPinDir | BIT11 | BIT12 | BIT13)); Revision = MmioRead32 (GPIO6_BASE + GPIO_DATAIN); // Restore I/O settings MmioWrite32 (GPIO6_BASE + GPIO_OE, OldPinDir); return (BEAGLEBOARD_REVISION)((Revision >> 11) & 0x7); }
VOID EFIAPI ArmGicEnableDistributor ( IN INTN GicDistributorBase ) { // Turn on the GIC distributor MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1); }
RETURN_STATUS AccessSysCfgRegister ( IN UINT32 ReadWrite, IN UINT32 Function, IN UINT32 Site, IN UINT32 Position, IN UINT32 Device, IN OUT UINT32* Data ) { UINT32 SysCfgCtrl; if (EfiAtRuntime ()) { return RETURN_UNSUPPORTED; } // Clear the COMPLETE bit MmioAnd32(ARM_VE_SYS_CFGSTAT_REG, ~SYS_CFGSTAT_COMPLETE); // If writing, then set the data value if(ReadWrite == SYS_CFGCTRL_WRITE) { MmioWrite32(ARM_VE_SYS_CFGDATA_REG, *Data); } // Set the control value SysCfgCtrl = SYS_CFGCTRL_START | ReadWrite | SYS_CFGCTRL_FUNCTION(Function) | SYS_CFGCTRL_SITE(Site) | SYS_CFGCTRL_POSITION(Position) | SYS_CFGCTRL_DEVICE(Device); MmioWrite32(ARM_VE_SYS_CFGCTRL_REG, SysCfgCtrl); // Wait until the COMPLETE bit is set while ((MmioRead32(ARM_VE_SYS_CFGSTAT_REG) & SYS_CFGSTAT_COMPLETE) == 0); // Check for errors if(MmioRead32(ARM_VE_SYS_CFGSTAT_REG) & SYS_CFGSTAT_ERROR) { return RETURN_DEVICE_ERROR; } // If reading then get the data value if(ReadWrite == SYS_CFGCTRL_READ) { *Data = MmioRead32(ARM_VE_SYS_CFGDATA_REG); } return RETURN_SUCCESS; }
EFI_STATUS EFIAPI BootLinuxConfig ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { DEBUG((EFI_D_ERROR,"SMMU CONFIG.........")); SmmuConfigForLinux(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"ITS CONFIG.........")); ITSCONFIG(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"AP CONFIG.........")); MmioWrite64(FixedPcdGet64(PcdMailBoxAddress), 0x0); (void)WriteBackInvalidateDataCacheRange((VOID *) FixedPcdGet64(PcdMailBoxAddress), 8); asm("DSB SY"); asm("ISB"); CoreSelectBoot(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"MN CONFIG.........")); MN_CONFIG (); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"RTC CONFIG.........")); MmioWrite32(0xA00021F0, 0xF); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"Tsensor CONFIG.........")); MmioWrite32(0x80010000 + 0x5000, 0x1); *(volatile UINT32*)0xA0000A8C = 0x1f; DEBUG((EFI_D_ERROR,"Done\n")); return EFI_SUCCESS; }
STATIC EFI_STATUS NorFlashWriteSingleWord ( IN NOR_FLASH_INSTANCE *Instance, IN UINTN WordAddress, IN UINT32 WriteData ) { EFI_STATUS Status; UINT32 StatusRegister; Status = EFI_SUCCESS; // Request a write single word command SEND_NOR_COMMAND(WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP); // Store the word into NOR Flash; MmioWrite32 (WordAddress, WriteData); // Wait for the write to complete and then check for any errors; i.e. check the Status Register do { // Prepare to read the status register StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress); // The chip is busy while the WRITE bit is not asserted } while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE); // Perform a full status check: // Mask the relevant bits of Status Register. // Everything should be zero, if not, we have a problem if (StatusRegister & P30_SR_BIT_VPP) { DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n",WordAddress)); Status = EFI_DEVICE_ERROR; } if (StatusRegister & P30_SR_BIT_PROGRAM) { DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n",WordAddress)); Status = EFI_DEVICE_ERROR; } if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n",WordAddress)); Status = EFI_DEVICE_ERROR; } if (!EFI_ERROR(Status)) { // Clear the Status Register SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER); } // Put device back into Read Array mode SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); return Status; }
/** 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. **/ STATIC EFI_STATUS EFIAPI SP805SetTimerPeriod ( IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, IN UINT64 TimerPeriod // In 100ns units ) { EFI_STATUS Status; UINT64 Ticks64bit; SP805Unlock (); Status = EFI_SUCCESS; if (TimerPeriod == 0) { // This is a watchdog stop request SP805Stop (); } else { // Calculate the Watchdog ticks required for a delay of (TimerTicks * 100) nanoseconds // The SP805 will count down to zero and generate an interrupt. // // WatchdogTicks = ((TimerPeriod * 100 * SP805_CLOCK_FREQUENCY) / 1GHz); // // i.e.: // // WatchdogTicks = (TimerPeriod * SP805_CLOCK_FREQUENCY) / 10 MHz ; Ticks64bit = MultU64x32 (TimerPeriod, PcdGet32 (PcdSP805WatchdogClockFrequencyInHz)); Ticks64bit = DivU64x32 (Ticks64bit, 10 * 1000 * 1000); // The registers in the SP805 are only 32 bits if (Ticks64bit > MAX_UINT32) { // 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 (); } mTimerPeriod = TimerPeriod; EXIT: // Ensure the watchdog is locked before exiting. SP805Lock (); ASSERT_EFI_ERROR (Status); return Status; }
/** Writes a 32-bit PCI configuration register. Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. Value is returned. This function must guarantee that all PCI read and write operations are serialized. If Address > 0x0FFFFFFF, then ASSERT(). If Address is not aligned on a 32-bit boundary, then ASSERT(). @param Address Address that encodes the PCI Bus, Device, Function and Register. @param Value The value to write. @return The value written to the PCI configuration register. **/ UINT32 EFIAPI PciExpressWrite32 ( IN UINTN Address, IN UINT32 Value ) { ASSERT_INVALID_PCI_ADDRESS (Address); return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value); }
EFI_STATUS OhciSetOperationalReg ( USB_OHCI_HC_DEV *Ohc, IN UINT32 Offset, IN UINT32 *Value ) { MmioWrite32(Ohc->UsbHostControllerBaseAddress + Offset, *Value); return EFI_SUCCESS; }
/** 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. **/ STATIC VOID SP805Unlock ( VOID ) { if (MmioRead32 (SP805_WDOG_LOCK_REG) == SP805_WDOG_LOCK_IS_LOCKED) { MmioWrite32 (SP805_WDOG_LOCK_REG, SP805_WDOG_SPECIAL_UNLOCK_CODE); } }
/* * This function configures the all interrupts to be Non-secure. * */ VOID EFIAPI ArmGicSetupNonSecure ( IN UINTN MpId, IN INTN GicDistributorBase, IN INTN GicInterruptInterfaceBase ) { UINTN InterruptId; UINTN CachedPriorityMask; UINTN Index; CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR); // Set priority Mask so that no interrupts get through to CPU MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0); InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); // Only try to clear valid interrupts. Ignore spurious interrupts. while ((InterruptId & 0x3FF) < ArmGicGetMaxNumInterrupts (GicDistributorBase)) { // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, InterruptId); // Next InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); } // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt). if (ArmPlatformIsPrimaryCore (MpId)) { // Ensure all GIC interrupts are Non-Secure for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff); } } else { // The secondary cores only set the Non Secure bit to their banked PPIs MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff); } // Ensure all interrupts can get through the priority mask MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask); }
EFI_STATUS Set ( IN EMBEDDED_GPIO *This, IN EMBEDDED_GPIO_PIN Gpio, IN EMBEDDED_GPIO_MODE Mode ) { UINTN Port; UINTN Pin; UINT32 OutputEnableRegister; UINT32 SetDataOutRegister; UINT32 ClearDataOutRegister; Port = GPIO_PORT(Gpio); Pin = GPIO_PIN(Gpio); OutputEnableRegister = GpioBase(Port) + GPIO_OE; SetDataOutRegister = GpioBase(Port) + GPIO_SETDATAOUT; ClearDataOutRegister = GpioBase(Port) + GPIO_CLEARDATAOUT; switch (Mode) { case GPIO_MODE_INPUT: MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_INPUT(Pin)); break; case GPIO_MODE_OUTPUT_0: MmioWrite32 (ClearDataOutRegister, GPIO_CLEARDATAOUT_BIT(Pin)); MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_OUTPUT(Pin)); break; case GPIO_MODE_OUTPUT_1: MmioWrite32 (SetDataOutRegister, GPIO_SETDATAOUT_BIT(Pin)); MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_OUTPUT(Pin)); break; default: return EFI_UNSUPPORTED; } return EFI_SUCCESS; }
/** Shutdown our hardware DXE Core will disable interrupts and turn off the timer and disable interrupts after all the event handlers have run. @param[in] Event The Event that is being processed @param[in] Context Event Context **/ STATIC VOID EFIAPI ExitBootServicesEvent ( IN EFI_EVENT Event, IN VOID *Context ) { // Disable all interrupts MmioWrite32 (RegBase + BCM2836_INTC_TIMER_CONTROL_OFFSET, 0); }
/** Write a 32-bit I/O APIC register. If Index is >= 0x100, then ASSERT(). @param Index Specifies the I/O APIC register to write. @param Value Specifies the value to write to the I/O APIC register specified by Index. @return The 32-bit value written to I/O APIC register specified by Index. **/ UINT32 EFIAPI IoApicWrite ( IN UINTN Index, IN UINT32 Value ) { ASSERT (Index < 0x100); MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index); return MmioWrite32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET, Value); }
/** 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. **/ STATIC 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); } }
VOID EFIAPI ArmGicSendSgiTo ( IN INTN GicDistributorBase, IN INTN TargetListFilter, IN INTN CPUTargetList, IN INTN SgiId ) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId); }
/** Signal to the hardware that the End Of Intrrupt state has been reached. @param This Instance pointer for this protocol @param Source Hardware source of the interrupt @retval EFI_SUCCESS Source interrupt EOI'ed. @retval EFI_DEVICE_ERROR Hardware could not be programmed. **/ EFI_STATUS EFIAPI EndOfInterrupt ( IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, IN HARDWARE_INTERRUPT_SOURCE Source ) { MmioWrite32 (INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR); ArmDataSyncronizationBarrier (); return EFI_SUCCESS; }
/** 32-bit memory write operations. @param[in] PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param[in] This Pointer to local data for the interface. @param[in] Address The physical address of the access. @param[in] Data The data to write. **/ VOID EFIAPI CpuMemWrite32 ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_CPU_IO_PPI *This, IN UINT64 Address, IN UINT32 Data ) { MmioWrite32 ((UINTN)Address, Data); }
/* * This function configures the all interrupts to be Non-secure. * */ VOID EFIAPI ArmGicSetupNonSecure ( IN UINTN MpId, IN INTN GicDistributorBase, IN INTN GicInterruptInterfaceBase ) { UINTN InterruptId; UINTN CachedPriorityMask; UINTN Index; CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR); // Set priority Mask so that no interrupts get through to CPU MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0); // Check if there are any pending interrupts //TODO: could be extended to take Peripheral interrupts into consideration, but at the moment only SGI's are taken into consideration. while(0 != (MmioRead32 (GicDistributorBase + ARM_GIC_ICDICPR) & 0xF)) { // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR); // Write to End of interrupt signal MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, InterruptId); } // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt). if (IS_PRIMARY_CORE(MpId)) { // Ensure all GIC interrupts are Non-Secure for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff); } } else { // The secondary cores only set the Non Secure bit to their banked PPIs MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff); } // Ensure all interrupts can get through the priority mask MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask); }
UINT32 DetermineCompatibleBoard ( void ) { UINTN PciD31F0RegBase = 0; UINT32 GpioValue = 0; UINT32 TmpVal = 0; UINT32 MmioConf0 = 0; UINT32 MmioPadval = 0; UINT32 PConf0Offset = 0x200; //GPIO_S5_4 pad_conf0 register offset UINT32 PValueOffset = 0x208; //GPIO_S5_4 pad_value register offset UINT32 SSUSOffset = 0x2000; UINT32 IoBase = 0; DEBUG ((EFI_D_ERROR, "DetermineCompatibleBoard() Entry\n")); PciD31F0RegBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_PCH_LPC, PCI_FUNCTION_NUMBER_PCH_LPC, 0 ); IoBase = MmioRead32 (PciD31F0RegBase + R_PCH_LPC_IO_BASE) & B_PCH_LPC_IO_BASE_BAR; MmioConf0 = IoBase + SSUSOffset + PConf0Offset; MmioPadval = IoBase + SSUSOffset + PValueOffset; //0xFED0E200/0xFED0E208 is pad_Conf/pad_val register address of GPIO_S5_4 DEBUG ((EFI_D_ERROR, "MmioConf0[0x%x], MmioPadval[0x%x]\n", MmioConf0, MmioPadval)); MmioWrite32 (MmioConf0, 0x2003CC00); TmpVal = MmioRead32 (MmioPadval); TmpVal &= ~0x6; //Clear bit 1:2 TmpVal |= 0x2; // Set the pin as GPI MmioWrite32 (MmioPadval, TmpVal); GpioValue = MmioRead32 (MmioPadval); DEBUG ((EFI_D_ERROR, "Gpio_S5_4 value is 0x%x\n", GpioValue)); return (GpioValue & 0x1); }
/** 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; }
VOID EFIAPI ArmGicDisableInterruptInterface ( IN INTN GicInterruptInterfaceBase ) { UINT32 ControlValue; // Disable CPU interface in Secure world and Non-secure World ControlValue = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR); MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, ControlValue & ~(ARM_GIC_ICCICR_ENABLE_SECURE | ARM_GIC_ICCICR_ENABLE_NS)); }
/** Write to a local APIC register. This function writes to a local APIC register either in xAPIC or x2APIC mode. It is required that in xAPIC mode wider registers (64-bit or 256-bit) must be accessed using multiple 32-bit loads or stores, so this function only performs 32-bit write. if the register index is invalid or unsupported in current APIC mode, then ASSERT. @param MmioOffset The MMIO offset of the local APIC register in xAPIC mode. It must be 16-byte aligned. @param Value Value to be written to the register. **/ VOID EFIAPI WriteLocalApicReg ( IN UINTN MmioOffset, IN UINT32 Value ) { ASSERT ((MmioOffset & 0xf) == 0); ASSERT (GetApicMode () == LOCAL_APIC_MODE_XAPIC); MmioWrite32 (PcdGet32 (PcdCpuLocalApicBaseAddress) + MmioOffset, Value); }
VOID TimerInit ( VOID ) { UINTN Timer = FixedPcdGet32(PcdOmap35xxFreeTimer); UINT32 TimerBaseAddress = TimerBase(Timer); // Set source clock for GPT3 & GPT4 to SYS_CLK MmioOr32 (CM_CLKSEL_PER, CM_CLKSEL_PER_CLKSEL_GPT3_SYS | CM_CLKSEL_PER_CLKSEL_GPT4_SYS); // Set count & reload registers MmioWrite32 (TimerBaseAddress + GPTIMER_TCRR, 0x00000000); MmioWrite32 (TimerBaseAddress + GPTIMER_TLDR, 0x00000000); // Disable interrupts MmioWrite32 (TimerBaseAddress + GPTIMER_TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_DISABLE | TIER_MAT_IT_DISABLE); // Start Timer MmioWrite32 (TimerBaseAddress + GPTIMER_TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); //Disable OMAP Watchdog timer (WDT2) MmioWrite32 (WDTIMER2_BASE + WSPR, 0xAAAA); DEBUG ((EFI_D_ERROR, "Magic delay to disable watchdog timers properly.\n")); MmioWrite32 (WDTIMER2_BASE + WSPR, 0x5555); }
/** 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 TimerCount; INT32 LoadValue; if (TimerPeriod == 0) { // Turn off GPTIMER3 MmioWrite32 (TCLR, TCLR_ST_OFF); Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector); } else { // Calculate required timer count TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedPerformanceCounterPeriodInNanoseconds)); // Set GPTIMER3 Load register LoadValue = (INT32) -TimerCount; MmioWrite32 (TLDR, LoadValue); MmioWrite32 (TCRR, LoadValue); // Enable Overflow interrupt MmioWrite32 (TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE); // Turn on GPTIMER3, it will reload at overflow MmioWrite32 (TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector); } // // Save the new timer period // mTimerPeriod = TimerPeriod; return Status; }
/** Write the data to the EHCI operation register. @param Ehc The EHCI device. @param Offset EHCI operation register offset. @param Data The data to write. **/ VOID EhcWriteOpReg ( IN PEI_USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Data ) { ASSERT (Ehc->CapLen != 0); MmioWrite32(Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset, Data); }
VOID DisableInterruptSource ( VOID ) { UINTN Bank; UINTN Bit; Bank = gVector / 32; Bit = 1UL << (gVector % 32); MmioWrite32 (INTCPS_MIR_SET(Bank), Bit); }
/** Set PTP interface type. @param[in] Register Pointer to PTP register. @param[in] PtpInterface PTP interface type. @retval EFI_SUCCESS PTP interface type is set. @retval EFI_INVALID_PARAMETER PTP interface type is invalid. @retval EFI_UNSUPPORTED PTP interface type is unsupported. @retval EFI_WRITE_PROTECTED PTP interface is locked. **/ EFI_STATUS SetPtpInterface ( IN VOID *Register, IN UINT8 PtpInterface ) { UINT8 PtpInterfaceCurrent; PTP_CRB_INTERFACE_IDENTIFIER InterfaceId; PtpInterfaceCurrent = GetPtpInterface (Register); if ((PtpInterfaceCurrent != TPM_DEVICE_INTERFACE_PTP_FIFO) && (PtpInterfaceCurrent != TPM_DEVICE_INTERFACE_PTP_CRB)) { return EFI_UNSUPPORTED; } InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId); if (InterfaceId.Bits.IntfSelLock != 0) { return EFI_WRITE_PROTECTED; } switch (PtpInterface) { case TPM_DEVICE_INTERFACE_PTP_FIFO: if (InterfaceId.Bits.CapFIFO == 0) { return EFI_UNSUPPORTED; } InterfaceId.Bits.InterfaceSelector = PTP_INTERFACE_IDENTIFIER_INTERFACE_SELECTOR_FIFO; MmioWrite32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId, InterfaceId.Uint32); return EFI_SUCCESS; case TPM_DEVICE_INTERFACE_PTP_CRB: if (InterfaceId.Bits.CapCRB == 0) { return EFI_UNSUPPORTED; } InterfaceId.Bits.InterfaceSelector = PTP_INTERFACE_IDENTIFIER_INTERFACE_SELECTOR_CRB; MmioWrite32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId, InterfaceId.Uint32); return EFI_SUCCESS; default: return EFI_INVALID_PARAMETER; } }
/** Sets the system wakeup alarm clock time. @param Enabled Enable or disable the wakeup alarm. @param Time If Enable is TRUE, the time to set the wakeup alarm for. @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If Enable is FALSE, then the wakeup alarm was disabled. @retval EFI_INVALID_PARAMETER A time field is out of range. @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. **/ EFI_STATUS EFIAPI LibSetWakeupTime ( IN BOOLEAN Enabled, OUT EFI_TIME *Time ) { UINT32 WakeupSeconds; // Convert time to raw seconds WakeupSeconds = EfiTimeToEpoch (Time); // Issue delayed write to alarm register RtcDelayedWrite (RTC_ALARM_2_REG, WakeupSeconds); if (Enabled) { MmioWrite32 (mArmadaRtcBase + RTC_IRQ_2_CONFIG_REG, RTC_IRQ_ALARM_EN); } else { MmioWrite32 (mArmadaRtcBase + RTC_IRQ_2_CONFIG_REG, 0); } return EFI_SUCCESS; }
VOID EFIAPI ArmGicEnableDistributor ( IN INTN GicDistributorBase ) { ARM_GIC_ARCH_REVISION Revision; /* * Enable GIC distributor in Non-Secure world. * Note: The ICDDCR register is banked when Security extensions are implemented */ Revision = ArmGicGetSupportedArchRevision (); if (Revision == ARM_GIC_ARCH_REVISION_2) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1); } else { if (MmioRead32 (GicDistributorBase + ARM_GIC_ICDDCR) & ARM_GIC_ICDDCR_ARE) { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x2); } else { MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1); } } }
STATIC VOID InitializeSataPorts ( EFI_PHYSICAL_ADDRESS AhciBaseAddr, UINTN PortCount ) { INTN PortNum; BOOLEAN IsCpd; BOOLEAN IsMpsp; UINT32 PortRegAddr; UINT32 RegVal; // Set Ports Implemented (PI) MmioWrite32 (AhciBaseAddr + EFI_AHCI_PI_OFFSET, (1 << PortCount) - 1); IsCpd = FixedPcdGetBool (PcdSataPortCpd); IsMpsp = FixedPcdGetBool (PcdSataPortMpsp); if (!IsCpd && !IsMpsp) { return; } for (PortNum = 0; PortNum < PortCount; PortNum++) { PortRegAddr = EFI_AHCI_PORT_OFFSET (PortNum) + EFI_AHCI_PORT_CMD; RegVal = MmioRead32(AhciBaseAddr + PortRegAddr); if (IsCpd) RegVal |= EFI_AHCI_PORT_CMD_CPD; else RegVal &= ~EFI_AHCI_PORT_CMD_CPD; if (IsMpsp) RegVal |= EFI_AHCI_PORT_CMD_MPSP; else RegVal &= ~EFI_AHCI_PORT_CMD_MPSP; RegVal |= EFI_AHCI_PORT_CMD_HPCP; MmioWrite32(AhciBaseAddr + PortRegAddr, RegVal); } }