/** @file This driver is used to manage SD/MMC PCI host controllers which are compliance with SD Host Controller Simplified Specification version 3.00. It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use. Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
Copyright (c) 2018, Marvell International, Ltd. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "XenonSdMmcOverride.h" /** Read/Write specified SD/MMC host controller mmio register. @param[in] PciIo The PCI IO protocol instance. @param[in] BarIndex The BAR index of the standard PCI Configuration header to use as the base address for the memory operation to perform. @param[in] Offset The offset within the selected BAR to start the memory operation. @param[in] Read A boolean to indicate it's read or write operation. @param[in] Count The width of the mmio register in bytes. Must be 1, 2 , 4 or 8 bytes. @param[in, out] Data For read operations, the destination buffer to store the results. For write operations, the source buffer to write data from. The caller is responsible for having ownership of the data buffer and ensuring its size not less than Count bytes. @retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Count is not valid. @retval EFI_SUCCESS The read/write operation succeeds. @retval Others The read/write operation fails. **/ EFI_STATUS EFIAPI XenonHcRwMmio ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 BarIndex, IN UINT32 Offset, IN BOOLEAN Read, IN UINT8 Count, IN OUT VOID *Data ) { EFI_STATUS Status; if ((PciIo == NULL) || (Data == NULL)) { return EFI_INVALID_PARAMETER; } if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) { return EFI_INVALID_PARAMETER; } if (Read) { Status = PciIo->Mem.Read ( PciIo, EfiPciIoWidthUint8, BarIndex, (UINT64) Offset, Count, Data ); } else { Status = PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint8, BarIndex, (UINT64) Offset, Count, Data ); } return Status; } /** Do OR operation with the value of the specified SD/MMC host controller mmio register. @param[in] PciIo The PCI IO protocol instance. @param[in] BarIndex The BAR index of the standard PCI Configuration header to use as the base address for the memory operation to perform. @param[in] Offset The offset within the selected BAR to start the memory operation. @param[in] Count The width of the mmio register in bytes. Must be 1, 2 , 4 or 8 bytes. @param[in] OrData The pointer to the data used to do OR operation. The caller is responsible for having ownership of the data buffer and ensuring its size not less than Count bytes. @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the Count is not valid. @retval EFI_SUCCESS The OR operation succeeds. @retval Others The OR operation fails. **/ EFI_STATUS EFIAPI XenonHcOrMmio ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 BarIndex, IN UINT32 Offset, IN UINT8 Count, IN VOID *OrData ) { EFI_STATUS Status; UINT64 Data; UINT64 Or; Status = XenonHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data); if (EFI_ERROR (Status)) { return Status; } if (Count == 1) { Or = *(UINT8*) OrData; } else if (Count == 2) { Or = *(UINT16*) OrData; } else if (Count == 4) { Or = *(UINT32*) OrData; } else if (Count == 8) { Or = *(UINT64*) OrData; } else { return EFI_INVALID_PARAMETER; } Data |= Or; Status = XenonHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data); return Status; } /** Do AND operation with the value of the specified SD/MMC host controller mmio register. @param[in] PciIo The PCI IO protocol instance. @param[in] BarIndex The BAR index of the standard PCI Configuration header to use as the base address for the memory operation to perform. @param[in] Offset The offset within the selected BAR to start the memory operation. @param[in] Count The width of the mmio register in bytes. Must be 1, 2 , 4 or 8 bytes. @param[in] AndData The pointer to the data used to do AND operation. The caller is responsible for having ownership of the data buffer and ensuring its size not less than Count bytes. @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the Count is not valid. @retval EFI_SUCCESS The AND operation succeeds. @retval Others The AND operation fails. **/ EFI_STATUS EFIAPI XenonHcAndMmio ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 BarIndex, IN UINT32 Offset, IN UINT8 Count, IN VOID *AndData ) { EFI_STATUS Status; UINT64 Data; UINT64 And; Status = XenonHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data); if (EFI_ERROR (Status)) { return Status; } if (Count == 1) { And = *(UINT8*) AndData; } else if (Count == 2) { And = *(UINT16*) AndData; } else if (Count == 4) { And = *(UINT32*) AndData; } else if (Count == 8) { And = *(UINT64*) AndData; } else { return EFI_INVALID_PARAMETER; } Data &= And; Status = XenonHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data); return Status; } /** Wait for the value of the specified MMIO register set to the test value. @param[in] PciIo The PCI IO protocol instance. @param[in] BarIndex The BAR index of the standard PCI Configuration header to use as the base address for the memory operation to perform. @param[in] Offset The offset within the selected BAR to start the memory operation. @param[in] Count The width of the mmio register in bytes. Must be 1, 2, 4 or 8 bytes. @param[in] MaskValue The mask value of memory. @param[in] TestValue The test value of memory. @retval EFI_NOT_READY The MMIO register hasn't set to the expected value. @retval EFI_SUCCESS The MMIO register has expected value. @retval Others The MMIO operation fails. **/ EFI_STATUS EFIAPI XenonHcCheckMmioSet ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 BarIndex, IN UINT32 Offset, IN UINT8 Count, IN UINT64 MaskValue, IN UINT64 TestValue ) { EFI_STATUS Status; UINT64 Value; // // Access PCI MMIO space to see if the value is the tested one. // Value = 0; Status = XenonHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Value); if (EFI_ERROR (Status)) { return Status; } Value &= MaskValue; if (Value == TestValue) { return EFI_SUCCESS; } return EFI_NOT_READY; } /** Wait for the value of the specified MMIO register set to the test value. @param[in] PciIo The PCI IO protocol instance. @param[in] BarIndex The BAR index of the standard PCI Configuration header to use as the base address for the memory operation to perform. @param[in] Offset The offset within the selected BAR to start the memory operation. @param[in] Count The width of the mmio register in bytes. Must be 1, 2, 4 or 8 bytes. @param[in] MaskValue The mask value of memory. @param[in] TestValue The test value of memory. @param[in] Timeout The time out value for wait memory set, uses 1 microsecond as a unit. @retval EFI_TIMEOUT The MMIO register hasn't expected value in timeout range. @retval EFI_SUCCESS The MMIO register has expected value. @retval Others The MMIO operation fails. **/ EFI_STATUS EFIAPI XenonHcWaitMmioSet ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 BarIndex, IN UINT32 Offset, IN UINT8 Count, IN UINT64 MaskValue, IN UINT64 TestValue, IN UINT64 Timeout ) { EFI_STATUS Status; BOOLEAN InfiniteWait; if (Timeout == 0) { InfiniteWait = TRUE; } else { InfiniteWait = FALSE; } while (InfiniteWait || (Timeout > 0)) { Status = XenonHcCheckMmioSet ( PciIo, BarIndex, Offset, Count, MaskValue, TestValue ); if (Status != EFI_NOT_READY) { return Status; } // // Stall for 1 microsecond. // gBS->Stall (1); Timeout--; } return EFI_TIMEOUT; }