public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Leif Lindholm <leif.lindholm@linaro.org>
To: Daniil Egranov <daniil.egranov@arm.com>
Cc: edk2-devel@lists.01.org, Daniil Egranov <daniil.egranov@linaro.org>
Subject: Re: [PATCH v4] ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe: Set Marvell Yukon MAC address
Date: Tue, 10 Jan 2017 22:36:10 +0000	[thread overview]
Message-ID: <20170110223609.GC24544@bivouac.eciton.net> (raw)
In-Reply-To: <1483996851-37828-1-git-send-email-daniil.egranov@arm.com>

On Mon, Jan 09, 2017 at 03:20:51PM -0600, Daniil Egranov wrote:
> From: Daniil Egranov <daniil.egranov@linaro.org>
> 
> The patch reads a valid MAC address form the Juno IOFPGA registers 
> and pushes it into onboard Marvell Yukon NIC.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Daniil Egranov <daniil.egranov@linaro.org>

Thanks for sticking with it.

I fixed a typo in commit message an shortened the subject line
slightly, but:
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Pushed as a8675a1

Regards,

Leif

> ---
> 
> Hi Leif,
> 
> The Marvell control registers should be accesable through the memory
> specified in BAR 0.
> 
> The new helper function should cover all 4 checks:
> - We can read BAR 0 attributes. 
>  We always read BAR 0
> - BAR 0 resources contain at least one QWORD Address Space Descriptor.
> - The first of these refers to something memory mapped.
> - That it is not (ARM terminology) Normal memory.
>  The BAR 0 for Marvell Yukon should always be a memory type. I am not 
>  sure if it's possible to have more than one descriptor for a BAR. The 
>  current implementation of PciIoGetBarAttributes() will return only one
>  descriptor based on BAR index following the End Tag one. This update 
>  will step through Address Space Descriptors anyway until the End Tag.  
> 
> Thanks,
> Daniil
> 
> Changelog:
> 
> v4
> Provided more comments on the code and corrected functions name.
> Created helper function for reading base memory address from BAR.
> Added stepping through ACPI address space descriptor until End Tag.
> 
> v3
> Changed code structure per Leif Lindholm's request
> 
> v2
> Corrected style issues and code structure.
> 
> v1
> The patch reads a valid MAC address form the Juno IOFPGA registers 
> and pushes it into onboard Marvell Yukon NIC.
> 
>  .../ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c     | 289 +++++++++++++++++++++
>  .../Drivers/ArmJunoDxe/ArmJunoDxeInternal.h        |  13 +
>  2 files changed, 302 insertions(+)
> 
> diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
> index b97f044..5847d0a 100644
> --- a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
> +++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c
> @@ -15,7 +15,9 @@
>  #include "ArmJunoDxeInternal.h"
>  #include <ArmPlatform.h>
>  
> +#include <IndustryStandard/Pci.h>
>  #include <Protocol/DevicePathFromText.h>
> +#include <Protocol/PciIo.h>
>  #include <Protocol/PciRootBridgeIo.h>
>  
>  #include <Guid/EventGroup.h>
> @@ -69,6 +71,290 @@ STATIC CONST EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mPciRootComplexDevicePath = {
>  EFI_EVENT mAcpiRegistration = NULL;
>  
>  /**
> +  This function reads PCI ID of the controller.
> +
> +  @param[in]  PciIo   PCI IO protocol handle
> +  @param[in]  PciId   Looking for specified PCI ID Vendor/Device
> +**/
> +STATIC
> +EFI_STATUS
> +ReadMarvellYoukonPciId (
> +  IN EFI_PCI_IO_PROTOCOL  *PciIo,
> +  IN UINT32               PciId
> +  )
> +{
> +  UINT32      DevicePciId;
> +  EFI_STATUS  Status;
> +
> +  Status = PciIo->Pci.Read (
> +                        PciIo,
> +                        EfiPciIoWidthUint32,
> +                        PCI_VENDOR_ID_OFFSET,
> +                        1,
> +                        &DevicePciId);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (DevicePciId != PciId) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function searches for Marvell Yukon NIC on the Juno
> +  platform and returns PCI IO protocol handle for the controller.
> +
> +  @param[out]  PciIo   PCI IO protocol handle
> +**/
> +STATIC
> +EFI_STATUS
> +GetMarvellYukonPciIoProtocol (
> +  OUT EFI_PCI_IO_PROTOCOL  **PciIo
> +  )
> +{
> +  UINTN       HandleCount;
> +  EFI_HANDLE  *HandleBuffer;
> +  UINTN       HIndex;
> +  EFI_STATUS  Status;
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiPciIoProtocolGuid,
> +                  NULL,
> +                  &HandleCount,
> +                  &HandleBuffer);
> +  if (EFI_ERROR (Status)) {
> +    return (Status);
> +  }
> +
> +  for (HIndex = 0; HIndex < HandleCount; ++HIndex) {
> +    // If PciIo opened with EFI_OPEN_PROTOCOL_GET_PROTOCOL, the CloseProtocol() is not required
> +    Status = gBS->OpenProtocol (
> +                    HandleBuffer[HIndex],
> +                    &gEfiPciIoProtocolGuid,
> +                    (VOID **) PciIo,
> +                    NULL,
> +                    NULL,
> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +
> +    Status = ReadMarvellYoukonPciId (*PciIo, JUNO_MARVELL_YUKON_ID);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    } else {
> +      break;
> +    }
> +  }
> +
> +  gBS->FreePool (HandleBuffer);
> +
> +  return Status;
> +}
> +
> +/**
> + This function restore the original controller attributes
> +
> +   @param[in]   PciIo               PCI IO protocol handle
> +   @param[in]   PciAttr             PCI controller attributes.
> +   @param[in]   AcpiResDescriptor   ACPI 2.0 resource descriptors for the BAR
> +**/
> +STATIC
> +VOID
> +RestorePciDev (
> +  IN EFI_PCI_IO_PROTOCOL                *PciIo,
> +  IN UINT64                             PciAttr
> +  )
> +{
> +  PciIo->Attributes (
> +           PciIo,
> +           EfiPciIoAttributeOperationSet,
> +           PciAttr,
> +           NULL
> +           );
> +}
> +
> +/**
> + This function returns PCI MMIO base address for a controller
> +
> +   @param[in]   PciIo               PCI IO protocol handle
> +   @param[out]  PciRegBase          PCI base MMIO address
> +**/
> +STATIC
> +EFI_STATUS
> +BarIsDeviceMemory (
> +  IN   EFI_PCI_IO_PROTOCOL *PciIo,
> +  OUT  UINT32              *PciRegBase
> +  )
> +{
> +  EFI_STATUS                         Status;
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *AcpiResDescriptor;
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *AcpiCurrentDescriptor;
> +
> +  // Marvell Yukon's Bar0 provides base memory address for control registers
> +  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX0, NULL, (VOID**)&AcpiResDescriptor);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  AcpiCurrentDescriptor = AcpiResDescriptor;
> +
> +  // Search for a memory type descriptor
> +  while (AcpiCurrentDescriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
> +
> +    // Check if Bar is memory type one and fetch a base address
> +    if (AcpiCurrentDescriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR &&
> +        AcpiCurrentDescriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM &&
> +        !(AcpiCurrentDescriptor->SpecificFlag & ACPI_SPECFLAG_PREFETCHABLE)) {
> +      *PciRegBase = AcpiCurrentDescriptor->AddrRangeMin;
> +      break;
> +    } else {
> +      Status = EFI_UNSUPPORTED;
> +    }
> +
> +    AcpiCurrentDescriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (AcpiCurrentDescriptor + 1);
> +  }
> +
> +  gBS->FreePool (AcpiResDescriptor);
> +
> +  return Status;
> +}
> +
> +/**
> + This function provides PCI MMIO base address, old PCI controller attributes.
> +
> +   @param[in]   PciIo               PCI IO protocol handle
> +   @param[out]  PciRegBase          PCI base MMIO address
> +   @param[out]  OldPciAttr          Old PCI controller attributes.
> +**/
> +STATIC
> +EFI_STATUS
> +InitPciDev (
> +  IN EFI_PCI_IO_PROTOCOL                 *PciIo,
> +  OUT UINT32                             *PciRegBase,
> +  OUT UINT64                             *OldPciAttr
> +  )
> +{
> +  UINT64      AttrSupports;
> +  EFI_STATUS  Status;
> +
> +  // Get controller's current attributes
> +  Status = PciIo->Attributes (
> +                    PciIo,
> +                    EfiPciIoAttributeOperationGet,
> +                    0,
> +                    OldPciAttr);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // Fetch supported attributes
> +  Status = PciIo->Attributes (
> +                    PciIo,
> +                    EfiPciIoAttributeOperationSupported,
> +                    0,
> +                    &AttrSupports);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  // Enable EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY and
> +  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER bits in the PCI Config Header
> +  AttrSupports &= EFI_PCI_DEVICE_ENABLE;
> +  Status = PciIo->Attributes (
> +                    PciIo,
> +                    EfiPciIoAttributeOperationEnable,
> +                    AttrSupports,
> +                    NULL);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = BarIsDeviceMemory (PciIo, PciRegBase);
> +  if (EFI_ERROR (Status)) {
> +    RestorePciDev (PciIo, *OldPciAttr);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> + This function reads MAC address from IOFPGA and writes it to Marvell Yukon NIC
> +
> +   @param[in]   PciRegBase   PCI base MMIO address
> +**/
> +STATIC
> +EFI_STATUS
> +WriteMacAddress (
> +  IN UINT32  PciRegBase
> +  )
> +{
> +  UINT32  MacHigh;
> +  UINT32  MacLow;
> +
> +  // Read MAC address from IOFPGA
> +  MacHigh= MmioRead32 (ARM_JUNO_SYS_PCIGBE_H);
> +  MacLow = MmioRead32 (ARM_JUNO_SYS_PCIGBE_L);
> +
> +  // Set software reset control register to protect from deactivation
> +  // the config write state
> +  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_CLR);
> +
> +  // Convert to Marvell MAC Address register format
> +  MacHigh = SwapBytes32 ((MacHigh & 0xFFFF) << 16 |
> +                         (MacLow & 0xFFFF0000) >> 16);
> +  MacLow = SwapBytes32 (MacLow) >> 16;
> +
> +  // Set MAC Address
> +  MmioWrite8 (PciRegBase + R_TST_CTRL_1, TST_CFG_WRITE_ENABLE);
> +  MmioWrite32 (PciRegBase + R_MAC, MacHigh);
> +  MmioWrite32 (PciRegBase + R_MAC_MAINT, MacHigh);
> +  MmioWrite32 (PciRegBase + R_MAC + R_MAC_LOW, MacLow);
> +  MmioWrite32 (PciRegBase + R_MAC_MAINT + R_MAC_LOW, MacLow);
> +  MmioWrite8 (PciRegBase + R_TST_CTRL_1, TST_CFG_WRITE_DISABLE);
> +
> +  // Initiate device reset
> +  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_SET);
> +  MmioWrite16 (PciRegBase + R_CONTROL_STATUS, CS_RESET_CLR);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  The function reads MAC address from Juno IOFPGA registers and writes it
> +  into Marvell Yukon NIC.
> +**/
> +STATIC
> +EFI_STATUS
> +ArmJunoSetNicMacAddress ()
> +{
> +  UINT64                              OldPciAttr;
> +  EFI_PCI_IO_PROTOCOL*                PciIo;
> +  UINT32                              PciRegBase;
> +  EFI_STATUS                          Status;
> +
> +  Status = GetMarvellYukonPciIoProtocol (&PciIo);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = InitPciDev (PciIo, &PciRegBase, &OldPciAttr);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = WriteMacAddress (PciRegBase);
> +
> +  RestorePciDev (PciIo, OldPciAttr);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
>    Notification function of the event defined as belonging to the
>    EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in
>    the entry point of the driver.
> @@ -106,6 +392,9 @@ OnEndOfDxe (
>  
>    Status = gBS->ConnectController (Handle, NULL, PciRootComplexDevicePath, FALSE);
>    ASSERT_EFI_ERROR (Status);
> +
> +  Status = ArmJunoSetNicMacAddress ();
> +  ASSERT_EFI_ERROR (Status);
>  }
>  
>  STATIC
> diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
> index 662c413..df02770 100644
> --- a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
> +++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxeInternal.h
> @@ -29,6 +29,19 @@
>  
>  #include <IndustryStandard/Acpi.h>
>  
> +#define ACPI_SPECFLAG_PREFETCHABLE    0x06
> +#define JUNO_MARVELL_YUKON_ID         0x438011AB /* Juno Marvell PCI Dev ID */
> +#define TST_CFG_WRITE_ENABLE          0x02       /* Enable Config Write */
> +#define TST_CFG_WRITE_DISABLE         0x00       /* Disable Config Write */
> +#define CS_RESET_CLR                  0x02       /* SW Reset Clear */
> +#define CS_RESET_SET                  0x00       /* SW Reset Set */
> +#define R_CONTROL_STATUS              0x0004     /* Control/Status Register */
> +#define R_MAC                         0x0100     /* MAC Address */
> +#define R_MAC_MAINT                   0x0110     /* MAC Address Maintenance */
> +#define R_MAC_LOW                     0x04       /* MAC Address Low Register Offset */
> +#define R_TST_CTRL_1                  0x0158     /* Test Control Register 1 */
> +
> +
>  EFI_STATUS
>  PciEmulationEntryPoint (
>    VOID
> -- 
> 2.7.4
> 


  reply	other threads:[~2017-01-10 22:36 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-09 21:20 [PATCH v4] ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe: Set Marvell Yukon MAC address Daniil Egranov
2017-01-10 22:36 ` Leif Lindholm [this message]
2017-01-11 11:45   ` Ryan Harkin
2017-01-11 12:24     ` Ryan Harkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170110223609.GC24544@bivouac.eciton.net \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox