/** * * Copyright (C) 2018, Marvell International Ltd. and its affiliates. * * SPDX-License-Identifier: BSD-2-Clause-Patent * * Glossary - abbreviations used in Marvell SampleAtReset library implementation: * AP - Application Processor hardware block (Armada 7k8k incorporates AP806) * CP - South Bridge hardware blocks (Armada 7k8k incorporates CP110) **/ #include #include #include #include #include #include #include #include #include "Armada7k8kSoCDescLib.h" /** Routine Description: Get base address of the SoC North Bridge. Arguments: ApBase - Base address of the North Bridge. ApIndex - Index of the North Bridge. Returns: EFI_SUCCESS - Proper base address is returned. EFI_INVALID_PARAMETER - The index is out of range. **/ EFI_STATUS EFIAPI ArmadaSoCAp8xxBaseGet ( IN OUT EFI_PHYSICAL_ADDRESS *ApBase, IN UINTN ApIndex ) { if (ApIndex != ARMADA7K8K_AP806_INDEX) { DEBUG ((DEBUG_ERROR, "%a: Only one AP806 in A7K/A8K SoC\n", __FUNCTION__)); return EFI_INVALID_PARAMETER; } *ApBase = MV_SOC_AP806_BASE; return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescComPhyGet ( IN OUT MV_SOC_COMPHY_DESC **ComPhyDesc, IN OUT UINTN *DescCount ) { MV_SOC_COMPHY_DESC *Desc; UINTN CpCount, CpIndex; CpCount = FixedPcdGet8 (PcdMaxCpCount); Desc = AllocateZeroPool (CpCount * sizeof (MV_SOC_COMPHY_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { Desc[CpIndex].ComPhyBaseAddress = MV_SOC_COMPHY_BASE (CpIndex); Desc[CpIndex].ComPhyHpipe3BaseAddress = MV_SOC_HPIPE3_BASE (CpIndex); Desc[CpIndex].ComPhyLaneCount = MV_SOC_COMPHY_LANE_COUNT; Desc[CpIndex].ComPhyMuxBitCount = MV_SOC_COMPHY_MUX_BITS; Desc[CpIndex].ComPhyChipType = MvComPhyTypeCp110; Desc[CpIndex].ComPhyId = CpIndex; } *ComPhyDesc = Desc; *DescCount = CpCount; return EFI_SUCCESS; } EFI_PHYSICAL_ADDRESS EFIAPI ArmadaSoCDescCpBaseGet ( IN UINTN CpIndex ) { ASSERT (CpIndex < FixedPcdGet8 (PcdMaxCpCount)); return MV_SOC_CP_BASE (CpIndex); } EFI_STATUS EFIAPI ArmadaSoCGpioGet ( IN OUT GPIO_CONTROLLER **SoCGpioDescription, IN OUT UINTN *Count ) { GPIO_CONTROLLER *GpioInstance; UINTN CpCount, CpIndex, Index; CpCount = FixedPcdGet8 (PcdMaxCpCount); *Count = CpCount * MV_SOC_GPIO_PER_CP_COUNT + MV_SOC_AP806_COUNT; GpioInstance = AllocateZeroPool (*Count * sizeof (GPIO_CONTROLLER)); if (GpioInstance == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } *SoCGpioDescription = GpioInstance; /* AP806 GPIO controller */ GpioInstance->RegisterBase = MV_SOC_AP806_GPIO_BASE; GpioInstance->InternalGpioCount = MV_SOC_AP806_GPIO_PIN_COUNT; GpioInstance++; /* CP110 GPIO controllers */ for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { for (Index = 0; Index < MV_SOC_GPIO_PER_CP_COUNT; Index++) { GpioInstance->RegisterBase = MV_SOC_CP_BASE (CpIndex) + MV_SOC_CP_GPIO_BASE (Index); GpioInstance->InternalGpioCount = MV_SOC_CP_GPIO_PIN_COUNT (Index); GpioInstance++; } } return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescI2cGet ( IN OUT MV_SOC_I2C_DESC **I2cDesc, IN OUT UINTN *DescCount ) { MV_SOC_I2C_DESC *Desc; UINTN CpCount, CpIndex, Index; CpCount = FixedPcdGet8 (PcdMaxCpCount); *DescCount = CpCount * MV_SOC_I2C_PER_CP_COUNT + MV_SOC_I2C_PER_AP_COUNT; Desc = AllocateZeroPool (*DescCount * sizeof (MV_SOC_I2C_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } *I2cDesc = Desc; Desc->I2cBaseAddress = MV_SOC_I2C_AP_BASE; Desc++; for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { for (Index = 0; Index < MV_SOC_I2C_PER_CP_COUNT; Index++) { Desc->I2cBaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_I2C_BASE (Index); Desc++; } } return EFI_SUCCESS; } // // Allocate the MSI address per interrupt Group, // unsupported Groups get NULL address. // STATIC MV_SOC_ICU_DESC mA7k8kIcuDescTemplate = { ICU_GIC_MAPPING_OFFSET, { /* Non secure interrupts */ { IcuGroupNsr, ICU_NSR_SET_SPI_BASE, ICU_NSR_CLEAR_SPI_BASE }, /* Secure interrupts */ { IcuGroupSr, ICU_GROUP_UNSUPPORTED, ICU_GROUP_UNSUPPORTED }, /* LPI interrupts */ { IcuGroupLpi, ICU_GROUP_UNSUPPORTED, ICU_GROUP_UNSUPPORTED }, /* Virtual LPI interrupts */ { IcuGroupVlpi, ICU_GROUP_UNSUPPORTED, ICU_GROUP_UNSUPPORTED }, /* System error interrupts */ { IcuGroupSei, ICU_SEI_SET_SPI_BASE, ICU_SEI_CLEAR_SPI_BASE }, /* RAM error interrupts */ { IcuGroupRei, ICU_REI_SET_SPI_BASE, ICU_REI_CLEAR_SPI_BASE }, } }; EFI_STATUS EFIAPI ArmadaSoCDescIcuGet ( IN OUT MV_SOC_ICU_DESC **IcuDesc ) { *IcuDesc = AllocateCopyPool (sizeof (mA7k8kIcuDescTemplate), &mA7k8kIcuDescTemplate); if (*IcuDesc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescMdioGet ( IN OUT MV_SOC_MDIO_DESC **MdioDesc, IN OUT UINTN *DescCount ) { MV_SOC_MDIO_DESC *Desc; UINTN CpCount, CpIndex; CpCount = FixedPcdGet8 (PcdMaxCpCount); Desc = AllocateZeroPool (CpCount * sizeof (MV_SOC_MDIO_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { Desc[CpIndex].MdioId = MV_SOC_MDIO_ID (CpIndex); Desc[CpIndex].MdioBaseAddress = MV_SOC_MDIO_BASE (CpIndex); } *MdioDesc = Desc; *DescCount = CpCount; return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescAhciGet ( IN OUT MV_SOC_AHCI_DESC **AhciDesc, IN OUT UINTN *DescCount ) { MV_SOC_AHCI_DESC *Desc; UINTN CpCount, CpIndex; CpCount = FixedPcdGet8 (PcdMaxCpCount); Desc = AllocateZeroPool (CpCount * sizeof (MV_SOC_AHCI_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { Desc[CpIndex].AhciId = MV_SOC_AHCI_ID (CpIndex); Desc[CpIndex].AhciBaseAddress = MV_SOC_AHCI_BASE (CpIndex); Desc[CpIndex].AhciMemSize = SIZE_8KB; Desc[CpIndex].AhciDmaType = NonDiscoverableDeviceDmaTypeCoherent; } *AhciDesc = Desc; *DescCount = CpCount; return EFI_SUCCESS; } /** This function returns the total number of PCIE controllers and an array with their base addresses. @param[in out] **PcieBaseAddresses Array containing PCIE controllers' base adresses. @param[in out] *Count Total amount of available PCIE controllers. @retval EFI_SUCCESS The data were obtained successfully. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. **/ EFI_STATUS EFIAPI ArmadaSoCPcieGet ( IN OUT EFI_PHYSICAL_ADDRESS **PcieBaseAddresses, IN OUT UINTN *Count ) { UINTN CpCount, CpIndex, Index; EFI_PHYSICAL_ADDRESS *BaseAddress; CpCount = FixedPcdGet8 (PcdMaxCpCount); *Count = CpCount * MV_SOC_PCIE_PER_CP_COUNT; BaseAddress = AllocateZeroPool (*Count * sizeof (EFI_PHYSICAL_ADDRESS)); if (BaseAddress == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } *PcieBaseAddresses = BaseAddress; for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { for (Index = 0; Index < MV_SOC_PCIE_PER_CP_COUNT; Index++) { *BaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_PCIE_BASE (Index); BaseAddress++; } } return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescPp2Get ( IN OUT MV_SOC_PP2_DESC **Pp2Desc, IN OUT UINTN *DescCount ) { MV_SOC_PP2_DESC *Desc; UINTN CpCount, CpIndex; CpCount = FixedPcdGet8 (PcdMaxCpCount); Desc = AllocateZeroPool (CpCount * sizeof (MV_SOC_PP2_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { Desc[CpIndex].Pp2BaseAddress = MV_SOC_PP2_BASE (CpIndex); Desc[CpIndex].Pp2ClockFrequency = MV_SOC_PP2_CLK_FREQ; } *Pp2Desc = Desc; *DescCount = CpCount; return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescSdMmcGet ( IN OUT MV_SOC_SDMMC_DESC **SdMmcDesc, IN OUT UINTN *Count ) { MV_SOC_SDMMC_DESC *SdMmc; UINTN CpCount, CpIndex; CpCount = FixedPcdGet8 (PcdMaxCpCount); *Count = CpCount * MV_SOC_SDMMC_PER_CP_COUNT + MV_SOC_AP806_COUNT; SdMmc = AllocateZeroPool (*Count * sizeof (MV_SOC_SDMMC_DESC)); if (SdMmc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } *SdMmcDesc = SdMmc; /* AP80x controller */ SdMmc->SdMmcBaseAddress = MV_SOC_AP80X_SDMMC_BASE; SdMmc->SdMmcMemSize = SIZE_1KB; SdMmc->SdMmcDmaType = NonDiscoverableDeviceDmaTypeCoherent; SdMmc++; /* CP11x controllers */ for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { SdMmc->SdMmcBaseAddress = MV_SOC_CP_SDMMC_BASE (CpIndex); SdMmc->SdMmcMemSize = SIZE_1KB; SdMmc->SdMmcDmaType = NonDiscoverableDeviceDmaTypeCoherent; SdMmc++; } return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescUtmiGet ( IN OUT MV_SOC_UTMI_DESC **UtmiDesc, IN OUT UINTN *DescCount ) { MV_SOC_UTMI_DESC *Desc; UINTN CpCount, CpIndex, Index, UtmiIndex; CpCount = FixedPcdGet8 (PcdMaxCpCount); *DescCount = CpCount * MV_SOC_UTMI_PER_CP_COUNT; Desc = AllocateZeroPool (*DescCount * sizeof (MV_SOC_UTMI_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } *UtmiDesc = Desc; UtmiIndex = 0; for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { for (Index = 0; Index < MV_SOC_UTMI_PER_CP_COUNT; Index++) { Desc->UtmiPhyId = MV_SOC_UTMI_ID (UtmiIndex); Desc->UtmiBaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_UTMI_BASE (Index); Desc->UtmiPllAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_UTMI_PLL_BASE; Desc->UtmiConfigAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_UTMI_CFG_BASE; Desc->UsbConfigAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_UTMI_USB_CFG_BASE; Desc++; UtmiIndex++; } } return EFI_SUCCESS; } EFI_STATUS EFIAPI ArmadaSoCDescXhciGet ( IN OUT MV_SOC_XHCI_DESC **XhciDesc, IN OUT UINTN *DescCount ) { MV_SOC_XHCI_DESC *Desc; UINTN CpCount, CpIndex, Index; CpCount = FixedPcdGet8 (PcdMaxCpCount); *DescCount = CpCount * MV_SOC_XHCI_PER_CP_COUNT; Desc = AllocateZeroPool (*DescCount * sizeof (MV_SOC_XHCI_DESC)); if (Desc == NULL) { DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); return EFI_OUT_OF_RESOURCES; } *XhciDesc = Desc; for (CpIndex = 0; CpIndex < CpCount; CpIndex++) { for (Index = 0; Index < MV_SOC_XHCI_PER_CP_COUNT; Index++) { Desc->XhciBaseAddress = MV_SOC_CP_BASE (CpIndex) + MV_SOC_XHCI_BASE (Index); Desc->XhciMemSize = SIZE_16KB; Desc->XhciDmaType = NonDiscoverableDeviceDmaTypeCoherent; Desc++; } } return EFI_SUCCESS; }