/** @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.<BR>
|
Copyright (c) 2018, Marvell International, Ltd. All rights reserved.<BR>
|
|
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;
|
}
|