summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-03-23 12:15:24 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-03-23 12:15:24 +0100
commit74ae57c86a39b8bd63b6c0130ce36040cd2db68a (patch)
treeaa37033c69d2b095057e9bfb9c515314dbe81550
parentbb2873db3ef11e7b1299b1cca129f5d002e47f59 (diff)
parent3f09313f542be73ad9fb998076e284d66264838d (diff)
downloadbarebox-74ae57c86a39b8bd63b6c0130ce36040cd2db68a.tar.gz
barebox-74ae57c86a39b8bd63b6c0130ce36040cd2db68a.tar.xz
Merge branch 'for-next/net'
-rw-r--r--drivers/net/macb.c3
-rw-r--r--drivers/net/phy/dp83867.c169
2 files changed, 93 insertions, 79 deletions
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 188dbf2d8c..14a0b45322 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -269,6 +269,9 @@ static int macb_set_tx_clk(struct macb_device *macb, int speed)
}
switch (speed) {
+ case SPEED_10:
+ rate = 2500000;
+ break;
case SPEED_100:
rate = 25000000;
break;
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 8131e8c9d6..05af83f076 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* 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 <common.h>
@@ -24,6 +16,7 @@
#define DP83867_DEVADDR MDIO_MMD_VEND2
#define MII_DP83867_PHYCTRL 0x10
+#define MII_DP83867_PHYSTS 0x11
#define MII_DP83867_MICR 0x12
#define MII_DP83867_ISR 0x13
#define MII_DP83867_CFG2 0x14
@@ -73,16 +66,21 @@
#define DP83867_PHYCTRL_TXFIFO_SHIFT 14
#define DP83867_PHYCR_RESERVED_MASK BIT(11)
+/* PHY STS bits */
+#define DP83867_PHYSTS_SPEED_1000 BIT(15)
+#define DP83867_PHYSTS_SPEED_100 BIT(14)
+#define DP83867_PHYSTS_DUPLEX_FULL BIT(13)
+
/* 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 DP83867_DOWNSHIFT_EN (BIT(8) | BIT(9))
+#define DP83867_DOWNSHIFT_ATTEMPT_MASK (BIT(10) | BIT(11))
+#define DP83867_DOWNSHIFT_1_COUNT_VAL 0
+#define DP83867_DOWNSHIFT_2_COUNT_VAL 1
+#define DP83867_DOWNSHIFT_4_COUNT_VAL 2
+#define DP83867_DOWNSHIFT_8_COUNT_VAL 3
/* CFG4 bits */
#define DP83867_CFG4_SGMII_AUTONEG_TIMER_MASK 0x60
@@ -117,9 +115,38 @@ struct dp83867_private {
bool rxctrl_strap_quirk;
};
+static int dp83867_read_status(struct phy_device *phydev)
+{
+ int status;
+ int ret;
+
+ ret = genphy_update_link(phydev);
+ if (ret)
+ return ret;
+
+ status = phy_read(phydev, MII_DP83867_PHYSTS);
+ if (status < 0)
+ return status;
+
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_HALF;
+
+ if (status & DP83867_PHYSTS_SPEED_1000)
+ phydev->speed = SPEED_1000;
+ else if (status & DP83867_PHYSTS_SPEED_100)
+ phydev->speed = SPEED_100;
+
+ if (status & DP83867_PHYSTS_DUPLEX_FULL)
+ phydev->duplex = DUPLEX_FULL;
+
+ phydev->pause = phydev->asym_pause = 0;
+
+ return 0;
+}
+
static int dp83867_config_port_mirroring(struct phy_device *phydev)
{
- struct dp83867_private *dp83867 = (struct dp83867_private *)phydev->priv;
+ struct dp83867_private *dp83867 = phydev->priv;
u16 val;
val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR);
@@ -154,18 +181,18 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->rxctrl_strap_quirk =
of_property_read_bool(of_node,
- "ti,dp83867-rxctrl-strap-quirk");
+ "ti,dp83867-rxctrl-strap-quirk");
ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
- &dp83867->rx_id_delay);
+ &dp83867->rx_id_delay);
if (ret && (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
return ret;
ret = of_property_read_u32(of_node, "ti,tx-internal-delay",
- &dp83867->tx_id_delay);
+ &dp83867->tx_id_delay);
if (ret && (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
return ret;
if (of_property_read_bool(of_node, "enet-phy-lane-swap"))
@@ -175,20 +202,20 @@ static int dp83867_of_init(struct phy_device *phydev)
dp83867->port_mirroring = DP83867_PORT_MIRROING_DIS;
return of_property_read_u32(of_node, "ti,fifo-depth",
- &dp83867->fifo_depth);
+ &dp83867->fifo_depth);
}
static inline bool phy_interface_is_sgmii(struct phy_device *phydev)
{
return phydev->interface == PHY_INTERFACE_MODE_SGMII ||
- phydev->interface == PHY_INTERFACE_MODE_QSGMII;
+ phydev->interface == PHY_INTERFACE_MODE_QSGMII;
}
static int dp83867_config_init(struct phy_device *phydev)
{
struct dp83867_private *dp83867;
int ret;
- u16 val, delay, cfg2;
+ u16 val, delay;
if (!phydev->priv) {
dp83867 = kzalloc(sizeof(*dp83867), GFP_KERNEL);
@@ -200,7 +227,7 @@ static int dp83867_config_init(struct phy_device *phydev)
if (ret)
return ret;
} else {
- dp83867 = (struct dp83867_private *)phydev->priv;
+ dp83867 = phydev->priv;
}
/* Restart the PHY. */
@@ -209,53 +236,26 @@ static int dp83867_config_init(struct phy_device *phydev)
if (dp83867->rxctrl_strap_quirk) {
val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
- DP83867_DEVADDR);
+ DP83867_DEVADDR);
val &= ~BIT(7);
- phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR,
- val);
+ phy_write_mmd_indirect(phydev, DP83867_CFG4,
+ DP83867_DEVADDR, val);
}
if (phy_interface_is_rgmii(phydev)) {
val = DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER |
- dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT;
+ dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT;
ret = phy_write(phydev, MII_DP83867_PHYCTRL, val);
if (ret)
return ret;
- } else if (phy_interface_is_sgmii(phydev)) {
- phy_write(phydev, MII_BMCR, BMCR_ANENABLE |
- BMCR_FULLDPLX |
- BMCR_SPEED1000);
-
- cfg2 = phy_read(phydev, 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, MII_DP83867_CFG2, cfg2);
- phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR, 0x0);
-
- val = 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, MII_DP83867_PHYCTRL, val);
- phy_write(phydev, MII_DP83867_BISCR, 0x0);
- }
-
- if (phy_interface_is_rgmii(phydev)) {
val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR);
+ DP83867_DEVADDR);
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII_ID:
- val |= (DP83867_RGMII_TX_CLK_DELAY_EN
- | DP83867_RGMII_RX_CLK_DELAY_EN);
+ val |= DP83867_RGMII_TX_CLK_DELAY_EN |
+ DP83867_RGMII_RX_CLK_DELAY_EN;
break;
case PHY_INTERFACE_MODE_RGMII_TXID:
val |= DP83867_RGMII_TX_CLK_DELAY_EN;
@@ -267,48 +267,59 @@ static int dp83867_config_init(struct phy_device *phydev)
break;
}
phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR, val);
+ DP83867_DEVADDR, 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, delay);
+ DP83867_DEVADDR, delay);
if (dp83867->io_impedance >= 0) {
val = phy_read_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
- DP83867_DEVADDR);
+ DP83867_DEVADDR);
val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
- val |= dp83867->io_impedance
- & 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, val);
+ DP83867_DEVADDR, val);
}
+ } else if (phy_interface_is_sgmii(phydev)) {
+ phy_write(phydev, MII_BMCR,
+ BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000);
+
+ phy_write_mmd_indirect(phydev, DP83867_RGMIICTL,
+ DP83867_DEVADDR, 0x0);
+
+ val = 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, MII_DP83867_PHYCTRL, val);
+ phy_write(phydev, MII_DP83867_BISCR, 0x0);
}
- genphy_config_aneg(phydev);
+ val = phy_read(phydev, MII_DP83867_CFG2);
+ val |= DP83867_DOWNSHIFT_EN;
+ phy_write(phydev, MII_DP83867_CFG2, val);
if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP)
dp83867_config_port_mirroring(phydev);
- dev_info(&phydev->dev, "DP83867\n");
-
return 0;
}
static struct phy_driver dp83867_driver[] = {
- {
- .phy_id = DP83867_PHY_ID,
- .phy_id_mask = 0xfffffff0,
- .drv.name = "TI DP83867",
- .features = PHY_GBIT_FEATURES,
-
- .config_init = dp83867_config_init,
-
- .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- },
+ {
+ .phy_id = DP83867_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .drv.name = "TI DP83867",
+ .features = PHY_GBIT_FEATURES,
+ .config_init = dp83867_config_init,
+ .read_status = dp83867_read_status,
+ },
};
device_phy_drivers(dp83867_driver);