On Sat, Apr 01, 2017 at 07:29:09PM +0800, Chenhui Sun wrote:
In some cases, the PCIe device may close part of lanes in config state of LTSSM, the hip06 RC should reconfig lane number and try to linkup again.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Chenhui Sun sunchenhui@huawei.com Signed-off-by: Heyi Guo heyi.guo@linaro.org Signed-off-by: Yi Li phoenix.liyi@huawei.com
Reviewed-by: Leif Lindholm leif.lindholm@linaro.org
.../Hi1610/Drivers/PcieInit1610/PcieInitLib.c | 136 ++++++++++++++++++++- Chips/Hisilicon/Include/Regs/HisiPcieV1RegOffset.h | 5 + 2 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/Chips/Hisilicon/Hi1610/Drivers/PcieInit1610/PcieInitLib.c b/Chips/Hisilicon/Hi1610/Drivers/PcieInit1610/PcieInitLib.c index 8ec094f..bd91ca4 100644 --- a/Chips/Hisilicon/Hi1610/Drivers/PcieInit1610/PcieInitLib.c +++ b/Chips/Hisilicon/Hi1610/Drivers/PcieInit1610/PcieInitLib.c @@ -39,6 +39,14 @@ extern PCIE_DRIVER_CFG gastr_pcie_driver_cfg; extern PCIE_IATU gastr_pcie_iatu_cfg; extern PCIE_IATU_VA mPcieIatuTable; +EFI_STATUS +EFIAPI +PciePortInit (
- IN UINT32 soctype,
 - IN UINT32 HostBridgeNum,
 - IN PCIE_DRIVER_CFG *PcieCfg
 - );
 VOID PcieRegWrite(UINT32 Port, UINTN Offset, UINT32 Value) { RegWrite((UINT64)mPcieIntCfg.RegResource[Port] + Offset, Value); @@ -149,8 +157,131 @@ VOID PcieRxValidCtrl(UINT32 soctype, UINT32 HostBridgeNum, UINT32 Port, BOOLEAN } } } +/*
- The ltssm register is assigned in an asynchronous way, the value
 
- of register may not right in metastable state.
 
- Read the register twice to get stable value.
 - */
 +VOID PcieGetLtssmValue (
- IN UINT32 HostBridgeNum,
 - IN UINT32 Port,
 - IN UINT32 *Value
 - )
 +{
- UINT32 ValueA;
 - UINT32 ValueB = 0;
 - UINT32 Count;
 - RegRead (PCIE_APB_SLAVE_BASE_1610[HostBridgeNum][Port] + PCIE_SYS_REG_OFFSET + PCIE_SYS_STATE4_REG, ValueA);
 - ValueA = ValueA & PCIE_LTSSM_STATE_MASK;
 - Count = 0;
 - while (Count < 2) {
 - RegRead (PCIE_APB_SLAVE_BASE_1610[HostBridgeNum][Port] + PCIE_SYS_REG_OFFSET + PCIE_SYS_STATE4_REG, ValueB);
 - ValueB = ValueB & PCIE_LTSSM_STATE_MASK;
 - /* Get the same state in continuous two times*/
 - if (ValueA == ValueB) {
 break;- }
 - //If the second value not equal to the first, we return the second one as the stable
 - ValueA = ValueB;
 - Count++;
 - }
 - *Value = ValueB;
 - return;
 +}
