PHY Integration Guide

Table of Contents

Introduction

The PHY driver is a submodule of the CPSW low-level driver (LLD) dedicated to Ethernet PHY management. It implements a state machine required to handle the lifecycle of PHYs, from initialization to link establishment.

The PHY submodule interacts with the MDIO submodule to perform operations like detecting alive and/or linked PHYs, and for PHY register accesses. The relationship between PHY, MDIO and CPSW integration layer is shown below.

CPSW-LLD_Block_Diagram.png
CPSW Low-Level Driver Block Diagram

Currently, the PHY driver supports only Clause-22 devices. Clause-45 devices are not supported.

PHY Driver

The top-layer of PHY driver is located at <CPSW_LLD>/src/cpsw_phy.c. This layer implements the basic APIs that are needed to communicate with the CPSW integration layer, namely CpswPhy_open(), CpswPhy_ioctl() and CpswPhy_close().

The CPSW_LLD is capable of supporting multiple PHYs running simultaneously; each PHY has its own driver instance, its own state machine and hence will follow independent lifecycle from other PHYs.

The lifecycle of the PHYs is handled by the PHY driver via a state machine implementation. This state machine is composed of the following states:

The diagram in the figure below provides a simplified view of the state transitions of the PHY state machine.

PHY_FSM_SimplifiedView.png
Simplified View of PHY State Machine

Refer to Appendix A for a more detailed view of the PHY state machine.

Device-Specific Drivers

The PHY driver model has been designed to partition device-specific operations from device-agnostic common operations. The former are implemented by PHY device specific drivers, while the latter can be carried out directly by the main PHY driver.

This model facilitates the addition of new drivers for PHY devices not yet supported in the CPSW_LLD. The CpswPhy_Drv structure is defined as the interface that device specific drivers must implement. Since this structure is not exposed to the application, its scope is internal to the CPSW LLD.

CpswPhy_Drv.png
CPSW PHY Driver Interface

The members of the CpswPhy_Drv structure can be mandatory or optional in nature. Optional members can be set to NULL if the PHY doesn't provide an implementation for them. The list below provides a description of the purpose of each CpswPhy_Drv member.

The current version of CPSW LLD includes two PHY drivers: generic PHY and DP83867.

The generic PHY driver is a special case because its implementation is limited to IEEE-Standard MII registers. Reuse of PHY generic function by other device-specific drivers is possible when their CpswPhy_Drv implementation doesn't deviate from standard. The diagram in figure below shows the reuse of extended register read/write functions by the DP83867 driver.

CpswPhy_Drv_Hierarchy.png
CPSW PHY Driver Hierarchy

Device specific drivers can be found at <CPSW_LLD>/src/phy/*.

PHY to Driver Binding

The PHY-to-driver binding is the process of selecting the best driver for a PHY device based on the device's unique identifier. This process is done by the main PHY driver upon alive detection of a PHY device and takes place in the FINDING state.

The device unique identifier is read from PHYIDR1 and PHYIDR2 registers and populated into a structure of type CpswPhy_Version.

CpswPhy_Version.png
CPSW PHY Version

The main PHY driver has a CpswPhy_drvs array which contains all device specific drivers that are registered and that will participate in the search for the best driver for the PHY that had been recently discovered.

static CpswPhyDrv_Handle CpswPhy_drvs[] =
{
&Dp83867_phyDrv, /* DP83867 */
&GenericPhy_phyDrv, /* Generic PHY must be last */
};

In the search process, the main PHY driver will call the isPhyDevSupported() function of each registered driver. The drivers will use the CpswPhy_Version which is passed as an argument in order to determine whether the device is supported or not. If it is, isPhyDevSupported() must return true and the search process ends. If not, the search continues with the next registered device.

The generic PHY (which must be the last one in the CpswPhy_drvs array) will be bound to the device if no other driver can support a given PHY, but the PHY full functionality can't be guaranteed.

Implementing a New PHY Driver

The following list of steps is provided as guideline when adding a new PHY driver for a device which is not supported by CPSW LLD.

CswPhy_Drv MyPhy_phyDrv =
{
.name = "My PHY driver",
.isPhyDevSupported = MyPhy_isPhyDevSupported,
.isMacModeSupported = MyPhy_isMacModeSupported,
.config = MyPhy_config,
.reset = MyPhy_reset,
.isResetComplete = MyPhy_isResetComplete,
.runComplianceTest = NULL,
.readExtReg = GenericPhy_readExtReg,
.writeExtReg = GenericPhy_writeExtReg,
.printRegs = MyPhy_printRegs,
};
extern CpswPhy_Drv GenericPhy_phyDrv;
extern CpswPhy_Drv Dp83867_phyDrv;
extern CpswPhy_Drv MyPhy_phyDrv;
static CpswPhyDrv_Handle CpswPhy_drvs[] =
{
&GenericPhy_phyDrv, /* My PHY driver */
&Dp83867_phyDrv, /* DP83867 */
&GenericPhy_phyDrv, /* Generic PHY must be last */
};
# Common source files and CFLAGS across all platforms and cores
SRCS_COMMON += cpsw.c
SRCS_COMMON += cpsw_ale.c cpsw_hostport.c cpsw_macport.c cpsw_mdio.c
SRCS_COMMON += cpsw_stats.c cpsw_cpts.c
SRCS_COMMON += cpsw_soc.c cpsw_rmcfg.c cpsw_osal.c cpsw_utils.c
SRCS_COMMON += cpsw_dma.c cpsw_dma_priv.c cpsw_queue.c cpsw_rm.c
SRCS_COMMON += cpsw_phy.c generic_phy.c dp83867.c
SRCS_COMMON += cpsw_trace.c

Appendix

Appendix A

Detailed view of the PHY state machine.

PHY_FSM.png
Detailed View of PHY State Machine

Copyright 2020, Texas Instruments Incorporated