/** @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;
}