+/*
- In some cases, the PCIe device may close part of lanes in
 
- config state of LTSSM, the hip06 RC should reconfig lane num
 
- and try to linkup again.
 - */
 +VOID PcieReconfigLaneNum (
- IN UINT32 soctype,
 - IN UINT32 HostBridgeNum,
 - IN UINT32 Port,
 - IN PCIE_DRIVER_CFG *PcieCfg
 - )
 +{
- EFI_STATUS Status;
 - UINT32 LtssmStatus;
 - UINT32 RegVal;
 - UINT32 LoopCnt = 0;
 - UINT32 LaneNumCnt = 0;
 - PCIE_PORT_WIDTH PortWidth = PcieCfg->PortInfo.PortWidth;
 - // 500 * 200us = 100ms, so it takes 100 ms must to reconfig lane numbers
 - while (LoopCnt < 500) {
 - /*
 * The minimum lanenum is 1, no need to try any more.*/- if (PortWidth <= 1) {
 DEBUG ((DEBUG_ERROR, "PcieReconfigLanenum PortWidth <= 1 !\n"));return;- }
 - /*
 * Check the lane num config state is normal or not.*/- PcieGetLtssmValue (HostBridgeNum, Port, &LtssmStatus);
 - if ((LtssmStatus == PCIE_LTSSM_CFG_LANENUM_ACPT) || (LtssmStatus == PCIE_LTSSM_CFG_COMPLETE)) {
 LaneNumCnt++;- } else if (LtssmStatus == PCIE_LTSSM_LINKUP_STATE) {
 PcieGetLtssmValue (HostBridgeNum, Port, &LtssmStatus);if (LtssmStatus == PCIE_LTSSM_LINKUP_STATE) {break;}- } else {
 LaneNumCnt = 0;- }
 - /*
 * The lane num config state is abnormal, need to reconfig* the lane num and try to establish link again.*/- if (LaneNumCnt > MAX_TRY_LINK_NUM) {
 /* Disable LTSSM */RegRead (PCIE_APB_SLAVE_BASE_1610[HostBridgeNum][Port] + PCIE_CTRL_7_REG, RegVal);RegVal &= ~(LTSSM_ENABLE);RegWrite (PCIE_APB_SLAVE_BASE_1610[HostBridgeNum][Port] + PCIE_CTRL_7_REG, RegVal);/** Decrease the PortWidth and try to link again,* the value of PortWidth 0xf (X8), 0x7(x4), 0x3(X2), 0x1(X1)*/PcieCfg->PortInfo.PortWidth = (PCIE_PORT_WIDTH)((UINT8)PcieCfg->PortInfo.PortWidth >> 1);Status = PciePortInit (soctype, HostBridgeNum, PcieCfg);if (EFI_ERROR(Status)) {DEBUG ((DEBUG_ERROR, "PcieReconfigLanenum HostBridge %d, Pcie Port %d Init Failed! \n", HostBridgeNum, Port));}return;- }
 - LoopCnt++;
 - /* Pcie 3.0 Spec,part 4.2.6.3.4.1: the Upstream Lanes are permitted
 * delay up to 1 ms before transitioning to Configuration.Lanenum.Accept.* So the delay time 200 us * 5(LanNumCnt) = 1ms, not beyond the reasonable range.*/- MicroSecondDelay (200);
 - }
 - return ;
 +} -EFI_STATUS PcieEnableItssm(UINT32 soctype, UINT32 HostBridgeNum, UINT32 Port) +EFI_STATUS +PcieEnableItssm (
- IN UINT32 soctype,
 - IN UINT32 HostBridgeNum,
 - IN UINT32 Port,
 - IN PCIE_DRIVER_CFG *PcieCfg
 - )
 { PCIE_CTRL_7_U pcie_ctrl7; UINT32 Value = 0; @@ -165,6 +296,7 @@ EFI_STATUS PcieEnableItssm(UINT32 soctype, UINT32 HostBridgeNum, UINT32 Port) Value |= BIT11|BIT30|BIT31; RegWrite(PCIE_APB_SLAVE_BASE_1610[HostBridgeNum][Port] + 0x1114, Value); (VOID)PcieRxValidCtrl(soctype, HostBridgeNum, Port, 1);
 } elsePcieReconfigLaneNum (soctype, HostBridgeNum, Port, PcieCfg); return EFI_SUCCESS;@@ -1008,7 +1140,7 @@ PciePortInit ( /* Disable RC Option Rom */ DisableRcOptionRom (soctype, HostBridgeNum, PortIndex, PcieCfg->PortInfo.PortType); /* assert LTSSM enable */
(VOID)PcieEnableItssm(soctype, HostBridgeNum, PortIndex);
(VOID)PcieEnableItssm (soctype, HostBridgeNum, PortIndex, PcieCfg); if (FeaturePcdGet(PcdIsPciPerfTuningEnable)) { //PCIe will still work even if performance tuning fails, //and there is warning message inside the function to printdiff --git a/Chips/Hisilicon/Include/Regs/HisiPcieV1RegOffset.h b/Chips/Hisilicon/Include/Regs/HisiPcieV1RegOffset.h index 539d567..bf57652 100644 --- a/Chips/Hisilicon/Include/Regs/HisiPcieV1RegOffset.h +++ b/Chips/Hisilicon/Include/Regs/HisiPcieV1RegOffset.h @@ -8982,6 +8982,7 @@ typedef union tagIepMsiCtrlIntStatus #define PCIE_SYS_CTRL28_REG (PCI_SYS_BASE + 0x1c4) #define PCIE_SYS_CTRL29_REG (PCI_SYS_BASE + 0x1c8) #define PCIE_SYS_CTRL54_REG (PCI_SYS_BASE + 0x274) +#define PCIE_SYS_STATE4_REG (PCI_SYS_BASE + 0x31C) #define PCIE_SYS_STATE5_REG (PCI_SYS_BASE + 0x30) #define PCIE_SYS_STATE6_REG (PCI_SYS_BASE + 0x34) #define PCIE_SYS_STATE7_REG (PCI_SYS_BASE + 0x38) @@ -12694,7 +12695,11 @@ typedef union tagPortlogic93 #define PCIE_SUBCTRL_SC_PCIE0_SYS_STATE3_REG (PCIE_SUBCTRL_BASE + 0x6814) #define PCIE_SUBCTRL_SC_PCIE0_SYS_STATE4_REG (PCIE_SUBCTRL_BASE + 0x6818) #define PCIE_LTSSM_STATE_MASK (0x3f) +#define PCIE_LTSSM_CFG_LANENUM_ACPT 0x0a +#define PCIE_LTSSM_CFG_COMPLETE 0x0b #define PCIE_LTSSM_LINKUP_STATE (0x11) +#define LTSSM_ENABLE BIT11 +#define MAX_TRY_LINK_NUM 5 #define PCIE_SUBCTRL_SC_PCIE0_AXI_MSTR_OOO_WR_STS0_REG (PCIE_SUBCTRL_BASE + 0x6880) #define PCIE_SUBCTRL_SC_PCIE0_AXI_MSTR_OOO_WR_STS1_REG (PCIE_SUBCTRL_BASE + 0x6884)
#define PCIE_SUBCTRL_SC_PCIE0_AXI_MSTR_OOO_RD_STS0_REG (PCIE_SUBCTRL_BASE + 0x6890)
1.9.1