This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3352: PHY porting

Part Number: AM3352


Hi Champs:

We are porting the TI DP82825 Phy by using the patch onto DP83822.

Can you guide us where is to open the DP83822 on the Sitara SDK?

I have check the 5.02.10 / 5.03 , there is no DP83822 menuconfig..

BR Rio

  • HI .

       I can add the menu config item for DP82825 in the kernel menuconfig now.

       But, I also need to add it onto the uboot.

       Since our SDK uboot only has the DP83867 in the uboot, I don't have the DP83825 drvier for uboot.

       I know there is DP83822/825 kernel driver like this: https://lkml.org/lkml/2019/3/19/768

       But the driver for uboot vs Kernel is different. See the attached DP83867 driver,

       So, where is the DP83825 uboot Phy driver?

       

    /*
     * Driver for the Texas Instruments DP83867 PHY
     *
     * Copyright (C) 2015 Texas Instruments Inc.
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     */
    
    #include <linux/ethtool.h>
    #include <linux/kernel.h>
    #include <linux/mii.h>
    #include <linux/module.h>
    #include <linux/of.h>
    #include <linux/phy.h>
    
    #include <dt-bindings/net/ti-dp83867.h>
    
    #define DP83867_PHY_ID		0x2000a231
    #define DP83867_DEVADDR		0x1f
    
    #define MII_DP83867_PHYCTRL	0x10
    #define MII_DP83867_MICR	0x12
    #define MII_DP83867_ISR		0x13
    #define DP83867_CTRL		0x1f
    #define DP83867_CFG3		0x1e
    
    /* Extended Registers */
    /* TBD register name to be available in a new revision of the TRM */
    #define DP83867_FLD_THRESH	0x002E
    #define DP83867_CFG4            0x0031
    #define DP83867_RGMIICTL	0x0032
    #define DP83867_STRAP_STS1	0x006E
    #define DP83867_STRAP_STS2	0x006F
    #define DP83867_RGMIIDCTL	0x0086
    #define DP83867_IO_MUX_CFG	0x0170
    
    #define DP83867_SW_RESET	BIT(15)
    #define DP83867_SW_RESTART	BIT(14)
    #define STRAP_STS2_FLD_MASK	BIT(10)
    
    /* MICR Interrupt bits */
    #define MII_DP83867_MICR_AN_ERR_INT_EN		BIT(15)
    #define MII_DP83867_MICR_SPEED_CHNG_INT_EN	BIT(14)
    #define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN	BIT(13)
    #define MII_DP83867_MICR_PAGE_RXD_INT_EN	BIT(12)
    #define MII_DP83867_MICR_AUTONEG_COMP_INT_EN	BIT(11)
    #define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN	BIT(10)
    #define MII_DP83867_MICR_FALSE_CARRIER_INT_EN	BIT(8)
    #define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN	BIT(4)
    #define MII_DP83867_MICR_WOL_INT_EN		BIT(3)
    #define MII_DP83867_MICR_XGMII_ERR_INT_EN	BIT(2)
    #define MII_DP83867_MICR_POL_CHNG_INT_EN	BIT(1)
    #define MII_DP83867_MICR_JABBER_INT_EN		BIT(0)
    
    /* RGMIICTL bits */
    #define DP83867_RGMII_TX_CLK_DELAY_EN		BIT(1)
    #define DP83867_RGMII_RX_CLK_DELAY_EN		BIT(0)
    
    /* STRAP_STS1 bits */
    #define DP83867_STRAP_STS1_RESERVED		BIT(11)
    
    /* PHY CTRL bits */
    #define DP83867_PHYCR_FIFO_DEPTH_SHIFT		14
    #define DP83867_PHYCR_FIFO_DEPTH_MASK		(3 << 14)
    #define DP83867_PHYCR_RESERVED_MASK		BIT(11)
    
    /* RGMIIDCTL bits */
    #define DP83867_RGMII_TX_CLK_DELAY_SHIFT	4
    
    /* IO_MUX_CFG bits */
    #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL	0x1f
    
    #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX	0x0
    #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN	0x1f
    
    /* CFG4 bits */
    #define DP83867_CFG4_PORT_MIRROR_EN              BIT(0)
    
    enum {
    	DP83867_PORT_MIRROING_KEEP,
    	DP83867_PORT_MIRROING_EN,
    	DP83867_PORT_MIRROING_DIS,
    };
    
    struct dp83867_private {
    	int rx_id_delay;
    	int tx_id_delay;
    	int fifo_depth;
    	int io_impedance;
    	int port_mirroring;
    	bool rxctrl_strap_quirk;
    };
    
    static int dp83867_ack_interrupt(struct phy_device *phydev)
    {
    	int err = phy_read(phydev, MII_DP83867_ISR);
    
    	if (err < 0)
    		return err;
    
    	return 0;
    }
    
    static int dp83867_config_intr(struct phy_device *phydev)
    {
    	int micr_status;
    
    	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
    		micr_status = phy_read(phydev, MII_DP83867_MICR);
    		if (micr_status < 0)
    			return micr_status;
    
    		micr_status |=
    			(MII_DP83867_MICR_AN_ERR_INT_EN |
    			MII_DP83867_MICR_SPEED_CHNG_INT_EN |
    			MII_DP83867_MICR_AUTONEG_COMP_INT_EN |
    			MII_DP83867_MICR_LINK_STS_CHNG_INT_EN |
    			MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN |
    			MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN);
    
    		return phy_write(phydev, MII_DP83867_MICR, micr_status);
    	}
    
    	micr_status = 0x0;
    	return phy_write(phydev, MII_DP83867_MICR, micr_status);
    }
    
    static int dp83867_config_port_mirroring(struct phy_device *phydev)
    {
    	struct dp83867_private *dp83867 =
    		(struct dp83867_private *)phydev->priv;
    	u16 val;
    
    	val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
    
    	if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN)
    		val |= DP83867_CFG4_PORT_MIRROR_EN;
    	else
    		val &= ~DP83867_CFG4_PORT_MIRROR_EN;
    
    	phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
    
    	return 0;
    }
    
    #ifdef CONFIG_OF_MDIO
    static int dp83867_of_init(struct phy_device *phydev)
    {
    	struct dp83867_private *dp83867 = phydev->priv;
    	struct device *dev = &phydev->mdio.dev;
    	struct device_node *of_node = dev->of_node;
    	int ret;
    
    	if (!of_node)
    		return -ENODEV;
    
    	dp83867->io_impedance = -EINVAL;
    
    	/* Optional configuration */
    	if (of_property_read_bool(of_node, "ti,max-output-impedance"))
    		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
    	else if (of_property_read_bool(of_node, "ti,min-output-impedance"))
    		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
    
    	dp83867->rxctrl_strap_quirk = of_property_read_bool(of_node,
    					"ti,dp83867-rxctrl-strap-quirk");
    
    	ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
    				   &dp83867->rx_id_delay);
    	if (ret &&
    	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
    	     phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
    		return ret;
    
    	ret = of_property_read_u32(of_node, "ti,tx-internal-delay",
    				   &dp83867->tx_id_delay);
    	if (ret &&
    	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
    	     phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
    		return ret;
    
    	if (of_property_read_bool(of_node, "enet-phy-lane-swap"))
    		dp83867->port_mirroring = DP83867_PORT_MIRROING_EN;
    
    	if (of_property_read_bool(of_node, "enet-phy-lane-no-swap"))
    		dp83867->port_mirroring = DP83867_PORT_MIRROING_DIS;
    
    	return of_property_read_u32(of_node, "ti,fifo-depth",
    				   &dp83867->fifo_depth);
    }
    #else
    static int dp83867_of_init(struct phy_device *phydev)
    {
    	return 0;
    }
    #endif /* CONFIG_OF_MDIO */
    
    static int dp83867_config_init(struct phy_device *phydev)
    {
    	struct dp83867_private *dp83867;
    	int ret, val, bs;
    	u16 delay;
    
    	if (!phydev->priv) {
    		dp83867 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83867),
    				       GFP_KERNEL);
    		if (!dp83867)
    			return -ENOMEM;
    
    		phydev->priv = dp83867;
    		ret = dp83867_of_init(phydev);
    		if (ret)
    			return ret;
    	} else {
    		dp83867 = (struct dp83867_private *)phydev->priv;
    	}
    
    	/* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */
    	if (dp83867->rxctrl_strap_quirk) {
    		val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
    		val &= ~BIT(7);
    		phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
    	}
    
    	/* When the Phy is strapped to enable Fast Link Drop (FLD) feature,
    	 * the detect threshold value becomes 0x2 in bit 2:0 instead of 0x1
    	 * as in non strapped case. This causes the phy link to be unstable.
    	 * As a workaround, write a value of 0x1 in this bit field if
    	 * bit 10 of DP83867_STRAP_STS2 is set (enable FLD).
    	 */
    	val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS2);
    	if (val & STRAP_STS2_FLD_MASK) {
    		val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_FLD_THRESH);
    		val &= ~0x7;
    		phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_FLD_THRESH,
    			      val | 0x1);
    	}
    
    	if (phy_interface_is_rgmii(phydev)) {
    		val = phy_read(phydev, MII_DP83867_PHYCTRL);
    		if (val < 0)
    			return val;
    		val &= ~DP83867_PHYCR_FIFO_DEPTH_MASK;
    		val |= (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT);
    
    		/* The code below checks if "port mirroring" N/A MODE4 has been
    		 * enabled during power on bootstrap.
    		 *
    		 * Such N/A mode enabled by mistake can put PHY IC in some
    		 * internal testing mode and disable RGMII transmission.
    		 *
    		 * In this particular case one needs to check STRAP_STS1
    		 * register's bit 11 (marked as RESERVED).
    		 */
    
    		bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS1);
    		if (bs & DP83867_STRAP_STS1_RESERVED)
    			val &= ~DP83867_PHYCR_RESERVED_MASK;
    
    		ret = phy_write(phydev, MII_DP83867_PHYCTRL, val);
    		if (ret)
    			return ret;
    	}
    
    	if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) &&
    	    (phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) {
    		val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL);
    
    		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
    			val |= (DP83867_RGMII_TX_CLK_DELAY_EN | DP83867_RGMII_RX_CLK_DELAY_EN);
    
    		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
    			val |= DP83867_RGMII_TX_CLK_DELAY_EN;
    
    		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
    			val |= DP83867_RGMII_RX_CLK_DELAY_EN;
    
    		phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val);
    
    		delay = (dp83867->rx_id_delay |
    			(dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
    
    		phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL,
    			      delay);
    
    		if (dp83867->io_impedance >= 0) {
    			val = phy_read_mmd(phydev, DP83867_DEVADDR,
    					   DP83867_IO_MUX_CFG);
    
    			val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
    			val |= dp83867->io_impedance &
    			       DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
    
    			phy_write_mmd(phydev, DP83867_DEVADDR,
    				      DP83867_IO_MUX_CFG, val);
    		}
    	}
    
    	/* Enable Interrupt output INT_OE in CFG3 register */
    	if (phy_interrupt_is_valid(phydev)) {
    		val = phy_read(phydev, DP83867_CFG3);
    		val |= BIT(7);
    		phy_write(phydev, DP83867_CFG3, val);
    	}
    
    	if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP)
    		dp83867_config_port_mirroring(phydev);
    
    	return 0;
    }
    
    static int dp83867_phy_reset(struct phy_device *phydev)
    {
    	int err;
    
    	err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
    	if (err < 0)
    		return err;
    
    	return dp83867_config_init(phydev);
    }
    
    static struct phy_driver dp83867_driver[] = {
    	{
    		.phy_id		= DP83867_PHY_ID,
    		.phy_id_mask	= 0xfffffff0,
    		.name		= "TI DP83867",
    		.features	= PHY_GBIT_FEATURES,
    		.flags		= PHY_HAS_INTERRUPT,
    
    		.config_init	= dp83867_config_init,
    		.soft_reset	= dp83867_phy_reset,
    
    		/* IRQ related */
    		.ack_interrupt	= dp83867_ack_interrupt,
    		.config_intr	= dp83867_config_intr,
    
    		.config_aneg	= genphy_config_aneg,
    		.read_status	= genphy_read_status,
    		.suspend	= genphy_suspend,
    		.resume		= genphy_resume,
    	},
    };
    module_phy_driver(dp83867_driver);
    
    static struct mdio_device_id __maybe_unused dp83867_tbl[] = {
    	{ DP83867_PHY_ID, 0xfffffff0 },
    	{ }
    };
    
    MODULE_DEVICE_TABLE(mdio, dp83867_tbl);
    
    MODULE_DESCRIPTION("Texas Instruments DP83867 PHY driver");
    MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
    MODULE_LICENSE("GPL");
    /*
     * TI PHY drivers
     *
     * SPDX-License-Identifier:	GPL-2.0
     *
     */
    #include <common.h>
    #include <phy.h>
    #include <linux/compat.h>
    #include <malloc.h>
    
    #include <dm.h>
    #include <dt-bindings/net/ti-dp83867.h>
    
    
    /* TI DP83867 */
    #define DP83867_DEVADDR		0x1f
    
    #define MII_DP83867_PHYCTRL	0x10
    #define MII_DP83867_MICR	0x12
    #define MII_DP83867_CFG2	0x14
    #define MII_DP83867_BISCR	0x16
    #define DP83867_CTRL		0x1f
    
    /* Extended Registers */
    #define DP83867_CFG4		0x0031
    #define DP83867_RGMIICTL	0x0032
    #define DP83867_RGMIIDCTL	0x0086
    #define DP83867_IO_MUX_CFG	0x0170
    
    #define DP83867_SW_RESET	BIT(15)
    #define DP83867_SW_RESTART	BIT(14)
    
    /* MICR Interrupt bits */
    #define MII_DP83867_MICR_AN_ERR_INT_EN		BIT(15)
    #define MII_DP83867_MICR_SPEED_CHNG_INT_EN	BIT(14)
    #define MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN	BIT(13)
    #define MII_DP83867_MICR_PAGE_RXD_INT_EN	BIT(12)
    #define MII_DP83867_MICR_AUTONEG_COMP_INT_EN	BIT(11)
    #define MII_DP83867_MICR_LINK_STS_CHNG_INT_EN	BIT(10)
    #define MII_DP83867_MICR_FALSE_CARRIER_INT_EN	BIT(8)
    #define MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN	BIT(4)
    #define MII_DP83867_MICR_WOL_INT_EN		BIT(3)
    #define MII_DP83867_MICR_XGMII_ERR_INT_EN	BIT(2)
    #define MII_DP83867_MICR_POL_CHNG_INT_EN	BIT(1)
    #define MII_DP83867_MICR_JABBER_INT_EN		BIT(0)
    
    /* RGMIICTL bits */
    #define DP83867_RGMII_TX_CLK_DELAY_EN		BIT(1)
    #define DP83867_RGMII_RX_CLK_DELAY_EN		BIT(0)
    
    /* PHY CTRL bits */
    #define DP83867_PHYCR_FIFO_DEPTH_SHIFT		14
    #define DP83867_MDI_CROSSOVER		5
    #define DP83867_MDI_CROSSOVER_AUTO	2
    #define DP83867_MDI_CROSSOVER_MDIX	2
    #define DP83867_PHYCTRL_SGMIIEN			0x0800
    #define DP83867_PHYCTRL_RXFIFO_SHIFT	12
    #define DP83867_PHYCTRL_TXFIFO_SHIFT	14
    
    /* RGMIIDCTL bits */
    #define DP83867_RGMII_TX_CLK_DELAY_SHIFT	4
    
    /* CFG2 bits */
    #define MII_DP83867_CFG2_SPEEDOPT_10EN		0x0040
    #define MII_DP83867_CFG2_SGMII_AUTONEGEN	0x0080
    #define MII_DP83867_CFG2_SPEEDOPT_ENH		0x0100
    #define MII_DP83867_CFG2_SPEEDOPT_CNT		0x0800
    #define MII_DP83867_CFG2_SPEEDOPT_INTLOW	0x2000
    #define MII_DP83867_CFG2_MASK			0x003F
    
    #define MII_MMD_CTRL	0x0d /* MMD Access Control Register */
    #define MII_MMD_DATA	0x0e /* MMD Access Data Register */
    
    /* MMD Access Control register fields */
    #define MII_MMD_CTRL_DEVAD_MASK	0x1f /* Mask MMD DEVAD*/
    #define MII_MMD_CTRL_ADDR	0x0000 /* Address */
    #define MII_MMD_CTRL_NOINCR	0x4000 /* no post increment */
    #define MII_MMD_CTRL_INCR_RDWT	0x8000 /* post increment on reads & writes */
    #define MII_MMD_CTRL_INCR_ON_WT	0xC000 /* post increment on writes only */
    
    /* User setting - can be taken from DTS */
    #define DEFAULT_RX_ID_DELAY	DP83867_RGMIIDCTL_2_25_NS
    #define DEFAULT_TX_ID_DELAY	DP83867_RGMIIDCTL_2_75_NS
    #define DEFAULT_FIFO_DEPTH	DP83867_PHYCR_FIFO_DEPTH_4_B_NIB
    
    /* IO_MUX_CFG bits */
    #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL	0x1f
    
    #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX	0x0
    #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN	0x1f
    
    struct dp83867_private {
    	int rx_id_delay;
    	int tx_id_delay;
    	int fifo_depth;
    	int io_impedance;
    	bool rxctrl_strap_quirk;
    };
    
    /**
     * phy_read_mmd_indirect - reads data from the MMD registers
     * @phydev: The PHY device bus
     * @prtad: MMD Address
     * @devad: MMD DEVAD
     * @addr: PHY address on the MII bus
     *
     * Description: it reads data from the MMD registers (clause 22 to access to
     * clause 45) of the specified phy address.
     * To read these registers we have:
     * 1) Write reg 13 // DEVAD
     * 2) Write reg 14 // MMD Address
     * 3) Write reg 13 // MMD Data Command for MMD DEVAD
     * 3) Read  reg 14 // Read MMD data
     */
    int phy_read_mmd_indirect(struct phy_device *phydev, int prtad,
    			  int devad, int addr)
    {
    	int value = -1;
    
    	/* Write the desired MMD Devad */
    	phy_write(phydev, addr, MII_MMD_CTRL, devad);
    
    	/* Write the desired MMD register address */
    	phy_write(phydev, addr, MII_MMD_DATA, prtad);
    
    	/* Select the Function : DATA with no post increment */
    	phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
    
    	/* Read the content of the MMD's selected register */
    	value = phy_read(phydev, addr, MII_MMD_DATA);
    	return value;
    }
    
    /**
     * phy_write_mmd_indirect - writes data to the MMD registers
     * @phydev: The PHY device
     * @prtad: MMD Address
     * @devad: MMD DEVAD
     * @addr: PHY address on the MII bus
     * @data: data to write in the MMD register
     *
     * Description: Write data from the MMD registers of the specified
     * phy address.
     * To write these registers we have:
     * 1) Write reg 13 // DEVAD
     * 2) Write reg 14 // MMD Address
     * 3) Write reg 13 // MMD Data Command for MMD DEVAD
     * 3) Write reg 14 // Write MMD data
     */
    void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
    			    int devad, int addr, u32 data)
    {
    	/* Write the desired MMD Devad */
    	phy_write(phydev, addr, MII_MMD_CTRL, devad);
    
    	/* Write the desired MMD register address */
    	phy_write(phydev, addr, MII_MMD_DATA, prtad);
    
    	/* Select the Function : DATA with no post increment */
    	phy_write(phydev, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
    
    	/* Write the data into MMD's selected register */
    	phy_write(phydev, addr, MII_MMD_DATA, data);
    }
    
    #if defined(CONFIG_DM_ETH)
    /**
     * dp83867_data_init - Convenience function for setting PHY specific data
     *
     * @phydev: the phy_device struct
     */
    static int dp83867_of_init(struct phy_device *phydev)
    {
    	struct dp83867_private *dp83867 = phydev->priv;
    	ofnode node;
    
    	node = phy_get_ofnode(phydev);
    	if (!ofnode_valid(node))
    		return -EINVAL;
    
    	if (ofnode_read_bool(node, "ti,max-output-impedance"))
    		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
    	else if (ofnode_read_bool(node, "ti,min-output-impedance"))
    		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
    	else
    		dp83867->io_impedance = -EINVAL;
    
    	if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk"))
    		dp83867->rxctrl_strap_quirk = true;
    	dp83867->rx_id_delay = ofnode_read_u32_default(
    					node, "ti,rx-internal-delay", -1);
    
    	dp83867->tx_id_delay = ofnode_read_u32_default(
    					node, "ti,tx-internal-delay", -1);
    
    	dp83867->fifo_depth = ofnode_read_u32_default(
    					node, "ti,fifo-depth", -1);
    
    	return 0;
    }
    #else
    static int dp83867_of_init(struct phy_device *phydev)
    {
    	struct dp83867_private *dp83867 = phydev->priv;
    
    	dp83867->rx_id_delay = DEFAULT_RX_ID_DELAY;
    	dp83867->tx_id_delay = DEFAULT_TX_ID_DELAY;
    	dp83867->fifo_depth = DEFAULT_FIFO_DEPTH;
    	dp83867->io_impedance = -EINVAL;
    
    	return 0;
    }
    #endif
    
    static int dp83867_config(struct phy_device *phydev)
    {
    	struct dp83867_private *dp83867;
    	unsigned int val, delay, cfg2;
    	int ret;
    
    	if (!phydev->priv) {
    		dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
    		if (!dp83867)
    			return -ENOMEM;
    
    		phydev->priv = dp83867;
    		ret = dp83867_of_init(phydev);
    		if (ret)
    			goto err_out;
    	} else {
    		dp83867 = (struct dp83867_private *)phydev->priv;
    	}
    
    	/* Restart the PHY.  */
    	val = phy_read(phydev, MDIO_DEVAD_NONE, DP83867_CTRL);
    	phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
    		  val | DP83867_SW_RESTART);
    
    	/* Mode 1 or 2 workaround */
    	if (dp83867->rxctrl_strap_quirk) {
    		val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
    					    DP83867_DEVADDR, phydev->addr);
    		val &= ~BIT(7);
    		phy_write_mmd_indirect(phydev, DP83867_CFG4,
    				       DP83867_DEVADDR, phydev->addr, val);
    	}
    
    	if (phy_interface_is_rgmii(phydev)) {
    		ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
    			(DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
    			(dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT));
    		if (ret)
    			goto err_out;
    	} else if (phy_interface_is_sgmii(phydev)) {
    		phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
    			  (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
    
    		cfg2 = phy_read(phydev, phydev->addr, MII_DP83867_CFG2);
    		cfg2 &= MII_DP83867_CFG2_MASK;
    		cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN |
    			 MII_DP83867_CFG2_SGMII_AUTONEGEN |
    			 MII_DP83867_CFG2_SPEEDOPT_ENH |
    			 MII_DP83867_CFG2_SPEEDOPT_CNT |
    			 MII_DP83867_CFG2_SPEEDOPT_INTLOW);
    		phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG2, cfg2);
    
    		phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
    				       DP83867_DEVADDR, phydev->addr, 0x0);
    
    		phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
    			  DP83867_PHYCTRL_SGMIIEN |
    			  (DP83867_MDI_CROSSOVER_MDIX <<
    			  DP83867_MDI_CROSSOVER) |
    			  (dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) |
    			  (dp83867->fifo_depth << DP83867_PHYCTRL_TXFIFO_SHIFT));
    		phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0);
    	}
    
    	if (phy_interface_is_rgmii(phydev)) {
    		val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
    					    DP83867_DEVADDR, phydev->addr);
    
    		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
    			val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
    				DP83867_RGMII_RX_CLK_DELAY_EN);
    
    		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
    			val |= DP83867_RGMII_TX_CLK_DELAY_EN;
    
    		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
    			val |= DP83867_RGMII_RX_CLK_DELAY_EN;
    
    		phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
    				       DP83867_DEVADDR, phydev->addr, val);
    
    		delay = (dp83867->rx_id_delay |
    			 (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
    
    		phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL,
    				       DP83867_DEVADDR, phydev->addr, delay);
    
    		if (dp83867->io_impedance >= 0) {
    			val = phy_read_mmd_indirect(phydev,
    						    DP83867_IO_MUX_CFG,
    						    DP83867_DEVADDR,
    						    phydev->addr);
    			val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
    			val |= dp83867->io_impedance &
    			       DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
    			phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
    					       DP83867_DEVADDR, phydev->addr,
    					       val);
    		}
    	}
    
    	genphy_config_aneg(phydev);
    	return 0;
    
    err_out:
    	kfree(dp83867);
    	return ret;
    }
    
    static struct phy_driver DP83867_driver = {
    	.name = "TI DP83867",
    	.uid = 0x2000a231,
    	.mask = 0xfffffff0,
    	.features = PHY_GBIT_FEATURES,
    	.config = &dp83867_config,
    	.startup = &genphy_startup,
    	.shutdown = &genphy_shutdown,
    };
    
    int phy_ti_init(void)
    {
    	phy_register(&DP83867_driver);
    	return 0;
    }

    BR Rio

        

       

  • Hi Rio,

    That is correct, currently there is not support for the dp83825 PHY at this time in U-boot in the SDK, just the  83867.

    Best Regards,

    Schuyler