From: Bartosz Szczepanek bsz@semihalf.com
MvPhyDxe implements support for Marvell 1512 PHYs. MARVELL_PHY_PROTOCOL is produced in order to provide Status and Initialize functions to network controller drivers. This driver requires MARVELL_MDIO_PROTOCOL to communicate with PHY device.
Several PCDs were added to enable PHY ids and connection types configuration. These are described in attached documentation.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Bartosz Szczepanek bsz@semihalf.com Signed-off-by: Marcin Wojtas mw@semihalf.com --- Documentation/Marvell/PortingGuide/Phy.txt | 45 +++ Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c | 432 +++++++++++++++++++++++++++++ Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h | 194 +++++++++++++ Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf | 71 +++++ Platforms/Marvell/Marvell.dec | 5 + 5 files changed, 747 insertions(+) create mode 100644 Documentation/Marvell/PortingGuide/Phy.txt create mode 100644 Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c create mode 100644 Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h create mode 100644 Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf
diff --git a/Documentation/Marvell/PortingGuide/Phy.txt b/Documentation/Marvell/PortingGuide/Phy.txt new file mode 100644 index 0000000..69dae02 --- /dev/null +++ b/Documentation/Marvell/PortingGuide/Phy.txt @@ -0,0 +1,45 @@ +PHY driver configuration +------------------------ +MvPhyDxe provides basic initialization and status routines for Marvell PHYs. +Currently only 1512 series PHYs are supported. Following PCDs are required: + + gMarvellTokenSpaceGuid.PcdPhyConnectionTypes + (list of values corresponding to PHY_CONNECTION enum) + gMarvellTokenSpaceGuid.PcdPhyStartupAutoneg + (boolean - if true, driver waits for autonegotiation on startup) + gMarvellTokenSpaceGuid.PcdPhyDeviceIds + (list of values corresponding to MV_PHY_DEVICE_ID enum) + +PHY_CONNECTION enum type is defined as follows: + + typedef enum { +0 PHY_CONNECTION_RGMII, +1 PHY_CONNECTION_RGMII_ID, +2 PHY_CONNECTION_RGMII_TXID, +3 PHY_CONNECTION_RGMII_RXID, +4 PHY_CONNECTION_SGMII, +5 PHY_CONNECTION_RTBI, +6 PHY_CONNECTION_XAUI, +7 PHY_CONNECTION_RXAUI + } PHY_CONNECTION; + +MV_PHY_DEVICE_ID: + + typedef enum { +0 MV_PHY_DEVICE_1512, + } MV_PHY_DEVICE_ID; + +It should be extended when adding support for other PHY +models. + +Thus in order to set RGMII for 1st PHY and SGMII for 2nd, PCD should be: + + gMarvellTokenSpaceGuid.PcdPhyConnectionTypes|{ 0x0, 0x4 } + +with disabled autonegotiation: + + gMarvellTokenSpaceGuid.PcdPhyStartupAutoneg|FALSE + +assuming, that PHY models are 1512: + + gMarvellTokenSpaceGuid.PcdPhyDeviceIds|{ 0x0, 0x0 } diff --git a/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c b/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c new file mode 100644 index 0000000..fb96d8b --- /dev/null +++ b/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.c @@ -0,0 +1,432 @@ +/******************************************************************************** +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; + + + /* Phy configuration */ + if (PhyDev->Connection == PHY_CONNECTION_SGMII) { + 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); + 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 */ + MvPhy1512WriteBits(PhyAddr, 20, 15, 1, 1); + Mdio->Write(Mdio, PhyAddr, 22, 0); + 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/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h b/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.h new file mode 100644 index 0000000..6bd06c5 --- /dev/null +++ b/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/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf b/Drivers/Net/Phy/MvPhyDxe/MvPhyDxe.inf new file mode 100644 index 0000000..713eada --- /dev/null +++ b/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 + OpenPlatformPkg/Platforms/Marvell/Marvell.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + IoLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gMarvellMdioProtocolGuid + gMarvellPhyProtocolGuid + +[Pcd] + gMarvellTokenSpaceGuid.PcdPhyConnectionTypes + gMarvellTokenSpaceGuid.PcdPhyDeviceIds + gMarvellTokenSpaceGuid.PcdPhyStartupAutoneg + +[Depex] + TRUE diff --git a/Platforms/Marvell/Marvell.dec b/Platforms/Marvell/Marvell.dec index 9c53b8c..73102ed 100644 --- a/Platforms/Marvell/Marvell.dec +++ b/Platforms/Marvell/Marvell.dec @@ -181,6 +181,11 @@ #MDIO gMarvellTokenSpaceGuid.PcdMdioBaseAddress|0|UINT64|0x3000043
+#PHY + gMarvellTokenSpaceGuid.PcdPhyConnectionTypes|{ 0 }|VOID*|0x3000044 + gMarvellTokenSpaceGuid.PcdPhyDeviceIds|{ 0 }|VOID*|0x3000095 + gMarvellTokenSpaceGuid.PcdPhyStartupAutoneg|FALSE|BOOLEAN|0x3000070 + [Protocols] gMarvellEepromProtocolGuid = { 0xcd728a1f, 0x45b5, 0x4feb, { 0x98, 0xc8, 0x31, 0x3d, 0xa8, 0x11, 0x74, 0x62 }} gMarvellMdioProtocolGuid = { 0x0d728a1f, 0x45b5, 0x4feb, { 0x98, 0xc8, 0x31, 0x3d, 0xa8, 0x11, 0x74, 0x62 }}