summaryrefslogtreecommitdiff
path: root/Platform/Marvell/Drivers/Net/Phy
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Marvell/Drivers/Net/Phy')
-rw-r--r--Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c438
-rw-r--r--Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h194
-rw-r--r--Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf71
3 files changed, 703 insertions, 0 deletions
diff --git a/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c b/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c
new file mode 100644
index 0000000000..aeb6f7a01b
--- /dev/null
+++ b/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c
@@ -0,0 +1,438 @@
+/********************************************************************************
+Copyright (C) 2016 Marvell International Ltd.
+
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Marvell nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <Protocol/DriverBinding.h>
+#include <Protocol/Mdio.h>
+#include <Protocol/MvPhy.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "MvPhyDxe.h"
+
+#define TIMEOUT 500
+
+STATIC MARVELL_MDIO_PROTOCOL *Mdio;
+
+STATIC MV_PHY_DEVICE MvPhyDevices[] = {
+ { MV_PHY_DEVICE_1512, MvPhyInit1512 },
+ { 0, NULL }
+};
+
+EFI_STATUS
+MvPhyStatus (
+ IN CONST MARVELL_PHY_PROTOCOL *This,
+ IN PHY_DEVICE *PhyDev
+ );
+
+EFI_STATUS
+MvPhyReset (
+ IN UINT32 PhyAddr
+ )
+{
+ UINT32 Reg = 0;
+ INTN timeout = TIMEOUT;
+
+ Mdio->Read(Mdio, PhyAddr, MII_BMCR, &Reg);
+ Reg |= BMCR_RESET;
+ Mdio->Write(Mdio, PhyAddr, MII_BMCR, Reg);
+
+ while ((Reg & BMCR_RESET) && timeout--) {
+ Mdio->Read(Mdio, PhyAddr, MII_BMCR, &Reg);
+ gBS->Stall(1000);
+ }
+
+ if (Reg & BMCR_RESET) {
+ DEBUG((DEBUG_ERROR, "PHY reset timed out\n"));
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/* Marvell 88E1111S */
+EFI_STATUS
+MvPhyM88e1111sConfig (
+ IN PHY_DEVICE *PhyDev
+ )
+{
+ UINT32 Reg;
+
+ if ((PhyDev->Connection == PHY_CONNECTION_RGMII) ||
+ (PhyDev->Connection == PHY_CONNECTION_RGMII_ID) ||
+ (PhyDev->Connection == PHY_CONNECTION_RGMII_RXID) ||
+ (PhyDev->Connection == PHY_CONNECTION_RGMII_TXID)) {
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_CR, &Reg);
+
+ if ((PhyDev->Connection == PHY_CONNECTION_RGMII) ||
+ (PhyDev->Connection == PHY_CONNECTION_RGMII_ID)) {
+ Reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY);
+ } else if (PhyDev->Connection == PHY_CONNECTION_RGMII_RXID) {
+ Reg &= ~MIIM_88E1111_TX_DELAY;
+ Reg |= MIIM_88E1111_RX_DELAY;
+ } else if (PhyDev->Connection == PHY_CONNECTION_RGMII_TXID) {
+ Reg &= ~MIIM_88E1111_RX_DELAY;
+ Reg |= MIIM_88E1111_TX_DELAY;
+ }
+
+ Mdio->Write(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_CR, Reg);
+
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, &Reg);
+
+ Reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK);
+
+ if (Reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES)
+ Reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII;
+ else
+ Reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII;
+
+ Mdio->Write(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, Reg);
+ }
+
+ if (PhyDev->Connection == PHY_CONNECTION_SGMII) {
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, &Reg);
+
+ Reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK);
+ Reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK;
+ Reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
+
+ Mdio->Write(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, Reg);
+ }
+
+ if (PhyDev->Connection == PHY_CONNECTION_RTBI) {
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_CR, &Reg);
+ Reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY);
+ Mdio->Write(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_CR, Reg);
+
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, &Reg);
+ Reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK |
+ MIIM_88E1111_HWCFG_FIBER_COPPER_RES);
+ Reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
+ Mdio->Write(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, Reg);
+
+ /* Soft reset */
+ MvPhyReset(PhyDev->Addr);
+
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, &Reg);
+ Reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK |
+ MIIM_88E1111_HWCFG_FIBER_COPPER_RES);
+ Reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI |
+ MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
+ Mdio->Write(Mdio, PhyDev->Addr, MIIM_88E1111_PHY_EXT_SR, Reg);
+ }
+
+ Mdio->Read(Mdio, PhyDev->Addr, MII_BMCR, &Reg);
+ Reg |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ Reg &= ~BMCR_ISOLATE;
+ Mdio->Write(Mdio, PhyDev->Addr, MII_BMCR, Reg);
+
+ /* Soft reset */
+ MvPhyReset(PhyDev->Addr);
+
+ MvPhyReset(PhyDev->Addr);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MvPhyParseStatus (
+ IN PHY_DEVICE *PhyDev
+ )
+{
+ UINT32 Data;
+ UINT32 Speed;
+
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1xxx_PHY_STATUS, &Data);
+
+ if ((Data & MIIM_88E1xxx_PHYSTAT_LINK) &&
+ !(Data & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
+ INTN i = 0;
+
+ DEBUG((DEBUG_ERROR,"MvPhyDxe: Waiting for PHY realtime link"));
+ while (!(Data & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
+ if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+ DEBUG((DEBUG_ERROR," TIMEOUT !\n"));
+ PhyDev->LinkUp = FALSE;
+ break;
+ }
+
+ if ((i++ % 1000) == 0)
+ DEBUG((DEBUG_ERROR, "."));
+ gBS->Stall(1000);
+ Mdio->Read(Mdio, PhyDev->Addr, MIIM_88E1xxx_PHY_STATUS, &Data);
+ }
+ DEBUG((DEBUG_ERROR," done\n"));
+ gBS->Stall(500000);
+ } else {
+ if (Data & MIIM_88E1xxx_PHYSTAT_LINK) {
+ DEBUG((DEBUG_ERROR, "MvPhyDxe: link up, "));
+ PhyDev->LinkUp = TRUE;
+ } else {
+ DEBUG((DEBUG_ERROR, "MvPhyDxe: link down, "));
+ PhyDev->LinkUp = FALSE;
+ }
+ }
+
+ if (Data & MIIM_88E1xxx_PHYSTAT_DUPLEX) {
+ DEBUG((DEBUG_ERROR, "full duplex, "));
+ PhyDev->FullDuplex = TRUE;
+ } else {
+ DEBUG((DEBUG_ERROR, "half duplex, "));
+ PhyDev->FullDuplex = FALSE;
+ }
+
+ Speed = Data & MIIM_88E1xxx_PHYSTAT_SPEED;
+
+ switch (Speed) {
+ case MIIM_88E1xxx_PHYSTAT_GBIT:
+ DEBUG((DEBUG_ERROR, "speed 1000\n"));
+ PhyDev->Speed = SPEED_1000;
+ break;
+ case MIIM_88E1xxx_PHYSTAT_100:
+ DEBUG((DEBUG_ERROR, "speed 100\n"));
+ PhyDev->Speed = SPEED_100;
+ break;
+ default:
+ DEBUG((DEBUG_ERROR, "speed 10\n"));
+ PhyDev->Speed = SPEED_10;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+MvPhy1512WriteBits (
+ IN UINT32 PhyAddr,
+ IN UINT8 RegNum,
+ IN UINT16 Offset,
+ IN UINT16 Len,
+ IN UINT16 Data)
+{
+ UINT32 Reg, Mask;
+
+ if ((Len + Offset) >= 16)
+ Mask = 0 - (1 << Offset);
+ else
+ Mask = (1 << (Len + Offset)) - (1 << Offset);
+
+ Mdio->Read(Mdio, PhyAddr, RegNum, &Reg);
+
+ Reg &= ~Mask;
+ Reg |= Data << Offset;
+
+ Mdio->Write(Mdio, PhyAddr, RegNum, Reg);
+}
+
+STATIC
+EFI_STATUS
+MvPhyInit1512 (
+ IN CONST MARVELL_PHY_PROTOCOL *Snp,
+ IN UINT32 PhyAddr,
+ IN OUT PHY_DEVICE *PhyDev
+ )
+{
+ UINT32 Data;
+ INTN i;
+
+ if (PhyDev->Connection == PHY_CONNECTION_SGMII) {
+ /* Select page 0xff and update configuration registers according to
+ * Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 Rev A0,
+ * Errata Section 3.1 - needed in SGMII mode.
+ */
+ Mdio->Write(Mdio, PhyAddr, 22, 0x00ff);
+ Mdio->Write(Mdio, PhyAddr, 17, 0x214B);
+ Mdio->Write(Mdio, PhyAddr, 16, 0x2144);
+ Mdio->Write(Mdio, PhyAddr, 17, 0x0C28);
+ Mdio->Write(Mdio, PhyAddr, 16, 0x2146);
+ Mdio->Write(Mdio, PhyAddr, 17, 0xB233);
+ Mdio->Write(Mdio, PhyAddr, 16, 0x214D);
+ Mdio->Write(Mdio, PhyAddr, 17, 0xCC0C);
+ Mdio->Write(Mdio, PhyAddr, 16, 0x2159);
+
+ /* Reset page selection and select page 0x12 */
+ Mdio->Write(Mdio, PhyAddr, 22, 0x0000);
+ Mdio->Write(Mdio, PhyAddr, 22, 0x0012);
+
+ /* Write HWCFG_MODE = SGMII to Copper */
+ MvPhy1512WriteBits(PhyAddr, 20, 0, 3, 1);
+
+ /* Phy reset - necessary after changing mode */
+ MvPhy1512WriteBits(PhyAddr, 20, 15, 1, 1);
+
+ /* Reset page selection */
+ Mdio->Write(Mdio, PhyAddr, 22, 0x0000);
+ gBS->Stall(100);
+ }
+
+ MvPhyM88e1111sConfig (PhyDev);
+
+ /* autonegotiation on startup is not always required */
+ if (!PcdGetBool (PcdPhyStartupAutoneg))
+ return EFI_SUCCESS;
+
+ Mdio->Read(Mdio, PhyAddr, MII_BMSR, &Data);
+
+ if ((Data & BMSR_ANEGCAPABLE) && !(Data & BMSR_ANEGCOMPLETE)) {
+
+ DEBUG((DEBUG_ERROR, "MvPhyDxe: Waiting for PHY auto negotiation... "));
+ for (i = 0; !(Data & BMSR_ANEGCOMPLETE); i++) {
+ if (i > PHY_ANEG_TIMEOUT) {
+ DEBUG((DEBUG_ERROR, "timeout\n"));
+ PhyDev->LinkUp = FALSE;
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall(1000); /* 1 ms */
+ Mdio->Read(Mdio, PhyAddr, MII_BMSR, &Data);
+ }
+ PhyDev->LinkUp = TRUE;
+ DEBUG((DEBUG_INFO, "MvPhyDxe: link up\n"));
+ } else {
+ Mdio->Read(Mdio, PhyAddr, MII_BMSR, &Data);
+
+ if (Data & BMSR_LSTATUS) {
+ PhyDev->LinkUp = TRUE;
+ DEBUG((DEBUG_INFO, "MvPhyDxe: link up\n"));
+ } else {
+ PhyDev->LinkUp = FALSE;
+ DEBUG((DEBUG_INFO, "MvPhyDxe: link down\n"));
+ }
+ }
+ MvPhyParseStatus (PhyDev);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MvPhyInit (
+ IN CONST MARVELL_PHY_PROTOCOL *Snp,
+ IN UINT32 PhyAddr,
+ IN PHY_CONNECTION PhyConnection,
+ IN OUT PHY_DEVICE **OutPhyDev
+ )
+{
+ EFI_STATUS Status;
+ PHY_DEVICE *PhyDev;
+ UINT8 *DeviceIds;
+ INTN i;
+
+ Status = gBS->LocateProtocol (
+ &gMarvellMdioProtocolGuid,
+ NULL,
+ (VOID **) &Mdio
+ );
+ if (EFI_ERROR(Status))
+ return Status;
+
+ /* perform setup common for all PHYs */
+ PhyDev = AllocateZeroPool (sizeof (PHY_DEVICE));
+ PhyDev->Addr = PhyAddr;
+ PhyDev->Connection = PhyConnection;
+ DEBUG((DEBUG_INFO, "MvPhyDxe: PhyAddr is %d, connection %d\n",
+ PhyAddr, PhyConnection));
+ *OutPhyDev = PhyDev;
+
+ DeviceIds = PcdGetPtr (PcdPhyDeviceIds);
+ for (i = 0; i < PcdGetSize (PcdPhyDeviceIds); i++) {
+ /* find MvPhyDevices fitting entry */
+ if (MvPhyDevices[i].DevId == DeviceIds[i]) {
+ ASSERT (MvPhyDevices[i].DevInit != NULL);
+ /* proceed with PHY-specific initialization */
+ return MvPhyDevices[i].DevInit(Snp, PhyAddr, PhyDev);
+ }
+ }
+
+ /* if we are here, no matching DevId was found */
+ Status = EFI_INVALID_PARAMETER;
+ FreePool (PhyDev);
+ return Status;
+}
+
+EFI_STATUS
+MvPhyStatus (
+ IN CONST MARVELL_PHY_PROTOCOL *This,
+ IN PHY_DEVICE *PhyDev
+ )
+{
+ UINT32 Data;
+
+ Mdio->Read(Mdio, PhyDev->Addr, MII_BMSR, &Data);
+ Mdio->Read(Mdio, PhyDev->Addr, MII_BMSR, &Data);
+
+ if ((Data & BMSR_LSTATUS) == 0) {
+ PhyDev->LinkUp = FALSE;
+ } else {
+ PhyDev->LinkUp = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+MvPhyDxeInitialise (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ MARVELL_PHY_PROTOCOL *Phy;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ Phy = AllocateZeroPool (sizeof (MARVELL_PHY_PROTOCOL));
+ Phy->Status = MvPhyStatus;
+ Phy->Init = MvPhyInit;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gMarvellPhyProtocolGuid, Phy,
+ NULL
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "Failed to install interfaces\n"));
+ return Status;
+ }
+ DEBUG((DEBUG_ERROR, "Succesfully installed protocol interfaces\n"));
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h b/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h
new file mode 100644
index 0000000000..6bd06c52ed
--- /dev/null
+++ b/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h
@@ -0,0 +1,194 @@
+/********************************************************************************
+Copyright (C) 2016 Marvell International Ltd.
+
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of Marvell nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+#ifndef __MV_PHY_DXE_H__
+#define __MV_PHY_DXE_H__
+
+#define MII_BMCR 0x00 /* Basic mode control Register */
+#define MII_BMSR 0x01 /* Basic mode status Register */
+#define MII_PHYSID1 0x02 /* PHYS ID 1 */
+#define MII_PHYSID2 0x03 /* PHYS ID 2 */
+#define MII_ADVERTISE 0x04 /* Advertisement control Reg */
+#define MII_LPA 0x05 /* Link partner ability Reg */
+#define MII_EXPANSION 0x06 /* Expansion Register */
+#define MII_CTRL1000 0x09 /* 1000BASE-T control */
+#define MII_STAT1000 0x0a /* 1000BASE-T status */
+#define MII_ESTATUS 0x0f /* Extended Status */
+#define MII_DCOUNTER 0x12 /* Disconnect counter */
+#define MII_FCSCOUNTER 0x13 /* False carrier counter */
+#define MII_NWAYTEST 0x14 /* N-way auto-neg test Reg */
+#define MII_RERRCOUNTER 0x15 /* Receive error counter */
+#define MII_SREVISION 0x16 /* Silicon revision */
+#define MII_RESV1 0x17 /* Reserved... */
+#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
+#define MII_PHYADDR 0x19 /* PHY address */
+#define MII_RESV2 0x1a /* Reserved... */
+#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
+#define MII_NCONFIG 0x1c /* Network interface config */
+
+/* Basic mode control Register. */
+#define BMCR_RESV 0x003f /* Unused... */
+#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
+#define BMCR_CTST 0x0080 /* Collision test */
+#define BMCR_FULLDPLX 0x0100 /* Full duplex */
+#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
+#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
+#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
+#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
+#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
+#define BMCR_RESET 0x8000 /* Reset the DP83840 */
+
+/* Basic mode status Register. */
+#define BMSR_ERCAP 0x0001 /* Ext-Reg capability */
+#define BMSR_JCD 0x0002 /* Jabber detected */
+#define BMSR_LSTATUS 0x0004 /* Link status */
+#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
+#define BMSR_RFAULT 0x0010 /* Remote fault detected */
+#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
+#define BMSR_RESV 0x00c0 /* Unused... */
+#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
+#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
+#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
+#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
+#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
+#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
+
+#define PHY_ANEG_TIMEOUT 4000
+
+#define PHY_INTERFACE_MODE_RGMII 0
+#define PHY_INTERFACE_MODE_RGMII_ID 1
+#define PHY_INTERFACE_MODE_RGMII_RXID 2
+#define PHY_INTERFACE_MODE_RGMII_TXID 3
+#define PHY_INTERFACE_MODE_SGMII 4
+#define PHY_INTERFACE_MODE_RTBI 5
+
+#define PHY_AUTONEGOTIATE_TIMEOUT 5000
+
+/* 88E1011 PHY Status Register */
+#define MIIM_88E1xxx_PHY_STATUS 0x11
+#define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000
+#define MIIM_88E1xxx_PHYSTAT_GBIT 0x8000
+#define MIIM_88E1xxx_PHYSTAT_100 0x4000
+#define MIIM_88E1xxx_PHYSTAT_DUPLEX 0x2000
+#define MIIM_88E1xxx_PHYSTAT_SPDDONE 0x0800
+#define MIIM_88E1xxx_PHYSTAT_LINK 0x0400
+
+#define MIIM_88E1xxx_PHY_SCR 0x10
+#define MIIM_88E1xxx_PHY_MDI_X_AUTO 0x0060
+
+/* 88E1111 PHY LED Control Register */
+#define MIIM_88E1111_PHY_LED_CONTROL 24
+#define MIIM_88E1111_PHY_LED_DIRECT 0x4100
+#define MIIM_88E1111_PHY_LED_COMBINE 0x411C
+
+/* 88E1111 Extended PHY Specific Control Register */
+#define MIIM_88E1111_PHY_EXT_CR 0x14
+#define MIIM_88E1111_RX_DELAY 0x80
+#define MIIM_88E1111_TX_DELAY 0x2
+
+/* 88E1111 Extended PHY Specific Status Register */
+#define MIIM_88E1111_PHY_EXT_SR 0x1b
+#define MIIM_88E1111_HWCFG_MODE_MASK 0xf
+#define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII 0xb
+#define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII 0x3
+#define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK 0x4
+#define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI 0x9
+#define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO 0x8000
+#define MIIM_88E1111_HWCFG_FIBER_COPPER_RES 0x2000
+
+#define MIIM_88E1111_COPPER 0
+#define MIIM_88E1111_FIBER 1
+
+/* 88E1118 PHY defines */
+#define MIIM_88E1118_PHY_PAGE 22
+#define MIIM_88E1118_PHY_LED_PAGE 3
+
+/* 88E1121 PHY LED Control Register */
+#define MIIM_88E1121_PHY_LED_CTRL 16
+#define MIIM_88E1121_PHY_LED_PAGE 3
+#define MIIM_88E1121_PHY_LED_DEF 0x0030
+
+/* 88E1121 PHY IRQ Enable/Status Register */
+#define MIIM_88E1121_PHY_IRQ_EN 18
+#define MIIM_88E1121_PHY_IRQ_STATUS 19
+
+#define MIIM_88E1121_PHY_PAGE 22
+
+/* 88E1145 Extended PHY Specific Control Register */
+#define MIIM_88E1145_PHY_EXT_CR 20
+#define MIIM_M88E1145_RGMII_RX_DELAY 0x0080
+#define MIIM_M88E1145_RGMII_TX_DELAY 0x0002
+
+#define MIIM_88E1145_PHY_LED_CONTROL 24
+#define MIIM_88E1145_PHY_LED_DIRECT 0x4100
+
+#define MIIM_88E1145_PHY_PAGE 29
+#define MIIM_88E1145_PHY_CAL_OV 30
+
+#define MIIM_88E1149_PHY_PAGE 29
+
+/* 88E1310 PHY defines */
+#define MIIM_88E1310_PHY_LED_CTRL 16
+#define MIIM_88E1310_PHY_IRQ_EN 18
+#define MIIM_88E1310_PHY_RGMII_CTRL 21
+#define MIIM_88E1310_PHY_PAGE 22
+
+typedef enum {
+ MV_PHY_DEVICE_1512
+} MV_PHY_DEVICE_ID;
+
+typedef
+EFI_STATUS
+(*MV_PHY_DEVICE_INIT) (
+ IN CONST MARVELL_PHY_PROTOCOL *Snp,
+ IN UINT32 PhyAddr,
+ IN OUT PHY_DEVICE *PhyDev
+ );
+
+typedef struct {
+ MV_PHY_DEVICE_ID DevId;
+ MV_PHY_DEVICE_INIT DevInit;
+} MV_PHY_DEVICE;
+
+STATIC
+EFI_STATUS
+MvPhyInit1512 (
+ IN CONST MARVELL_PHY_PROTOCOL *Snp,
+ IN UINT32 PhyAddr,
+ IN OUT PHY_DEVICE *PhyDev
+ );
+
+#endif
diff --git a/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf b/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf
new file mode 100644
index 0000000000..c262ce42b5
--- /dev/null
+++ b/Platform/Marvell/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf
@@ -0,0 +1,71 @@
+# Copyright (C) 2016 Marvell International Ltd.
+#
+# Marvell BSD License Option
+#
+# If you received this File from Marvell, you may opt to use, redistribute and/or
+# modify this File under the following licensing terms.
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * Neither the name of Marvell nor the names of its contributors may be
+# used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MvPhyDxe
+ FILE_GUID = 5aac3843-d8d4-40ba-ae07-38967138509c
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = MvPhyDxeInitialise
+
+[Sources.common]
+ MvPhyDxe.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Platform/Marvell/Marvell.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gMarvellMdioProtocolGuid
+ gMarvellPhyProtocolGuid
+
+[Pcd]
+ gMarvellTokenSpaceGuid.PcdPhyConnectionTypes
+ gMarvellTokenSpaceGuid.PcdPhyDeviceIds
+ gMarvellTokenSpaceGuid.PcdPhyStartupAutoneg
+
+[Depex]
+ TRUE