summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2019-05-08 22:46:31 -0400
committerTom Rini <trini@konsulko.com>2019-05-08 22:46:31 -0400
commiteb511984e90423dd3b5ee3a614f040fa353ee9aa (patch)
treedb02d1f61d07dc438bf6de99b1f681505e493007
parent504bf790da08db9b4a443566cf6ef577f9c7996a (diff)
parent6314d1c8c035d1c4d14ea1ffd133f25385edd067 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-net
- Various PHY fixes / enhancements. - TI K2G fixes
-rw-r--r--arch/arm/dts/sama5d3xcm.dtsi32
-rw-r--r--arch/arm/dts/sama5d3xcm_cmp.dtsi32
-rw-r--r--arch/arm/dts/socfpga_arria5_socdk.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_is1.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_socdk.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_sockit.dts4
-rw-r--r--arch/arm/dts/socfpga_cyclone5_vining_fpga.dts4
-rw-r--r--board/ti/ks2_evm/mux-k2g.h36
-rw-r--r--cmd/mdio.c27
-rw-r--r--doc/device-tree-bindings/net/micrel-ksz90x1.txt27
-rw-r--r--drivers/net/ldpaa_eth/ldpaa_eth.c1
-rw-r--r--drivers/net/phy/Kconfig20
-rw-r--r--drivers/net/phy/aquantia.c7
-rw-r--r--drivers/net/phy/micrel_ksz90x1.c24
-rw-r--r--drivers/net/phy/phy.c21
-rw-r--r--drivers/net/phy/realtek.c19
-rw-r--r--drivers/net/phy/ti.c130
-rw-r--r--include/phy.h70
18 files changed, 283 insertions, 183 deletions
diff --git a/arch/arm/dts/sama5d3xcm.dtsi b/arch/arm/dts/sama5d3xcm.dtsi
index 2cf9c3611d..d123057f30 100644
--- a/arch/arm/dts/sama5d3xcm.dtsi
+++ b/arch/arm/dts/sama5d3xcm.dtsi
@@ -44,28 +44,28 @@
reg = <0x1>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
ethernet-phy@7 {
reg = <0x7>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
};
};
diff --git a/arch/arm/dts/sama5d3xcm_cmp.dtsi b/arch/arm/dts/sama5d3xcm_cmp.dtsi
index 77638c3cbe..332b057e0a 100644
--- a/arch/arm/dts/sama5d3xcm_cmp.dtsi
+++ b/arch/arm/dts/sama5d3xcm_cmp.dtsi
@@ -43,28 +43,28 @@
reg = <0x1>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
ethernet-phy@7 {
reg = <0x7>;
interrupt-parent = <&pioB>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
- txen-skew-ps = <800>;
- txc-skew-ps = <3000>;
- rxdv-skew-ps = <400>;
- rxc-skew-ps = <3000>;
- rxd0-skew-ps = <400>;
- rxd1-skew-ps = <400>;
- rxd2-skew-ps = <400>;
- rxd3-skew-ps = <400>;
+ txen-skew-ps = <480>;
+ txc-skew-ps = <1800>;
+ rxdv-skew-ps = <240>;
+ rxc-skew-ps = <1800>;
+ rxd0-skew-ps = <240>;
+ rxd1-skew-ps = <240>;
+ rxd2-skew-ps = <240>;
+ rxd3-skew-ps = <240>;
};
};
diff --git a/arch/arm/dts/socfpga_arria5_socdk.dts b/arch/arm/dts/socfpga_arria5_socdk.dts
index 90e676e701..fa972e287f 100644
--- a/arch/arm/dts/socfpga_arria5_socdk.dts
+++ b/arch/arm/dts/socfpga_arria5_socdk.dts
@@ -67,9 +67,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio0 {
diff --git a/arch/arm/dts/socfpga_cyclone5_is1.dts b/arch/arm/dts/socfpga_cyclone5_is1.dts
index 2d31412923..a769498791 100644
--- a/arch/arm/dts/socfpga_cyclone5_is1.dts
+++ b/arch/arm/dts/socfpga_cyclone5_is1.dts
@@ -43,9 +43,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio1 {
diff --git a/arch/arm/dts/socfpga_cyclone5_socdk.dts b/arch/arm/dts/socfpga_cyclone5_socdk.dts
index 6f138b2b26..95c7619b8d 100644
--- a/arch/arm/dts/socfpga_cyclone5_socdk.dts
+++ b/arch/arm/dts/socfpga_cyclone5_socdk.dts
@@ -71,9 +71,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio0 {
diff --git a/arch/arm/dts/socfpga_cyclone5_sockit.dts b/arch/arm/dts/socfpga_cyclone5_sockit.dts
index c155ff02eb..90669cde45 100644
--- a/arch/arm/dts/socfpga_cyclone5_sockit.dts
+++ b/arch/arm/dts/socfpga_cyclone5_sockit.dts
@@ -128,9 +128,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
&gpio0 { /* GPIO 0..29 */
diff --git a/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
index 355b3dbf43..ac57f41cb5 100644
--- a/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
+++ b/arch/arm/dts/socfpga_cyclone5_vining_fpga.dts
@@ -85,9 +85,9 @@
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
- txc-skew-ps = <2600>;
+ txc-skew-ps = <1560>;
rxdv-skew-ps = <0>;
- rxc-skew-ps = <2000>;
+ rxc-skew-ps = <1200>;
};
};
};
diff --git a/board/ti/ks2_evm/mux-k2g.h b/board/ti/ks2_evm/mux-k2g.h
index 89c49f9e4f..6aa785ea42 100644
--- a/board/ti/ks2_evm/mux-k2g.h
+++ b/board/ti/ks2_evm/mux-k2g.h
@@ -126,22 +126,22 @@ struct pin_cfg k2g_evm_pin_cfg[] = {
{ 71, MODE(0) }, /* MMC1POW TP124 */
/* EMAC */
- { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
- { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
{ 77, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD3 */
+ { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
{ 80, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD0 */
- { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
- { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
- { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
- { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
{ 85, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXC */
+ { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
+ { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
+ { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
{ 95, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXCTL */
- { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
- { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
/* MDIO */
- { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
{ 98, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_DATA */
+ { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
/* PWM */
{ 73, MODE(4) }, /* SOC_EHRPWM3A */
@@ -350,22 +350,22 @@ struct pin_cfg k2g_ice_evm_pin_cfg[] = {
{ 135, MODE(0) }, /* SOC_QSPI_CSN0 */
/* EMAC */
- { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
- { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
{ 77, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD3 */
+ { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */
+ { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */
{ 80, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD0 */
- { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
- { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
- { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
- { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
{ 85, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXC */
+ { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */
+ { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */
+ { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */
+ { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */
{ 95, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXCTL */
- { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */
- { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */
/* MDIO */
- { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
{ 98, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_DATA */
+ { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */
{ MAX_PIN_N, }
};
diff --git a/cmd/mdio.c b/cmd/mdio.c
index 184868063a..efe8c9ef09 100644
--- a/cmd/mdio.c
+++ b/cmd/mdio.c
@@ -39,21 +39,24 @@ static int extract_range(char *input, int *plo, int *phi)
return 0;
}
-static int mdio_write_ranges(struct phy_device *phydev, struct mii_dev *bus,
+static int mdio_write_ranges(struct mii_dev *bus,
int addrlo,
int addrhi, int devadlo, int devadhi,
int reglo, int reghi, unsigned short data,
int extended)
{
+ struct phy_device *phydev;
int addr, devad, reg;
int err = 0;
for (addr = addrlo; addr <= addrhi; addr++) {
+ phydev = bus->phymap[addr];
+
for (devad = devadlo; devad <= devadhi; devad++) {
for (reg = reglo; reg <= reghi; reg++) {
if (!extended)
- err = bus->write(bus, addr, devad,
- reg, data);
+ err = phy_write_mmd(phydev, devad,
+ reg, data);
else
err = phydev->drv->writeext(phydev,
addr, devad, reg, data);
@@ -68,15 +71,17 @@ err_out:
return err;
}
-static int mdio_read_ranges(struct phy_device *phydev, struct mii_dev *bus,
+static int mdio_read_ranges(struct mii_dev *bus,
int addrlo,
int addrhi, int devadlo, int devadhi,
int reglo, int reghi, int extended)
{
int addr, devad, reg;
+ struct phy_device *phydev;
printf("Reading from bus %s\n", bus->name);
for (addr = addrlo; addr <= addrhi; addr++) {
+ phydev = bus->phymap[addr];
printf("PHY at address %x:\n", addr);
for (devad = devadlo; devad <= devadhi; devad++) {
@@ -84,7 +89,7 @@ static int mdio_read_ranges(struct phy_device *phydev, struct mii_dev *bus,
int val;
if (!extended)
- val = bus->read(bus, addr, devad, reg);
+ val = phy_read_mmd(phydev, devad, reg);
else
val = phydev->drv->readext(phydev, addr,
devad, reg);
@@ -222,14 +227,14 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
bus = phydev->bus;
extended = 1;
} else {
- return -1;
+ return CMD_RET_FAILURE;
}
if (!phydev->drv ||
(!phydev->drv->writeext && (op[0] == 'w')) ||
(!phydev->drv->readext && (op[0] == 'r'))) {
puts("PHY does not have extended functions\n");
- return -1;
+ return CMD_RET_FAILURE;
}
}
}
@@ -242,13 +247,13 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (pos > 1)
if (extract_reg_range(argv[pos--], &devadlo, &devadhi,
&reglo, &reghi))
- return -1;
+ return CMD_RET_FAILURE;
default:
if (pos > 1)
if (extract_phy_range(&argv[2], pos - 1, &bus,
&phydev, &addrlo, &addrhi))
- return -1;
+ return CMD_RET_FAILURE;
break;
}
@@ -264,12 +269,12 @@ static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
switch (op[0]) {
case 'w':
- mdio_write_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi,
+ mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi, data, extended);
break;
case 'r':
- mdio_read_ranges(phydev, bus, addrlo, addrhi, devadlo, devadhi,
+ mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi, extended);
break;
}
diff --git a/doc/device-tree-bindings/net/micrel-ksz90x1.txt b/doc/device-tree-bindings/net/micrel-ksz90x1.txt
index 307f53f726..a214d35fc9 100644
--- a/doc/device-tree-bindings/net/micrel-ksz90x1.txt
+++ b/doc/device-tree-bindings/net/micrel-ksz90x1.txt
@@ -14,6 +14,33 @@ KSZ9021:
value is 0, the maximum value is 1800, and it is incremented by 120ps
steps.
+ The KSZ9021 hardware supports a range of skew values from negative to
+ positive, where the specific range is property dependent. All values
+ specified in the devicetree are offset by the minimum value so they
+ can be represented as positive integers in the devicetree since it's
+ difficult to represent a negative number in the devictree.
+
+ The following 4-bit values table applies to all the skew properties:
+
+ Pad Skew Value Delay (ps) Devicetree Value
+ ------------------------------------------------------
+ 0000 -840ps 0
+ 0001 -720ps 120
+ 0010 -600ps 240
+ 0011 -480ps 360
+ 0100 -360ps 480
+ 0101 -240ps 600
+ 0110 -120ps 720
+ 0111 0ps 840
+ 1000 120ps 960
+ 1001 240ps 1080
+ 1010 360ps 1200
+ 1011 480ps 1320
+ 1100 600ps 1440
+ 1101 720ps 1560
+ 1110 840ps 1680
+ 1111 960ps 1800
+
Optional properties:
- rxc-skew-ps : Skew control of RXC pad
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c
index 73b7ba29df..34253e3924 100644
--- a/drivers/net/ldpaa_eth/ldpaa_eth.c
+++ b/drivers/net/ldpaa_eth/ldpaa_eth.c
@@ -1074,6 +1074,7 @@ int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
if (!priv) {
printf("ldpaa_eth_priv malloc() failed\n");
+ free(net_dev);
return -ENOMEM;
}
memset(priv, 0, sizeof(struct ldpaa_eth_priv));
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3dc0822d9c..631b52b1cf 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -202,6 +202,26 @@ config RTL8211X_PHY_FORCE_MASTER
If unsure, say N.
+config RTL8211F_PHY_FORCE_EEE_RXC_ON
+ bool "Ethernet PHY RTL8211F: do not stop receiving the xMII clock during LPI"
+ depends on PHY_REALTEK
+ default n
+ help
+ The IEEE 802.3az-2010 (EEE) standard provides a protocol to coordinate
+ transitions to/from a lower power consumption level (Low Power Idle
+ mode) based on link utilization. When no packets are being
+ transmitted, the system goes to Low Power Idle mode to save power.
+
+ Under particular circumstances this setting can cause issues where
+ the PHY is unable to transmit or receive any packet when in LPI mode.
+ The problem is caused when the PHY is configured to stop receiving
+ the xMII clock while it is signaling LPI. For some PHYs the bit
+ configuring this behavior is set by the Linux kernel, causing the
+ issue in U-Boot on reboot if the PHY retains the register value.
+
+ Default n, which means that the PHY state is not changed. To work
+ around the issues, change this setting to y.
+
config PHY_SMSC
bool "Microchip(SMSC) Ethernet PHYs support"
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 12df09877d..5c3298d612 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -303,9 +303,14 @@ int aquantia_config(struct phy_device *phydev)
AQUANTIA_SYSTEM_INTERFACE_SR);
/* If SI is USXGMII then start USXGMII autoneg */
if ((val & AQUANTIA_SI_IN_USE_MASK) == AQUANTIA_SI_USXGMII) {
+ reg_val1 = phy_read(phydev, MDIO_MMD_PHYXS,
+ AQUANTIA_VENDOR_PROVISIONING_REG);
+
+ reg_val1 |= AQUANTIA_USX_AUTONEG_CONTROL_ENA;
+
phy_write(phydev, MDIO_MMD_PHYXS,
AQUANTIA_VENDOR_PROVISIONING_REG,
- AQUANTIA_USX_AUTONEG_CONTROL_ENA);
+ reg_val1);
printf("%s: system interface USXGMII\n",
phydev->dev->name);
} else {
diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index 63e7b0242b..8dec9f2367 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -33,10 +33,14 @@
#define CTRL1000_CONFIG_MASTER (1 << 11)
#define CTRL1000_MANUAL_CONFIG (1 << 12)
+#define KSZ9021_PS_TO_REG 120
+
/* KSZ9031 PHY Registers */
#define MII_KSZ9031_MMD_ACCES_CTRL 0x0d
#define MII_KSZ9031_MMD_REG_DATA 0x0e
+#define KSZ9031_PS_TO_REG 60
+
static int ksz90xx_startup(struct phy_device *phydev)
{
unsigned phy_ctl;
@@ -102,20 +106,28 @@ static const struct ksz90x1_reg_field ksz9031_clk_grp[] = {
};
static int ksz90x1_of_config_group(struct phy_device *phydev,
- struct ksz90x1_ofcfg *ofcfg)
+ struct ksz90x1_ofcfg *ofcfg,
+ int ps_to_regval)
{
struct udevice *dev = phydev->dev;
struct phy_driver *drv = phydev->drv;
- const int ps_to_regval = 60;
int val[4];
int i, changed = 0, offset, max;
u16 regval = 0;
+ ofnode node;
if (!drv || !drv->writeext)
return -EOPNOTSUPP;
+ /* Look for a PHY node under the Ethernet node */
+ node = dev_read_subnode(dev, "ethernet-phy");
+ if (!ofnode_valid(node)) {
+ /* No node found, look in the Ethernet node */
+ node = dev_ofnode(dev);
+ }
+
for (i = 0; i < ofcfg->grpsz; i++) {
- val[i] = dev_read_u32_default(dev, ofcfg->grp[i].name, ~0);
+ val[i] = ofnode_read_u32_default(node, ofcfg->grp[i].name, ~0);
offset = ofcfg->grp[i].off;
if (val[i] == -1) {
/* Default register value for KSZ9021 */
@@ -148,7 +160,8 @@ static int ksz9021_of_config(struct phy_device *phydev)
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
- ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
+ ret = ksz90x1_of_config_group(phydev, &ofcfg[i],
+ KSZ9021_PS_TO_REG);
if (ret)
return ret;
}
@@ -167,7 +180,8 @@ static int ksz9031_of_config(struct phy_device *phydev)
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(ofcfg); i++) {
- ret = ksz90x1_of_config_group(phydev, &(ofcfg[i]));
+ ret = ksz90x1_of_config_group(phydev, &ofcfg[i],
+ KSZ9031_PS_TO_REG);
if (ret)
return ret;
}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4e8d2943ee..c1c1af9abd 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -462,6 +462,18 @@ static LIST_HEAD(phy_drivers);
int phy_init(void)
{
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ /*
+ * The pointers inside phy_drivers also needs to be updated incase of
+ * manual reloc, without which these points to some invalid
+ * pre reloc address and leads to invalid accesses, hangs.
+ */
+ struct list_head *head = &phy_drivers;
+
+ head->next = (void *)head->next + gd->reloc_off;
+ head->prev = (void *)head->prev + gd->reloc_off;
+#endif
+
#ifdef CONFIG_B53_SWITCH
phy_b53_init();
#endif
@@ -549,6 +561,10 @@ int phy_register(struct phy_driver *drv)
drv->readext += gd->reloc_off;
if (drv->writeext)
drv->writeext += gd->reloc_off;
+ if (drv->read_mmd)
+ drv->read_mmd += gd->reloc_off;
+ if (drv->write_mmd)
+ drv->write_mmd += gd->reloc_off;
#endif
return 0;
}
@@ -655,7 +671,10 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
dev->drv = get_phy_driver(dev, interface);
- phy_probe(dev);
+ if (phy_probe(dev)) {
+ printf("%s, PHY probe failed\n", __func__);
+ return NULL;
+ }
if (addr >= 0 && addr < PHY_MAX_ADDR)
bus->phymap[addr] = dev;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index dd45e11b3a..8f1d759632 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -12,6 +12,7 @@
#define PHY_RTL8211x_FORCE_MASTER BIT(1)
#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2)
+#define PHY_RTL8211F_FORCE_EEE_RXC_ON BIT(3)
#define PHY_AUTONEGOTIATE_TIMEOUT 5000
@@ -102,6 +103,15 @@ static int rtl8211e_probe(struct phy_device *phydev)
return 0;
}
+static int rtl8211f_probe(struct phy_device *phydev)
+{
+#ifdef CONFIG_RTL8211F_PHY_FORCE_EEE_RXC_ON
+ phydev->flags |= PHY_RTL8211F_FORCE_EEE_RXC_ON;
+#endif
+
+ return 0;
+}
+
/* RealTek RTL8211x */
static int rtl8211x_config(struct phy_device *phydev)
{
@@ -151,6 +161,14 @@ static int rtl8211f_config(struct phy_device *phydev)
{
u16 reg;
+ if (phydev->flags & PHY_RTL8211F_FORCE_EEE_RXC_ON) {
+ unsigned int reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1);
+ reg &= ~MDIO_PCS_CTRL1_CLKSTOP_EN;
+ phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+ }
+
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
phy_write(phydev, MDIO_DEVAD_NONE,
@@ -360,6 +378,7 @@ static struct phy_driver RTL8211F_driver = {
.uid = 0x1cc916,
.mask = 0xffffff,
.features = PHY_GBIT_FEATURES,
+ .probe = &rtl8211f_probe,
.config = &rtl8211f_config,
.startup = &rtl8211f_startup,
.shutdown = &genphy_shutdown,
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 6db6edd0d0..6ac890a7f5 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -73,16 +73,6 @@
#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
@@ -116,88 +106,20 @@ struct dp83867_private {
int clk_output_sel;
};
-/**
- * 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);
-}
-
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);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
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);
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
return 0;
}
@@ -257,13 +179,13 @@ static int dp83867_of_init(struct phy_device *phydev)
/* 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 = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG);
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);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG, val);
}
return 0;
@@ -308,11 +230,11 @@ static int dp83867_config(struct phy_device *phydev)
/* Mode 1 or 2 workaround */
if (dp83867->rxctrl_strap_quirk) {
- val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
- DP83867_DEVADDR, phydev->addr);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_CFG4);
val &= ~BIT(7);
- phy_write_mmd_indirect(phydev, DP83867_CFG4,
- DP83867_DEVADDR, phydev->addr, val);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_CFG4, val);
}
if (phy_interface_is_rgmii(phydev)) {
@@ -332,8 +254,8 @@ static int dp83867_config(struct phy_device *phydev)
* register's bit 11 (marked as RESERVED).
*/
- bs = phy_read_mmd_indirect(phydev, DP83867_STRAP_STS1,
- DP83867_DEVADDR, phydev->addr);
+ bs = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_STRAP_STS1);
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL);
if (bs & DP83867_STRAP_STS1_RESERVED) {
val &= ~DP83867_PHYCR_RESERVED_MASK;
@@ -354,8 +276,8 @@ static int dp83867_config(struct phy_device *phydev)
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_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIICTL, 0x0);
phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
DP83867_PHYCTRL_SGMIIEN |
@@ -367,8 +289,8 @@ static int dp83867_config(struct phy_device *phydev)
}
if (phy_interface_is_rgmii(phydev)) {
- val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
- DP83867_DEVADDR, phydev->addr);
+ val = phy_read_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIICTL);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
val |= (DP83867_RGMII_TX_CLK_DELAY_EN |
@@ -380,26 +302,24 @@ static int dp83867_config(struct phy_device *phydev)
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);
+ 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_indirect(phydev, DP83867_RGMIIDCTL,
- DP83867_DEVADDR, phydev->addr, delay);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_RGMIIDCTL, delay);
if (dp83867->io_impedance >= 0) {
- val = phy_read_mmd_indirect(phydev,
- DP83867_IO_MUX_CFG,
- DP83867_DEVADDR,
- phydev->addr);
+ 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_indirect(phydev, DP83867_IO_MUX_CFG,
- DP83867_DEVADDR, phydev->addr,
- val);
+ phy_write_mmd(phydev, DP83867_DEVADDR,
+ DP83867_IO_MUX_CFG, val);
}
}
diff --git a/include/phy.h b/include/phy.h
index f23ca63f3b..d01435d1aa 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -101,6 +101,14 @@ struct phy_driver {
int (*readext)(struct phy_device *phydev, int addr, int devad, int reg);
int (*writeext)(struct phy_device *phydev, int addr, int devad, int reg,
u16 val);
+
+ /* Phy specific driver override for reading a MMD register */
+ int (*read_mmd)(struct phy_device *phydev, int devad, int reg);
+
+ /* Phy specific driver override for writing a MMD register */
+ int (*write_mmd)(struct phy_device *phydev, int devad, int reg,
+ u16 val);
+
struct list_head list;
};
@@ -165,6 +173,68 @@ static inline int phy_write(struct phy_device *phydev, int devad, int regnum,
return bus->write(bus, phydev->addr, devad, regnum, val);
}
+static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad,
+ int regnum)
+{
+ /* Write the desired MMD Devad */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad);
+
+ /* Write the desired MMD register address */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum);
+
+ /* Select the Function : DATA with no post increment */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL,
+ (devad | MII_MMD_CTRL_NOINCR));
+}
+
+static inline int phy_read_mmd(struct phy_device *phydev, int devad,
+ int regnum)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ /* driver-specific access */
+ if (drv->read_mmd)
+ return drv->read_mmd(phydev, devad, regnum);
+
+ /* direct C45 / C22 access */
+ if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
+ devad == MDIO_DEVAD_NONE || !devad)
+ return phy_read(phydev, devad, regnum);
+
+ /* indirect C22 access */
+ phy_mmd_start_indirect(phydev, devad, regnum);
+
+ /* Read the content of the MMD's selected register */
+ return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA);
+}
+
+static inline int phy_write_mmd(struct phy_device *phydev, int devad,
+ int regnum, u16 val)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (regnum > (u16)~0 || devad > 32)
+ return -EINVAL;
+
+ /* driver-specific access */
+ if (drv->write_mmd)
+ return drv->write_mmd(phydev, devad, regnum, val);
+
+ /* direct C45 / C22 access */
+ if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES ||
+ devad == MDIO_DEVAD_NONE || !devad)
+ return phy_write(phydev, devad, regnum, val);
+
+ /* indirect C22 access */
+ phy_mmd_start_indirect(phydev, devad, regnum);
+
+ /* Write the data into MMD's selected register */
+ return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val);
+}
+
#ifdef CONFIG_PHYLIB_10G
extern struct phy_driver gen10g_driver;