[U-Boot] [PATCH v4 0/3] Expand dp83867-driver

- Add enet-phy-lane-(no)-swap to the documentaion
Janine Hagemann (3): net: phy: ti: Add lane swapping support in the DP83867 TI's PHY driver net: phy: ti: Recover from "port mirroring" N/A MODE4 net: phy: ti: Add binding for the CLK_OUT pin muxing
doc/device-tree-bindings/net/ti,dp83867.txt | 8 +++ drivers/net/phy/ti.c | 91 ++++++++++++++++++++++++++++- include/dt-bindings/net/ti-dp83867.h | 15 +++++ 3 files changed, 113 insertions(+), 1 deletion(-)

This patch adds support for enabling or disabling the lane swapping (called "port mirroring" in PHY's CFG4 register) feature of the DP83867 TI's PHY device.
One use case is when bootstrap configuration enables this feature (because of e.g. LED_0 wrong wiring) so then one needs to disable it in software (at u-boot/Linux).
Based on commit fc6d39c39581 ("net: phy: dp83867: Add lane swapping support in the DP83867 TI's PHY driver") of mainline linux kernel.
Signed-off-by: Janine Hagemann j.hagemann@phytec.de Acked-by: Lukasz Majewski lukma@denx.de Acked-by: Joe Hershberger joe.hershberger@ni.com --- doc/device-tree-bindings/net/ti,dp83867.txt | 5 ++++ drivers/net/phy/ti.c | 39 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)
diff --git a/doc/device-tree-bindings/net/ti,dp83867.txt b/doc/device-tree-bindings/net/ti,dp83867.txt index cb77fdf..f31c2da 100644 --- a/doc/device-tree-bindings/net/ti,dp83867.txt +++ b/doc/device-tree-bindings/net/ti,dp83867.txt @@ -8,6 +8,10 @@ Required properties: for applicable values - ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h for applicable values + - enet-phy-lane-swap - Indicates that PHY will swap the TX/RX lanes to + compensate for the board being designed with the lanes swapped. + - enet-phy-no-lane-swap - Indicates that PHY will disable swap of the + TX/RX lanes.
Default child nodes are standard Ethernet PHY device nodes as described in doc/devicetree/bindings/net/ethernet.txt @@ -19,6 +23,7 @@ Example: ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>; ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>; ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; + enet-phy-lane-no-swap; };
Datasheet can be found: diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index f870e6d..b5fa687 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -89,12 +89,22 @@ #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_MIRRORING_KEEP, + DP83867_PORT_MIRRORING_EN, + DP83867_PORT_MIRRORING_DIS, +}; + struct dp83867_private { int rx_id_delay; int tx_id_delay; int fifo_depth; int io_impedance; bool rxctrl_strap_quirk; + int port_mirroring; };
/** @@ -163,6 +173,26 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, phy_write(phydev, addr, MII_MMD_DATA, data); }
+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_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr); + + if (dp83867->port_mirroring == DP83867_PORT_MIRRORING_EN) + val |= DP83867_CFG4_PORT_MIRROR_EN; + else + val &= ~DP83867_CFG4_PORT_MIRROR_EN; + + phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR, + phydev->addr, val); + + return 0; +} + #if defined(CONFIG_DM_ETH) /** * dp83867_data_init - Convenience function for setting PHY specific data @@ -197,6 +227,12 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth", -1); + if (ofnode_read_bool(node, "enet-phy-lane-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_EN; + + if (ofnode_read_bool(node, "enet-phy-lane-no-swap")) + dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS; +
return 0; } @@ -315,6 +351,9 @@ static int dp83867_config(struct phy_device *phydev) } }
+ if (dp83867->port_mirroring != DP83867_PORT_MIRRORING_KEEP) + dp83867_config_port_mirroring(phydev); + genphy_config_aneg(phydev); return 0;

Hi Janine,
https://patchwork.ozlabs.org/patch/962741/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe

The DP83867 when not properly bootstrapped - especially with LED_0 pin - can enter N/A MODE4 for "port mirroring" feature.
To provide normal operation of the PHY, one needs not only to explicitly disable the port mirroring feature, but as well stop some IC internal testing (which disables RGMII communication).
To do that the STRAP_STS1 (0x006E) register must be read and RESERVED bit 11 examined. When it is set, the another RESERVED bit (11) at PHYCR (0x0010) register must be clear to disable testing mode and enable RGMII communication.
Thorough explanation of the problem can be found at following e2e thread: "DP83867IR: Problem with RESERVED bits in PHY Control Register (PHYCR) - Linux driver"
https://e2e.ti.com/support/interface/ethernet/f/903/p/571313/2096954#2096954
Based on commit ac6e058b75be ("net: phy: dp83867: Recover from "port mirroring" N/A MODE4") of mainline linux kernel.
Signed-off-by: Janine Hagemann j.hagemann@phytec.de Acked-by: Joe Hershberger joe.hershberger@ni.com Acked-by: Lukasz Majewski lukma@denx.de --- drivers/net/phy/ti.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index b5fa687..120867e 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -24,6 +24,7 @@ /* Extended Registers */ #define DP83867_CFG4 0x0031 #define DP83867_RGMIICTL 0x0032 +#define DP83867_STRAP_STS1 0x006E #define DP83867_RGMIIDCTL 0x0086 #define DP83867_IO_MUX_CFG 0x0170
@@ -48,8 +49,12 @@ #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_RESERVED_MASK BIT(11) #define DP83867_MDI_CROSSOVER 5 #define DP83867_MDI_CROSSOVER_AUTO 2 #define DP83867_MDI_CROSSOVER_MDIX 2 @@ -254,7 +259,7 @@ static int dp83867_config(struct phy_device *phydev) { struct dp83867_private *dp83867; unsigned int val, delay, cfg2; - int ret; + int ret, bs;
if (!phydev->priv) { dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL); @@ -289,6 +294,25 @@ static int dp83867_config(struct phy_device *phydev) (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT)); if (ret) goto err_out; + + /* 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_indirect(phydev, DP83867_STRAP_STS1, + DP83867_DEVADDR, phydev->addr); + val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL); + if (bs & DP83867_STRAP_STS1_RESERVED) { + val &= ~DP83867_PHYCR_RESERVED_MASK; + phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL, val); + } + } else if (phy_interface_is_sgmii(phydev)) { phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));

Hi Janine,
https://patchwork.ozlabs.org/patch/962746/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe

The DP83867 has a muxing option for the CLK_OUT pin. It is possible to set CLK_OUT for different channels. Create a binding to select a specific clock for CLK_OUT pin.
Based on commit 9708fb630d19 ("net: phy: dp83867: Add binding for the CLK_OUT pin muxing option") of mainline linux kernel.
Signed-off-by: Janine Hagemann j.hagemann@phytec.de --- doc/device-tree-bindings/net/ti,dp83867.txt | 3 +++ drivers/net/phy/ti.c | 26 ++++++++++++++++++++++++++ include/dt-bindings/net/ti-dp83867.h | 15 +++++++++++++++ 3 files changed, 44 insertions(+)
diff --git a/doc/device-tree-bindings/net/ti,dp83867.txt b/doc/device-tree-bindings/net/ti,dp83867.txt index f31c2da..034146f 100644 --- a/doc/device-tree-bindings/net/ti,dp83867.txt +++ b/doc/device-tree-bindings/net/ti,dp83867.txt @@ -12,6 +12,8 @@ Required properties: compensate for the board being designed with the lanes swapped. - enet-phy-no-lane-swap - Indicates that PHY will disable swap of the TX/RX lanes. + - ti,clk-output-sel - Clock output select - see dt-bindings/net/ti-dp83867.h + for applicable values
Default child nodes are standard Ethernet PHY device nodes as described in doc/devicetree/bindings/net/ethernet.txt @@ -24,6 +26,7 @@ Example: ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>; ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; enet-phy-lane-no-swap; + ti,clk-output-sel = <DP83867_CLK_O_SEL_CHN_A_TCLK>; };
Datasheet can be found: diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c index 120867e..d443266 100644 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@ -93,6 +93,8 @@
#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f +#define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8 +#define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK GENMASK(0x1f, DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT)
/* CFG4 bits */ #define DP83867_CFG4_PORT_MIRROR_EN BIT(0) @@ -110,6 +112,7 @@ struct dp83867_private { int io_impedance; bool rxctrl_strap_quirk; int port_mirroring; + int clk_output_sel; };
/** @@ -208,6 +211,18 @@ static int dp83867_of_init(struct phy_device *phydev) { struct dp83867_private *dp83867 = phydev->priv; ofnode node; + u16 val; + + /* Optional configuration */ + + /* + * Keep the default value if ti,clk-output-sel is not set + * or to high + */ + + dp83867->clk_output_sel = ofnode_read_u32_default(node, + "ti,clk-output-sel", + DP83867_CLK_O_SEL_REF_CLK);
node = phy_get_ofnode(phydev); if (!ofnode_valid(node)) @@ -239,6 +254,17 @@ static int dp83867_of_init(struct phy_device *phydev) dp83867->port_mirroring = DP83867_PORT_MIRRORING_DIS;
+ /* Clock output selection if muxing property is set */ + if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) { + val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr); + val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; + val |= (dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); + phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG, + DP83867_DEVADDR, phydev->addr, val); + } + return 0; } #else diff --git a/include/dt-bindings/net/ti-dp83867.h b/include/dt-bindings/net/ti-dp83867.h index b8e5df6..85d08f6 100644 --- a/include/dt-bindings/net/ti-dp83867.h +++ b/include/dt-bindings/net/ti-dp83867.h @@ -31,4 +31,19 @@ #define DP83867_RGMIIDCTL_3_75_NS 0xe #define DP83867_RGMIIDCTL_4_00_NS 0xf
+/* IO_MUX_CFG - Clock output selection */ +#define DP83867_CLK_O_SEL_CHN_A_RCLK 0x0 +#define DP83867_CLK_O_SEL_CHN_B_RCLK 0x1 +#define DP83867_CLK_O_SEL_CHN_C_RCLK 0x2 +#define DP83867_CLK_O_SEL_CHN_D_RCLK 0x3 +#define DP83867_CLK_O_SEL_CHN_A_RCLK_DIV5 0x4 +#define DP83867_CLK_O_SEL_CHN_B_RCLK_DIV5 0x5 +#define DP83867_CLK_O_SEL_CHN_C_RCLK_DIV5 0x6 +#define DP83867_CLK_O_SEL_CHN_D_RCLK_DIV5 0x7 +#define DP83867_CLK_O_SEL_CHN_A_TCLK 0x8 +#define DP83867_CLK_O_SEL_CHN_B_TCLK 0x9 +#define DP83867_CLK_O_SEL_CHN_C_TCLK 0xA +#define DP83867_CLK_O_SEL_CHN_D_TCLK 0xB +#define DP83867_CLK_O_SEL_REF_CLK 0xC + #endif

On Tue, Aug 28, 2018 at 1:32 AM Janine Hagemann j.hagemann@phytec.de wrote:
The DP83867 has a muxing option for the CLK_OUT pin. It is possible to set CLK_OUT for different channels. Create a binding to select a specific clock for CLK_OUT pin.
Based on commit 9708fb630d19 ("net: phy: dp83867: Add binding for the CLK_OUT pin muxing option") of mainline linux kernel.
Signed-off-by: Janine Hagemann j.hagemann@phytec.de
Acked-by: Joe Hershberger joe.hershberger@ni.com

Hi Janine,
https://patchwork.ozlabs.org/patch/962743/ was applied to http://git.denx.de/?p=u-boot/u-boot-net.git
Thanks! -Joe
participants (2)
-
Janine Hagemann
-
Joe Hershberger