提交 c3152d47 编写于 作者: L Lendacky, Thomas 提交者: David S. Miller

amd-xgbe-phy: Change auto-negotiation logic

The auto negotiation logic was geared to being the initiator of the
auto negotiation. This presented problems when auto negotiation was
initiated by the remote end. Change the auto negotiation logic to
make use of the auto negotiation event interrupt thus allowing the
auto negotiation state machine to function properly in either scenario.
This also removes the polling during auto-negotiation.
Signed-off-by: NTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 a83ef427
...@@ -7,6 +7,9 @@ Required properties: ...@@ -7,6 +7,9 @@ Required properties:
- SerDes Rx/Tx registers - SerDes Rx/Tx registers
- SerDes integration registers (1/2) - SerDes integration registers (1/2)
- SerDes integration registers (2/2) - SerDes integration registers (2/2)
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the amd-xgbe-phy interrupt.
Optional properties: Optional properties:
- amd,speed-set: Speed capabilities of the device - amd,speed-set: Speed capabilities of the device
...@@ -19,5 +22,7 @@ Example: ...@@ -19,5 +22,7 @@ Example:
reg = <0 0xe1240800 0 0x00400>, reg = <0 0xe1240800 0 0x00400>,
<0 0xe1250000 0 0x00060>, <0 0xe1250000 0 0x00060>,
<0 0xe1250080 0 0x00004>; <0 0xe1250080 0 0x00004>;
interrupt-parent = <&gic>;
interrupts = <0 323 4>;
amd,speed-set = <0>; amd,speed-set = <0>;
}; };
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
*/ */
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/mdio.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/bitrev.h> #include <linux/bitrev.h>
#include <linux/crc32.h> #include <linux/crc32.h>
...@@ -673,6 +674,9 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata) ...@@ -673,6 +674,9 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata)
static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata) static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
{ {
if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3)
return 0;
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3); XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3);
return 0; return 0;
...@@ -680,6 +684,9 @@ static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata) ...@@ -680,6 +684,9 @@ static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata) static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata)
{ {
if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2)
return 0;
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2); XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2);
return 0; return 0;
...@@ -687,6 +694,9 @@ static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata) ...@@ -687,6 +694,9 @@ static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata)
static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata) static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata)
{ {
if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0)
return 0;
XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0); XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0);
return 0; return 0;
...@@ -881,6 +891,23 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad, ...@@ -881,6 +891,23 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
else else
mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
/* If the PCS is changing modes, match the MAC speed to it */
if (((mmd_address >> 16) == MDIO_MMD_PCS) &&
((mmd_address & 0xffff) == MDIO_CTRL2)) {
struct phy_device *phydev = pdata->phydev;
if (mmd_data & MDIO_PCS_CTRL2_TYPE) {
/* KX mode */
if (phydev->supported & SUPPORTED_1000baseKX_Full)
xgbe_set_gmii_speed(pdata);
else
xgbe_set_gmii_2500_speed(pdata);
} else {
/* KR mode */
xgbe_set_xgmii_speed(pdata);
}
}
/* The PCS registers are accessed using mmio. The underlying APB3 /* The PCS registers are accessed using mmio. The underlying APB3
* management interface uses indirect addressing to access the MMD * management interface uses indirect addressing to access the MMD
* register sets. This requires accessing of the PCS register in two * register sets. This requires accessing of the PCS register in two
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册