/******************************************************************************** Copyright (C) 2016 Marvell International Ltd. SPDX-License-Identifier: BSD-2-Clause-Patent *******************************************************************************/ #include "ComPhyLib.h" #include #include #include #define SD_LANE_ADDR_WIDTH 0x1000 #define HPIPE_ADDR_OFFSET 0x800 #define COMPHY_ADDR_LANE_WIDTH 0x28 #define SD_ADDR(base, Lane) (base + SD_LANE_ADDR_WIDTH * Lane) #define HPIPE_ADDR(base, Lane) (SD_ADDR(base, Lane) + HPIPE_ADDR_OFFSET) #define COMPHY_ADDR(base, Lane) (base + COMPHY_ADDR_LANE_WIDTH * Lane) STATIC VOID ComPhySataMacPowerDown ( IN EFI_PHYSICAL_ADDRESS SataBase ) { UINT32 Mask, Data; /* * MAC configuration - power down ComPhy * Use indirect address for vendor specific SATA control register */ RegSet (SataBase + SATA3_VENDOR_ADDRESS, SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET, SATA3_VENDOR_ADDR_MASK); /* SATA 0 power down */ Mask = SATA3_CTRL_SATA0_PD_MASK; Data = 0x1 << SATA3_CTRL_SATA0_PD_OFFSET; /* SATA 1 power down */ Mask |= SATA3_CTRL_SATA1_PD_MASK; Data |= 0x1 << SATA3_CTRL_SATA1_PD_OFFSET; /* SATA SSU disable */ Mask |= SATA3_CTRL_SATA1_ENABLE_MASK; Data |= 0x0 << SATA3_CTRL_SATA1_ENABLE_OFFSET; /* SATA port 1 disable */ Mask |= SATA3_CTRL_SATA_SSU_MASK; Data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET; RegSet (SataBase + SATA3_VENDOR_DATA, Data, Mask); } STATIC VOID ComPhySataPhyPowerUp ( IN EFI_PHYSICAL_ADDRESS SataBase ) { UINT32 Data, Mask; /* * MAC configuration - power up ComPhy - power up PLL/TX/RX * Use indirect address for vendor specific SATA control register */ RegSet (SataBase + SATA3_VENDOR_ADDRESS, SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET, SATA3_VENDOR_ADDR_MASK); /* SATA 0 power up */ Mask = SATA3_CTRL_SATA0_PD_MASK; Data = 0x0 << SATA3_CTRL_SATA0_PD_OFFSET; /* SATA 1 power up */ Mask |= SATA3_CTRL_SATA1_PD_MASK; Data |= 0x0 << SATA3_CTRL_SATA1_PD_OFFSET; /* SATA SSU enable */ Mask |= SATA3_CTRL_SATA1_ENABLE_MASK; Data |= 0x1 << SATA3_CTRL_SATA1_ENABLE_OFFSET; /* SATA port 1 enable */ Mask |= SATA3_CTRL_SATA_SSU_MASK; Data |= 0x1 << SATA3_CTRL_SATA_SSU_OFFSET; RegSet (SataBase + SATA3_VENDOR_DATA, Data, Mask); /* MBUS request size and interface select register */ RegSet (SataBase + SATA3_VENDOR_ADDRESS, SATA_MBUS_SIZE_SELECT_REG << SATA3_VENDOR_ADDR_OFSSET, SATA3_VENDOR_ADDR_MASK); /* Mbus regret enable */ RegSet (SataBase + SATA3_VENDOR_DATA, 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK); } STATIC EFI_STATUS ComPhySmc ( IN UINT32 FunctionId, EFI_PHYSICAL_ADDRESS ComPhyBaseAddr, IN UINT32 Lane, IN UINT32 Mode ) { ARM_SMC_ARGS SmcRegs = {0}; SmcRegs.Arg0 = FunctionId; SmcRegs.Arg1 = (UINTN)ComPhyBaseAddr; SmcRegs.Arg2 = Lane; SmcRegs.Arg3 = Mode; ArmCallSmc (&SmcRegs); if (SmcRegs.Arg0 != 0) { return EFI_DEVICE_ERROR; } return EFI_SUCCESS; } STATIC UINTN ComPhySataPowerUp ( IN UINTN ChipId, IN UINT32 Lane, IN EFI_PHYSICAL_ADDRESS HpipeBase, IN EFI_PHYSICAL_ADDRESS ComPhyBase, IN MV_BOARD_AHCI_DESC *Desc ) { EFI_STATUS Status; DEBUG ((DEBUG_INFO, "ComPhySata: Initialize SATA PHYs\n")); DEBUG((DEBUG_INFO, "ComPhySataPowerUp: stage: MAC configuration - power down ComPhy\n")); ComPhySataMacPowerDown (Desc[ChipId].SoC->AhciBaseAddress); Status = ComPhySmc (MV_SMC_ID_COMPHY_POWER_ON, ComPhyBase, Lane, COMPHY_FW_FORMAT (COMPHY_SATA_MODE, Desc[ChipId].SoC->AhciId, COMPHY_SPEED_DEFAULT)); if (EFI_ERROR (Status)) { return Status; } ComPhySataPhyPowerUp (Desc[ChipId].SoC->AhciBaseAddress); Status = ComPhySmc (MV_SMC_ID_COMPHY_PLL_LOCK, ComPhyBase, Lane, COMPHY_FW_FORMAT (COMPHY_SATA_MODE, Desc[ChipId].SoC->AhciId, COMPHY_SPEED_DEFAULT)); if (EFI_ERROR (Status)) { return Status; } return Status; } VOID ComPhyCp110Init ( IN CHIP_COMPHY_CONFIG *PtrChipCfg ) { EFI_STATUS Status; COMPHY_MAP *PtrComPhyMap, *SerdesMap; EFI_PHYSICAL_ADDRESS ComPhyBaseAddr, HpipeBaseAddr; MARVELL_BOARD_DESC_PROTOCOL *BoardDescProtocol; MV_BOARD_AHCI_DESC *AhciBoardDesc; UINT32 ComPhyMaxCount, Lane; UINT32 PcieWidth = 0; UINT8 ChipId; ComPhyMaxCount = PtrChipCfg->LanesCount; ComPhyBaseAddr = PtrChipCfg->ComPhyBaseAddr; HpipeBaseAddr = PtrChipCfg->Hpipe3BaseAddr; SerdesMap = PtrChipCfg->MapData; ChipId = PtrChipCfg->ChipId; /* Check if the first 4 Lanes configured as By-4 */ for (Lane = 0, PtrComPhyMap = SerdesMap; Lane < 4; Lane++, PtrComPhyMap++) { if (PtrComPhyMap->Type != COMPHY_TYPE_PCIE0) { break; } PcieWidth++; } for (Lane = 0, PtrComPhyMap = SerdesMap; Lane < ComPhyMaxCount; Lane++, PtrComPhyMap++) { DEBUG((DEBUG_INFO, "ComPhy: Initialize serdes number %d\n", Lane)); DEBUG((DEBUG_INFO, "ComPhy: Serdes Type = 0x%x\n", PtrComPhyMap->Type)); if (Lane >= 4) { /* PCIe lanes above the first 4 lanes, can be only by1 */ PcieWidth = 1; } switch (PtrComPhyMap->Type) { case COMPHY_TYPE_UNCONNECTED: continue; break; case COMPHY_TYPE_PCIE0: case COMPHY_TYPE_PCIE1: case COMPHY_TYPE_PCIE2: case COMPHY_TYPE_PCIE3: Status = ComPhySmc (MV_SMC_ID_COMPHY_POWER_ON, PtrChipCfg->ComPhyBaseAddr, Lane, COMPHY_FW_PCIE_FORMAT (PcieWidth, COMPHY_PCIE_MODE, PtrComPhyMap->Speed)); break; case COMPHY_TYPE_SATA0: case COMPHY_TYPE_SATA1: case COMPHY_TYPE_SATA2: case COMPHY_TYPE_SATA3: /* Obtain AHCI board description */ Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid, NULL, (VOID **)&BoardDescProtocol); if (EFI_ERROR (Status)) { break; } Status = BoardDescProtocol->BoardDescAhciGet (BoardDescProtocol, &AhciBoardDesc); if (EFI_ERROR (Status)) { break; } Status = ComPhySataPowerUp (ChipId, Lane, HpipeBaseAddr, ComPhyBaseAddr, AhciBoardDesc); BoardDescProtocol->BoardDescFree (AhciBoardDesc); break; case COMPHY_TYPE_USB3_HOST0: case COMPHY_TYPE_USB3_HOST1: Status = ComPhySmc (MV_SMC_ID_COMPHY_POWER_ON, PtrChipCfg->ComPhyBaseAddr, Lane, COMPHY_FW_MODE_FORMAT (COMPHY_USB3H_MODE)); break; case COMPHY_TYPE_SGMII0: case COMPHY_TYPE_SGMII1: case COMPHY_TYPE_SGMII2: case COMPHY_TYPE_SGMII3: Status = ComPhySmc (MV_SMC_ID_COMPHY_POWER_ON, PtrChipCfg->ComPhyBaseAddr, Lane, COMPHY_FW_FORMAT (COMPHY_SGMII_MODE, (PtrComPhyMap->Type - COMPHY_TYPE_SGMII0), PtrComPhyMap->Speed)); break; case COMPHY_TYPE_SFI: Status = ComPhySmc (MV_SMC_ID_COMPHY_POWER_ON, PtrChipCfg->ComPhyBaseAddr, Lane, COMPHY_FW_FORMAT (COMPHY_SFI_MODE, COMPHY_UNIT_ID0, PtrComPhyMap->Speed)); break; case COMPHY_TYPE_RXAUI0: case COMPHY_TYPE_RXAUI1: Status = ComPhySmc (MV_SMC_ID_COMPHY_POWER_ON, PtrChipCfg->ComPhyBaseAddr, Lane, COMPHY_FW_MODE_FORMAT (COMPHY_RXAUI_MODE)); break; default: DEBUG((DEBUG_ERROR, "Unknown SerDes Type, skip initialize SerDes %d\n", Lane)); Status = EFI_INVALID_PARAMETER; ASSERT (FALSE); break; } if (EFI_ERROR(Status)) { DEBUG ((DEBUG_ERROR, "Failed to initialize Lane %d\n with Status = 0x%x", Lane, Status)); PtrComPhyMap->Type = COMPHY_TYPE_UNCONNECTED; } } }