MdeModulePkg/Ufs: Refine EDKII_UFS_HOST_CONTROLLER_PROTOCOL interface

The EDKII_UFS_HOST_CONTROLLER_PROTOCOL is refined to provide
interfaces accessing UFS host controller MMIO register.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17533 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Feng Tian 2015-05-28 07:42:05 +00:00 committed by erictian
parent 500e2ac246
commit 095f077993
6 changed files with 474 additions and 136 deletions

View File

@ -2,7 +2,7 @@
UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller
MMIO base, to upper layer UFS drivers. MMIO base, to upper layer UFS drivers.
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -39,9 +39,12 @@ UFS_HOST_CONTROLLER_PRIVATE_DATA gUfsHcTemplate = {
UfsHcFreeBuffer, UfsHcFreeBuffer,
UfsHcMap, UfsHcMap,
UfsHcUnmap, UfsHcUnmap,
UfsHcFlush UfsHcFlush,
UfsHcMmioRead,
UfsHcMmioWrite
}, },
NULL, // PciIo NULL, // PciIo
0, // BarIndex
0 // PciAttributes 0 // PciAttributes
}; };
@ -64,25 +67,32 @@ UfsHcGetMmioBar (
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status; EFI_STATUS Status;
UINT8 BarIndex;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
if ((This == NULL) || (MmioBar == NULL)) { if ((This == NULL) || (MmioBar == NULL)) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); BarDesc = NULL;
PciIo = Private->PciIo; Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
PciIo = Private->PciIo;
BarIndex = Private->BarIndex;
Status = PciIo->Pci.Read ( Status = PciIo->GetBarAttributes (
PciIo, PciIo,
EfiPciIoWidthUint8, BarIndex,
PCI_BASE_ADDRESSREG_OFFSET, NULL,
sizeof (UINT32), (VOID**) &BarDesc
MmioBar );
); if (EFI_ERROR (Status)) {
return Status;
if (!EFI_ERROR (Status)) {
*MmioBar &= (UINTN)~0xF;
} }
*MmioBar = (UINTN)BarDesc->AddrRangeMin;
FreePool (BarDesc);
return Status; return Status;
} }
@ -272,6 +282,90 @@ UfsHcFlush (
return Status; return Status;
} }
/**
Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
@param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
@param Width Signifies the width of the memory operations.
@param Offset The offset within the UFS Host Controller MMIO space to start the
memory operation.
@param Count The number of memory operations to perform.
@param Buffer For read operations, the destination buffer to store the results.
For write operations, the source buffer to write data from.
@retval EFI_SUCCESS The data was read from or written to the UFS host controller.
@retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
valid for the UFS Host Controller memory space.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
UfsHcMmioRead (
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,
IN UINT64 Offset,
IN UINTN Count,
IN OUT VOID *Buffer
)
{
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
UINT8 BarIndex;
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
PciIo = Private->PciIo;
BarIndex = Private->BarIndex;
Status = PciIo->Mem.Read (PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)Width, BarIndex, Offset, Count, Buffer);
return Status;
}
/**
Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
@param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
@param Width Signifies the width of the memory operations.
@param Offset The offset within the UFS Host Controller MMIO space to start the
memory operation.
@param Count The number of memory operations to perform.
@param Buffer For read operations, the destination buffer to store the results.
For write operations, the source buffer to write data from.
@retval EFI_SUCCESS The data was read from or written to the UFS host controller.
@retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
valid for the UFS Host Controller memory space.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
UfsHcMmioWrite (
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,
IN UINT64 Offset,
IN UINTN Count,
IN OUT VOID *Buffer
)
{
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_STATUS Status;
UINT8 BarIndex;
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
PciIo = Private->PciIo;
BarIndex = Private->BarIndex;
Status = PciIo->Mem.Write (PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)Width, BarIndex, Offset, Count, Buffer);
return Status;
}
/** /**
Tests to see if this driver supports a given controller. If a child device is provided, Tests to see if this driver supports a given controller. If a child device is provided,
it further tests to see if this driver supports creating a handle for the specified child device. it further tests to see if this driver supports creating a handle for the specified child device.
@ -468,10 +562,13 @@ UfsHcDriverBindingStart (
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
UINT64 Supports; UINT64 Supports;
UINT8 BarIndex;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
PciIo = NULL; PciIo = NULL;
Private = NULL; Private = NULL;
Supports = 0; Supports = 0;
BarDesc = NULL;
// //
// Now test and open the EfiPciIoProtocol // Now test and open the EfiPciIoProtocol
@ -507,6 +604,28 @@ UfsHcDriverBindingStart (
Private->PciIo = PciIo; Private->PciIo = PciIo;
for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
Status = PciIo->GetBarAttributes (
PciIo,
BarIndex,
NULL,
(VOID**) &BarDesc
);
if (Status == EFI_UNSUPPORTED) {
continue;
} else if (EFI_ERROR (Status)) {
goto Done;
}
if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
Private->BarIndex = BarIndex;
FreePool (BarDesc);
break;
}
FreePool (BarDesc);
}
Status = PciIo->Attributes ( Status = PciIo->Attributes (
PciIo, PciIo,
EfiPciIoAttributeOperationGet, EfiPciIoAttributeOperationGet,

View File

@ -2,7 +2,7 @@
UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller
MMIO base, to upper layer UFS drivers. MMIO base, to upper layer UFS drivers.
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -19,6 +19,7 @@
#include <Uefi.h> #include <Uefi.h>
#include <IndustryStandard/Pci.h> #include <IndustryStandard/Pci.h>
#include <IndustryStandard/Acpi.h>
#include <Protocol/ComponentName.h> #include <Protocol/ComponentName.h>
#include <Protocol/ComponentName2.h> #include <Protocol/ComponentName2.h>
@ -56,6 +57,7 @@ struct _UFS_HOST_CONTROLLER_PRIVATE_DATA {
EDKII_UFS_HOST_CONTROLLER_PROTOCOL UfsHc; EDKII_UFS_HOST_CONTROLLER_PROTOCOL UfsHc;
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 BarIndex;
UINT64 PciAttributes; UINT64 PciAttributes;
}; };
@ -450,4 +452,60 @@ UfsHcFlush (
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
); );
/**
Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
@param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
@param Width Signifies the width of the memory operations.
@param Offset The offset within the UFS Host Controller MMIO space to start the
memory operation.
@param Count The number of memory operations to perform.
@param Buffer For read operations, the destination buffer to store the results.
For write operations, the source buffer to write data from.
@retval EFI_SUCCESS The data was read from or written to the UFS host controller.
@retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
valid for the UFS Host Controller memory space.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
UfsHcMmioRead (
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,
IN UINT64 Offset,
IN UINTN Count,
IN OUT VOID *Buffer
);
/**
Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
@param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
@param Width Signifies the width of the memory operations.
@param Offset The offset within the UFS Host Controller MMIO space to start the
memory operation.
@param Count The number of memory operations to perform.
@param Buffer For read operations, the destination buffer to store the results.
For write operations, the source buffer to write data from.
@retval EFI_SUCCESS The data was read from or written to the UFS host controller.
@retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
valid for the UFS Host Controller memory space.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
EFI_STATUS
EFIAPI
UfsHcMmioWrite (
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,
IN UINT64 Offset,
IN UINTN Count,
IN OUT VOID *Buffer
);
#endif #endif

View File

@ -1,6 +1,6 @@
/** @file /** @file
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -27,7 +27,6 @@
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include <Library/DevicePathLib.h> #include <Library/DevicePathLib.h>
#include <Library/IoLib.h>
#include <Library/TimerLib.h> #include <Library/TimerLib.h>
#include "UfsPassThruHci.h" #include "UfsPassThruHci.h"

View File

@ -52,7 +52,6 @@
UefiDriverEntryPoint UefiDriverEntryPoint
DebugLib DebugLib
DevicePathLib DevicePathLib
IoLib
TimerLib TimerLib
[Protocols] [Protocols]

View File

@ -2,7 +2,7 @@
UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface
for upper layer application to execute UFS-supported SCSI cmds. for upper layer application to execute UFS-supported SCSI cmds.
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -16,29 +16,93 @@
#include "UfsPassThru.h" #include "UfsPassThru.h"
/** /**
Wait for the value of the specified system memory set to the test value. Read 32bits data from specified UFS MMIO register.
@param Address The system memory address to test. @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
@param MaskValue The mask value of memory. @param[in] Offset The offset within the UFS Host Controller MMIO space to start
@param TestValue The test value of memory. the memory operation.
@param Timeout The time out value for wait memory set, uses 100ns as a unit. @param[out] Value The data buffer to store.
@retval EFI_TIMEOUT The system memory setting is time out. @retval EFI_TIMEOUT The operation is time out.
@retval EFI_SUCCESS The system memory is correct set. @retval EFI_SUCCESS The operation succeeds.
@retval Others The operation fails.
**/
EFI_STATUS
UfsMmioRead32 (
IN UFS_PASS_THRU_PRIVATE_DATA *Private,
IN UINTN Offset,
OUT UINT32 *Value
)
{
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
EFI_STATUS Status;
UfsHc = Private->UfsHostController;
Status = UfsHc->Read (UfsHc, EfiUfsHcWidthUint32, Offset, 1, Value);
return Status;
}
/**
Write 32bits data to specified UFS MMIO register.
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
@param[in] Offset The offset within the UFS Host Controller MMIO space to start
the memory operation.
@param[in] Value The data to write.
@retval EFI_TIMEOUT The operation is time out.
@retval EFI_SUCCESS The operation succeeds.
@retval Others The operation fails.
**/
EFI_STATUS
UfsMmioWrite32 (
IN UFS_PASS_THRU_PRIVATE_DATA *Private,
IN UINTN Offset,
IN UINT32 Value
)
{
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
EFI_STATUS Status;
UfsHc = Private->UfsHostController;
Status = UfsHc->Write (UfsHc, EfiUfsHcWidthUint32, Offset, 1, &Value);
return Status;
}
/**
Wait for the value of the specified system memory set to the test value.
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
@param[in] Offset The offset within the UFS Host Controller MMIO space to start
the memory operation.
@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 100ns as a unit.
@retval EFI_TIMEOUT The system memory setting is time out.
@retval EFI_SUCCESS The system memory is correct set.
@retval Others The operation fails.
**/ **/
EFI_STATUS EFI_STATUS
EFIAPI
UfsWaitMemSet ( UfsWaitMemSet (
IN UINTN Address, IN UFS_PASS_THRU_PRIVATE_DATA *Private,
IN UINT32 MaskValue, IN UINTN Offset,
IN UINT32 TestValue, IN UINT32 MaskValue,
IN UINT64 Timeout IN UINT32 TestValue,
IN UINT64 Timeout
) )
{ {
UINT32 Value; UINT32 Value;
UINT64 Delay; UINT64 Delay;
BOOLEAN InfiniteWait; BOOLEAN InfiniteWait;
EFI_STATUS Status;
if (Timeout == 0) { if (Timeout == 0) {
InfiniteWait = TRUE; InfiniteWait = TRUE;
@ -52,7 +116,12 @@ UfsWaitMemSet (
// //
// Access PCI MMIO space to see if the value is the tested one. // Access PCI MMIO space to see if the value is the tested one.
// //
Value = MmioRead32 (Address) & MaskValue; Status = UfsMmioRead32 (Private, Offset, &Value);
if (EFI_ERROR (Status)) {
return Status;
}
Value &= MaskValue;
if (Value == TestValue) { if (Value == TestValue) {
return EFI_SUCCESS; return EFI_SUCCESS;
@ -712,26 +781,33 @@ UfsFindAvailableSlotInTmrl (
@param[in] Slot The slot to be started. @param[in] Slot The slot to be started.
**/ **/
VOID EFI_STATUS
UfsStartExecCmd ( UfsStartExecCmd (
IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_PASS_THRU_PRIVATE_DATA *Private,
IN UINT8 Slot IN UINT8 Slot
) )
{ {
UINTN UfsHcBase;
UINTN Address;
UINT32 Data; UINT32 Data;
EFI_STATUS Status;
UfsHcBase = Private->UfsHcBase; Status = UfsMmioRead32 (Private, UFS_HC_UTRLRSR_OFFSET, &Data);
if (EFI_ERROR (Status)) {
Address = UfsHcBase + UFS_HC_UTRLRSR_OFFSET; return Status;
Data = MmioRead32 (Address);
if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {
MmioWrite32 (Address, UFS_HC_UTRLRSR);
} }
Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET; if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {
MmioWrite32 (Address, BIT0 << Slot); Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
if (EFI_ERROR (Status)) {
return Status;
}
}
Status = UfsMmioWrite32 (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
} }
/** /**
@ -741,25 +817,33 @@ UfsStartExecCmd (
@param[in] Slot The slot to be stop. @param[in] Slot The slot to be stop.
**/ **/
VOID EFI_STATUS
UfsStopExecCmd ( UfsStopExecCmd (
IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_PASS_THRU_PRIVATE_DATA *Private,
IN UINT8 Slot IN UINT8 Slot
) )
{ {
UINTN UfsHcBase;
UINTN Address;
UINT32 Data; UINT32 Data;
EFI_STATUS Status;
UfsHcBase = Private->UfsHcBase; Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
if (EFI_ERROR (Status)) {
Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET; return Status;
Data = MmioRead32 (Address);
if ((Data & (BIT0 << Slot)) != 0) {
Address = UfsHcBase + UFS_HC_UTRLCLR_OFFSET;
Data = MmioRead32 (Address);
MmioWrite32 (Address, (Data & ~(BIT0 << Slot)));
} }
if ((Data & (BIT0 << Slot)) != 0) {
Status = UfsMmioRead32 (Private, UFS_HC_UTRLCLR_OFFSET, &Data);
if (EFI_ERROR (Status)) {
return Status;
}
Status = UfsMmioWrite32 (Private, UFS_HC_UTRLCLR_OFFSET, Data & ~(BIT0 << Slot));
if (EFI_ERROR (Status)) {
return Status;
}
}
return EFI_SUCCESS;
} }
/** /**
@ -793,7 +877,6 @@ UfsRwDeviceDesc (
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet; UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
UINT8 Slot; UINT8 Slot;
UTP_TRD *Trd; UTP_TRD *Trd;
UINTN Address;
UTP_QUERY_RESP_UPIU *QueryResp; UTP_QUERY_RESP_UPIU *QueryResp;
UINT32 CmdDescSize; UINT32 CmdDescSize;
UINT16 ReturnDataSize; UINT16 ReturnDataSize;
@ -852,8 +935,7 @@ UfsRwDeviceDesc (
// //
// Wait for the completion of the transfer request. // Wait for the completion of the transfer request.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);
Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Exit; goto Exit;
} }
@ -922,7 +1004,6 @@ UfsRwAttributes (
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet; UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
UINT8 Slot; UINT8 Slot;
UTP_TRD *Trd; UTP_TRD *Trd;
UINTN Address;
UTP_QUERY_RESP_UPIU *QueryResp; UTP_QUERY_RESP_UPIU *QueryResp;
UINT32 CmdDescSize; UINT32 CmdDescSize;
UINT32 ReturnData; UINT32 ReturnData;
@ -977,8 +1058,7 @@ UfsRwAttributes (
// //
// Wait for the completion of the transfer request. // Wait for the completion of the transfer request.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);
Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Exit; goto Exit;
} }
@ -1038,7 +1118,6 @@ UfsRwFlags (
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet; UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
UINT8 Slot; UINT8 Slot;
UTP_TRD *Trd; UTP_TRD *Trd;
UINTN Address;
UTP_QUERY_RESP_UPIU *QueryResp; UTP_QUERY_RESP_UPIU *QueryResp;
UINT32 CmdDescSize; UINT32 CmdDescSize;
VOID *CmdDescHost; VOID *CmdDescHost;
@ -1103,8 +1182,7 @@ UfsRwFlags (
// //
// Wait for the completion of the transfer request. // Wait for the completion of the transfer request.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);
Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Exit; goto Exit;
} }
@ -1237,7 +1315,6 @@ UfsExecNopCmds (
UTP_TRD *Trd; UTP_TRD *Trd;
UTP_NOP_IN_UPIU *NopInUpiu; UTP_NOP_IN_UPIU *NopInUpiu;
UINT32 CmdDescSize; UINT32 CmdDescSize;
UINTN Address;
VOID *CmdDescHost; VOID *CmdDescHost;
VOID *CmdDescMapping; VOID *CmdDescMapping;
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc; EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
@ -1272,8 +1349,7 @@ UfsExecNopCmds (
// //
// Wait for the completion of the transfer request. // Wait for the completion of the transfer request.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, UFS_TIMEOUT);
Status = UfsWaitMemSet (Address, BIT0, 0, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Exit; goto Exit;
} }
@ -1328,7 +1404,6 @@ UfsExecScsiCmds (
EFI_STATUS Status; EFI_STATUS Status;
UINT8 Slot; UINT8 Slot;
UTP_TRD *Trd; UTP_TRD *Trd;
UINTN Address;
UINT32 CmdDescSize; UINT32 CmdDescSize;
UTP_RESPONSE_UPIU *Response; UTP_RESPONSE_UPIU *Response;
UINT16 SenseDataLen; UINT16 SenseDataLen;
@ -1414,9 +1489,8 @@ UfsExecScsiCmds (
// //
// Wait for the completion of the transfer request. // Wait for the completion of the transfer request.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);
Status = UfsWaitMemSet (Address, BIT0, 0, Packet->Timeout);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto Exit; goto Exit;
} }
@ -1506,18 +1580,21 @@ UfsExecUicCommands (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINTN Address;
UINT32 Data; UINT32 Data;
UINTN UfsHcBase;
UfsHcBase = Private->UfsHcBase; Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);
Address = UfsHcBase + UFS_HC_IS_OFFSET; if (EFI_ERROR (Status)) {
Data = MmioRead32 (Address); return Status;
}
if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) { if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {
// //
// Clear IS.BIT10 UIC Command Completion Status (UCCS) at first. // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.
// //
MmioWrite32 (Address, Data); Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);
if (EFI_ERROR (Status)) {
return Status;
}
} }
// //
@ -1525,41 +1602,48 @@ UfsExecUicCommands (
// only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3) // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)
// are set. // are set.
// //
Address = UfsHcBase + UFS_HC_UCMD_ARG1_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, Arg1);
MmioWrite32 (Address, Arg1);
Address = UfsHcBase + UFS_HC_UCMD_ARG2_OFFSET;
MmioWrite32 (Address, Arg2);
Address = UfsHcBase + UFS_HC_UCMD_ARG3_OFFSET;
MmioWrite32 (Address, Arg3);
//
// Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
//
Address = Private->UfsHcBase + UFS_HC_STATUS_OFFSET;
Status = UfsWaitMemSet (Address, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
Address = UfsHcBase + UFS_HC_UIC_CMD_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, Arg2);
MmioWrite32 (Address, (UINT32)UicOpcode); if (EFI_ERROR (Status)) {
return Status;
}
Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, Arg3);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
//
Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
if (EFI_ERROR (Status)) {
return Status;
}
Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, (UINT32)UicOpcode);
if (EFI_ERROR (Status)) {
return Status;
}
// //
// UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS) // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)
// This bit is set to '1' by the host controller upon completion of a UIC command. // This bit is set to '1' by the host controller upon completion of a UIC command.
// //
Address = UfsHcBase + UFS_HC_IS_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
Data = MmioRead32 (Address);
Status = UfsWaitMemSet (Address, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
if (UicOpcode != UfsUicDmeReset) { if (UicOpcode != UfsUicDmeReset) {
Address = UfsHcBase + UFS_HC_UCMD_ARG2_OFFSET; Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &Data);
Data = MmioRead32 (Address); if (EFI_ERROR (Status)) {
return Status;
}
if ((Data & 0xFF) != 0) { if ((Data & 0xFF) != 0) {
DEBUG_CODE_BEGIN(); DEBUG_CODE_BEGIN();
DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF)); DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF));
@ -1571,11 +1655,13 @@ UfsExecUicCommands (
// //
// Check value of HCS.DP and make sure that there is a device attached to the Link. // Check value of HCS.DP and make sure that there is a device attached to the Link.
// //
Address = UfsHcBase + UFS_HC_STATUS_OFFSET; Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);
Data = MmioRead32 (Address); if (EFI_ERROR (Status)) {
return Status;
}
if ((Data & UFS_HC_HCS_DP) == 0) { if ((Data & UFS_HC_HCS_DP) == 0) {
Address = UfsHcBase + UFS_HC_IS_OFFSET; Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
Status = UfsWaitMemSet (Address, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -1694,7 +1780,6 @@ UfsEnableHostController (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINTN Address;
UINT32 Data; UINT32 Data;
// //
@ -1702,17 +1787,23 @@ UfsEnableHostController (
// //
// Reinitialize the UFS host controller if HCE bit of HC register is set. // Reinitialize the UFS host controller if HCE bit of HC register is set.
// //
Address = Private->UfsHcBase + UFS_HC_ENABLE_OFFSET; Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
Data = MmioRead32 (Address); if (EFI_ERROR (Status)) {
return Status;
}
if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) { if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {
// //
// Write a 0 to the HCE register at first to disable the host controller. // Write a 0 to the HCE register at first to disable the host controller.
// //
MmioWrite32 (Address, 0); Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
if (EFI_ERROR (Status)) {
return Status;
}
// //
// Wait until HCE is read as '0' before continuing. // Wait until HCE is read as '0' before continuing.
// //
Status = UfsWaitMemSet (Address, UFS_HC_HCE_EN, 0, UFS_TIMEOUT); Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -1721,11 +1812,15 @@ UfsEnableHostController (
// //
// Write a 1 to the HCE register to enable the UFS host controller. // Write a 1 to the HCE register to enable the UFS host controller.
// //
MmioWrite32 (Address, UFS_HC_HCE_EN); Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);
if (EFI_ERROR (Status)) {
return Status;
}
// //
// Wait until HCE is read as '1' before continuing. // Wait until HCE is read as '1' before continuing.
// //
Status = UfsWaitMemSet (Address, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT); Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -1789,7 +1884,6 @@ UfsInitTaskManagementRequestList (
IN UFS_PASS_THRU_PRIVATE_DATA *Private IN UFS_PASS_THRU_PRIVATE_DATA *Private
) )
{ {
UINTN Address;
UINT32 Data; UINT32 Data;
UINT8 Nutmrs; UINT8 Nutmrs;
VOID *CmdDescHost; VOID *CmdDescHost;
@ -1803,8 +1897,12 @@ UfsInitTaskManagementRequestList (
CmdDescHost = NULL; CmdDescHost = NULL;
CmdDescMapping = NULL; CmdDescMapping = NULL;
CmdDescPhyAddr = 0; CmdDescPhyAddr = 0;
Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;
Data = MmioRead32 (Address); Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
if (EFI_ERROR (Status)) {
return Status;
}
Private->Capabilities = Data; Private->Capabilities = Data;
// //
@ -1820,10 +1918,15 @@ UfsInitTaskManagementRequestList (
// Program the UTP Task Management Request List Base Address and UTP Task Management // Program the UTP Task Management Request List Base Address and UTP Task Management
// Request List Base Address with a 64-bit address allocated at step 6. // Request List Base Address with a 64-bit address allocated at step 6.
// //
Address = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); if (EFI_ERROR (Status)) {
Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET; return Status;
MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32)); }
Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
if (EFI_ERROR (Status)) {
return Status;
}
Private->UtpTmrlBase = CmdDescHost; Private->UtpTmrlBase = CmdDescHost;
Private->Nutmrs = Nutmrs; Private->Nutmrs = Nutmrs;
Private->TmrlMapping = CmdDescMapping; Private->TmrlMapping = CmdDescMapping;
@ -1832,8 +1935,10 @@ UfsInitTaskManagementRequestList (
// Enable the UTP Task Management Request List by setting the UTP Task Management // Enable the UTP Task Management Request List by setting the UTP Task Management
// Request List RunStop Register (UTMRLRSR) to '1'. // Request List RunStop Register (UTMRLRSR) to '1'.
// //
Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);
MmioWrite32 (Address, UFS_HC_UTMRLRSR); if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -1852,7 +1957,6 @@ UfsInitTransferRequestList (
IN UFS_PASS_THRU_PRIVATE_DATA *Private IN UFS_PASS_THRU_PRIVATE_DATA *Private
) )
{ {
UINTN Address;
UINT32 Data; UINT32 Data;
UINT8 Nutrs; UINT8 Nutrs;
VOID *CmdDescHost; VOID *CmdDescHost;
@ -1866,8 +1970,12 @@ UfsInitTransferRequestList (
CmdDescHost = NULL; CmdDescHost = NULL;
CmdDescMapping = NULL; CmdDescMapping = NULL;
CmdDescPhyAddr = 0; CmdDescPhyAddr = 0;
Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;
Data = MmioRead32 (Address); Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
if (EFI_ERROR (Status)) {
return Status;
}
Private->Capabilities = Data; Private->Capabilities = Data;
// //
@ -1883,10 +1991,16 @@ UfsInitTransferRequestList (
// Program the UTP Transfer Request List Base Address and UTP Transfer Request List // Program the UTP Transfer Request List Base Address and UTP Transfer Request List
// Base Address with a 64-bit address allocated at step 8. // Base Address with a 64-bit address allocated at step 8.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr); if (EFI_ERROR (Status)) {
Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET; return Status;
MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32)); }
Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
if (EFI_ERROR (Status)) {
return Status;
}
Private->UtpTrlBase = CmdDescHost; Private->UtpTrlBase = CmdDescHost;
Private->Nutrs = Nutrs; Private->Nutrs = Nutrs;
Private->TrlMapping = CmdDescMapping; Private->TrlMapping = CmdDescMapping;
@ -1895,8 +2009,10 @@ UfsInitTransferRequestList (
// Enable the UTP Transfer Request List by setting the UTP Transfer Request List // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
// RunStop Register (UTRLRSR) to '1'. // RunStop Register (UTRLRSR) to '1'.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
MmioWrite32 (Address, UFS_HC_UTRLRSR); if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -1960,35 +2076,44 @@ UfsControllerStop (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINTN Address;
UINT32 Data; UINT32 Data;
// //
// Enable the UTP Task Management Request List by setting the UTP Task Management // Enable the UTP Task Management Request List by setting the UTP Task Management
// Request List RunStop Register (UTMRLRSR) to '1'. // Request List RunStop Register (UTMRLRSR) to '1'.
// //
Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);
MmioWrite32 (Address, 0); if (EFI_ERROR (Status)) {
return Status;
}
// //
// Enable the UTP Transfer Request List by setting the UTP Transfer Request List // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
// RunStop Register (UTRLRSR) to '1'. // RunStop Register (UTRLRSR) to '1'.
// //
Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET; Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);
MmioWrite32 (Address, 0); if (EFI_ERROR (Status)) {
return Status;
}
// //
// Write a 0 to the HCE register in order to disable the host controller. // Write a 0 to the HCE register in order to disable the host controller.
// //
Address = Private->UfsHcBase + UFS_HC_ENABLE_OFFSET; Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
Data = MmioRead32 (Address); if (EFI_ERROR (Status)) {
return Status;
}
ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN); ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);
MmioWrite32 (Address, 0);
Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
if (EFI_ERROR (Status)) {
return Status;
}
// //
// Wait until HCE is read as '0' before continuing. // Wait until HCE is read as '0' before continuing.
// //
Status = UfsWaitMemSet (Address, UFS_HC_HCE_EN, 0, UFS_TIMEOUT); Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }

View File

@ -2,7 +2,7 @@
EDKII Universal Flash Storage Host Controller Protocol. EDKII Universal Flash Storage Host Controller Protocol.
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution. the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at The full text of the license may be found at
@ -185,6 +185,42 @@ EFI_STATUS
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
); );
typedef enum {
EfiUfsHcWidthUint8 = 0,
EfiUfsHcWidthUint16,
EfiUfsHcWidthUint32,
EfiUfsHcWidthUint64,
EfiUfsHcWidthMaximum
} EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH;
/**
Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
@param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
@param Width Signifies the width of the memory operations.
@param Offset The offset within the UFS Host Controller MMIO space to start the
memory operation.
@param Count The number of memory operations to perform.
@param Buffer For read operations, the destination buffer to store the results.
For write operations, the source buffer to write data from.
@retval EFI_SUCCESS The data was read from or written to the UFS host controller.
@retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not
valid for the UFS Host Controller memory space.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_UFS_HC_MMIO_READ_WRITE)(
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,
IN UINT64 Offset,
IN UINTN Count,
IN OUT VOID *Buffer
);
/// ///
/// UFS Host Controller Protocol structure. /// UFS Host Controller Protocol structure.
/// ///
@ -195,6 +231,8 @@ struct _EDKII_UFS_HOST_CONTROLLER_PROTOCOL {
EDKII_UFS_HC_MAP Map; EDKII_UFS_HC_MAP Map;
EDKII_UFS_HC_UNMAP Unmap; EDKII_UFS_HC_UNMAP Unmap;
EDKII_UFS_HC_FLUSH Flush; EDKII_UFS_HC_FLUSH Flush;
EDKII_UFS_HC_MMIO_READ_WRITE Read;
EDKII_UFS_HC_MMIO_READ_WRITE Write;
}; };
/// ///