/** @file Pch common library for PCH INIT PEI/DXE/SMM modules Copyright (c) 2019 Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include #include extern CONST PCH_PCIE_CONTROLLER_INFO mPchPcieControllerInfo[]; extern CONST UINT32 mPchPcieControllerInfoSize; #define PORT_PLS_TIMEOUT 100 ///< 100 * 10 us = 1ms timeout for USB3 PortSC PLS polling /** This function returns PID according to PCIe controller index @param[in] ControllerIndex PCIe controller index @retval PCH_SBI_PID Returns PID for SBI Access **/ PCH_SBI_PID PchGetPcieControllerSbiPid ( IN UINT32 ControllerIndex ) { ASSERT (ControllerIndex < mPchPcieControllerInfoSize); return mPchPcieControllerInfo[ControllerIndex].Pid; } /** This function returns PID according to Root Port Number @param[in] RpIndex Root Port Index (0-based) @retval PCH_SBI_PID Returns PID for SBI Access **/ PCH_SBI_PID GetRpSbiPid ( IN UINTN RpIndex ) { return PchGetPcieControllerSbiPid ((UINT32) (RpIndex / PCH_PCIE_CONTROLLER_PORTS)); } /** Calculate root port device number based on physical port index. @param[in] RpIndex Root port index (0-based). @retval Root port device number. **/ UINT32 PchGetPcieRpDevice ( IN UINT32 RpIndex ) { UINTN ControllerIndex; ControllerIndex = RpIndex / PCH_PCIE_CONTROLLER_PORTS; ASSERT (ControllerIndex < mPchPcieControllerInfoSize); return mPchPcieControllerInfo[ControllerIndex].DevNum; } /** This function reads Pci Config register via SBI Access @param[in] RpIndex Root Port Index (0-based) @param[in] Offset Offset of Config register @param[out] *Data32 Value of Config register @retval EFI_SUCCESS SBI Read successful. **/ EFI_STATUS PchSbiRpPciRead32 ( IN UINT32 RpIndex, IN UINT32 Offset, OUT UINT32 *Data32 ) { EFI_STATUS Status; UINT32 RpDevice; UINT8 Response; UINT16 Fid; RpDevice = PchGetPcieRpDevice (RpIndex); Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 )); Status = PchSbiExecutionEx ( GetRpSbiPid (RpIndex), Offset, PciConfigRead, FALSE, 0xF, 0, Fid, Data32, &Response ); if (Status != EFI_SUCCESS) { DEBUG((DEBUG_ERROR,"Sideband Read Failed of RpIndex %d Offset 0x%x. Device = %d Fid = 0x%x\n",RpIndex, Offset, RpDevice, Fid)); ASSERT (FALSE); } return Status; } /** This function And then Or Pci Config register via SBI Access @param[in] RpIndex Root Port Index (0-based) @param[in] Offset Offset of Config register @param[in] Data32And Value of Config register to be And-ed @param[in] Data32AOr Value of Config register to be Or-ed @retval EFI_SUCCESS SBI Read and Write successful. **/ EFI_STATUS PchSbiRpPciAndThenOr32 ( IN UINT32 RpIndex, IN UINT32 Offset, IN UINT32 Data32And, IN UINT32 Data32Or ) { EFI_STATUS Status; UINT32 RpDevice; UINT32 Data32; UINT8 Response; UINT16 Fid; RpDevice = PchGetPcieRpDevice (RpIndex); Status = PchSbiRpPciRead32 (RpIndex, Offset, &Data32); if (Status == EFI_SUCCESS) { Data32 &= Data32And; Data32 |= Data32Or; Fid = (UINT16) ((RpDevice << 3) | (RpIndex % 4 )); Status = PchSbiExecutionEx ( GetRpSbiPid (RpIndex), Offset, PciConfigWrite, FALSE, 0xF, 0, Fid, &Data32, &Response ); if (Status != EFI_SUCCESS) { DEBUG((DEBUG_ERROR,"Sideband Write Failed of RpIndex %d Offset 0x%x. Device = %d Fid = 0x%x\n",RpIndex, Offset, RpDevice, Fid)); ASSERT (FALSE); } } else { ASSERT (FALSE); } return Status; } /** Print registers value @param[in] PrintMmioBase Mmio base address @param[in] PrintSize Number of registers @param[in] OffsetFromBase Offset from mmio base address @retval None **/ VOID PrintRegisters ( IN UINTN PrintMmioBase, IN UINT32 PrintSize, IN UINT32 OffsetFromBase ) { UINT32 Offset; DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")); for (Offset = 0; Offset < PrintSize; Offset++) { if ((Offset % 16) == 0) { DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0)); } DEBUG ((DEBUG_VERBOSE, "%02X ", MmioRead8 (PrintMmioBase + Offset))); } DEBUG ((DEBUG_VERBOSE, "\n")); } /** Print registers value @param[in] PrintPciSegmentBase Pci segment base address @param[in] PrintSize Number of registers @param[in] OffsetFromBase Offset from mmio base address @retval None **/ VOID PrintPciRegisters ( IN UINT64 PrintPciSegmentBase, IN UINT32 PrintSize, IN UINT32 OffsetFromBase ) { UINT32 Offset; DEBUG ((DEBUG_VERBOSE, " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")); for (Offset = 0; Offset < PrintSize; Offset++) { if ((Offset % 16) == 0) { DEBUG ((DEBUG_VERBOSE, "\n %04X: ", (Offset + OffsetFromBase) & 0xFFF0)); } DEBUG ((DEBUG_VERBOSE, "%02X ", PciSegmentRead8 (PrintPciSegmentBase + Offset))); } DEBUG ((DEBUG_VERBOSE, "\n")); }