mirror of
https://github.com/torvalds/linux.git
synced 2024-12-05 02:23:16 +00:00
amd-xgbe: Move the PHY support into amd-xgbe
The AMD XGBE device is intended to work with a specific integrated PHY and that PHY is not meant to be a standalone PHY for use by other devices. As such this patch removes the phylib driver and implements the PHY support in the amd-xgbe driver (the majority of the logic from the phylib driver is moved into the amd-xgbe driver). Update the driver version to 1.0.1. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7d9ca345b5
commit
7c12aa0877
@ -1,48 +0,0 @@
|
||||
* AMD 10GbE PHY driver (amd-xgbe-phy)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "amd,xgbe-phy-seattle-v1a" and
|
||||
"ethernet-phy-ieee802.3-c45"
|
||||
- reg: Address and length of the register sets for the device
|
||||
- SerDes Rx/Tx registers
|
||||
- SerDes integration registers (1/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:
|
||||
- amd,speed-set: Speed capabilities of the device
|
||||
0 - 1GbE and 10GbE (default)
|
||||
1 - 2.5GbE and 10GbE
|
||||
|
||||
The following optional properties are represented by an array with each
|
||||
value corresponding to a particular speed. The first array value represents
|
||||
the setting for the 1GbE speed, the second value for the 2.5GbE speed and
|
||||
the third value for the 10GbE speed. All three values are required if the
|
||||
property is used.
|
||||
- amd,serdes-blwc: Baseline wandering correction enablement
|
||||
0 - Off
|
||||
1 - On
|
||||
- amd,serdes-cdr-rate: CDR rate speed selection
|
||||
- amd,serdes-pq-skew: PQ (data sampling) skew
|
||||
- amd,serdes-tx-amp: TX amplitude boost
|
||||
- amd,serdes-dfe-tap-config: DFE taps available to run
|
||||
- amd,serdes-dfe-tap-enable: DFE taps to enable
|
||||
|
||||
Example:
|
||||
xgbe_phy@e1240800 {
|
||||
compatible = "amd,xgbe-phy-seattle-v1a", "ethernet-phy-ieee802.3-c45";
|
||||
reg = <0 0xe1240800 0 0x00400>,
|
||||
<0 0xe1250000 0 0x00060>,
|
||||
<0 0xe1250080 0 0x00004>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 323 4>;
|
||||
amd,speed-set = <0>;
|
||||
amd,serdes-blwc = <1>, <1>, <0>;
|
||||
amd,serdes-cdr-rate = <2>, <2>, <7>;
|
||||
amd,serdes-pq-skew = <10>, <10>, <30>;
|
||||
amd,serdes-tx-amp = <15>, <15>, <10>;
|
||||
amd,serdes-dfe-tap-config = <3>, <3>, <1>;
|
||||
amd,serdes-dfe-tap-enable = <0>, <0>, <127>;
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
* AMD 10GbE driver (amd-xgbe)
|
||||
|
||||
Required properties:
|
||||
Required properties (ethernet device):
|
||||
- compatible: Should be "amd,xgbe-seattle-v1a"
|
||||
- reg: Address and length of the register sets for the device
|
||||
- MAC registers
|
||||
@ -22,7 +22,7 @@ Required properties:
|
||||
- phy-handle: See ethernet.txt file in the same directory
|
||||
- phy-mode: See ethernet.txt file in the same directory
|
||||
|
||||
Optional properties:
|
||||
Optional properties (ethernet device):
|
||||
- mac-address: mac address to be assigned to the device. Can be overridden
|
||||
by UEFI.
|
||||
- dma-coherent: Present if dma operations are coherent
|
||||
@ -30,6 +30,35 @@ Optional properties:
|
||||
a unique interrupt for each DMA channel - this requires an additional
|
||||
interrupt be configured for each DMA channel
|
||||
|
||||
Required properties (phy device):
|
||||
- compatible: Should be "amd,xgbe-phy-seattle-v1a"
|
||||
- reg: Address and length of the register sets for the device
|
||||
- SerDes Rx/Tx registers
|
||||
- SerDes integration registers (1/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 (phy device):
|
||||
- amd,speed-set: Speed capabilities of the device
|
||||
0 - 1GbE and 10GbE (default)
|
||||
1 - 2.5GbE and 10GbE
|
||||
|
||||
The following optional properties are represented by an array with each
|
||||
value corresponding to a particular speed. The first array value represents
|
||||
the setting for the 1GbE speed, the second value for the 2.5GbE speed and
|
||||
the third value for the 10GbE speed. All three values are required if the
|
||||
property is used.
|
||||
- amd,serdes-blwc: Baseline wandering correction enablement
|
||||
0 - Off
|
||||
1 - On
|
||||
- amd,serdes-cdr-rate: CDR rate speed selection
|
||||
- amd,serdes-pq-skew: PQ (data sampling) skew
|
||||
- amd,serdes-tx-amp: TX amplitude boost
|
||||
- amd,serdes-dfe-tap-config: DFE taps available to run
|
||||
- amd,serdes-dfe-tap-enable: DFE taps to enable
|
||||
|
||||
Example:
|
||||
xgbe@e0700000 {
|
||||
compatible = "amd,xgbe-seattle-v1a";
|
||||
@ -41,7 +70,23 @@ Example:
|
||||
amd,per-channel-interrupt;
|
||||
clocks = <&xgbe_dma_clk>, <&xgbe_ptp_clk>;
|
||||
clock-names = "dma_clk", "ptp_clk";
|
||||
phy-handle = <&phy>;
|
||||
phy-handle = <&xgbe_phy>;
|
||||
phy-mode = "xgmii";
|
||||
mac-address = [ 02 a1 a2 a3 a4 a5 ];
|
||||
};
|
||||
|
||||
xgbe_phy@e1240800 {
|
||||
compatible = "amd,xgbe-phy-seattle-v1a";
|
||||
reg = <0 0xe1240800 0 0x00400>,
|
||||
<0 0xe1250000 0 0x00060>,
|
||||
<0 0xe1250080 0 0x00004>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <0 323 4>;
|
||||
amd,speed-set = <0>;
|
||||
amd,serdes-blwc = <1>, <1>, <0>;
|
||||
amd,serdes-cdr-rate = <2>, <2>, <7>;
|
||||
amd,serdes-pq-skew = <10>, <10>, <30>;
|
||||
amd,serdes-tx-amp = <15>, <15>, <10>;
|
||||
amd,serdes-dfe-tap-config = <3>, <3>, <1>;
|
||||
amd,serdes-dfe-tap-enable = <0>, <0>, <127>;
|
||||
};
|
||||
|
@ -652,7 +652,6 @@ M: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/amd/xgbe/
|
||||
F: drivers/net/phy/amd-xgbe-phy.c
|
||||
|
||||
AMS (Apple Motion Sensor) DRIVER
|
||||
M: Michael Hanselmann <linux-kernel@hansmi.ch>
|
||||
|
@ -179,10 +179,8 @@ config SUNLANCE
|
||||
|
||||
config AMD_XGBE
|
||||
tristate "AMD 10GbE Ethernet driver"
|
||||
depends on (OF_NET || ACPI) && HAS_IOMEM && HAS_DMA
|
||||
depends on ((OF_NET && OF_ADDRESS) || ACPI) && HAS_IOMEM && HAS_DMA
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
select PHYLIB
|
||||
select AMD_XGBE_PHY
|
||||
select BITREVERSE
|
||||
select CRC32
|
||||
select PTP_1588_CLOCK
|
||||
|
@ -857,6 +857,48 @@
|
||||
*/
|
||||
#define PCS_MMD_SELECT 0xff
|
||||
|
||||
/* SerDes integration register offsets */
|
||||
#define SIR0_KR_RT_1 0x002c
|
||||
#define SIR0_STATUS 0x0040
|
||||
#define SIR1_SPEED 0x0000
|
||||
|
||||
/* SerDes integration register entry bit positions and sizes */
|
||||
#define SIR0_KR_RT_1_RESET_INDEX 11
|
||||
#define SIR0_KR_RT_1_RESET_WIDTH 1
|
||||
#define SIR0_STATUS_RX_READY_INDEX 0
|
||||
#define SIR0_STATUS_RX_READY_WIDTH 1
|
||||
#define SIR0_STATUS_TX_READY_INDEX 8
|
||||
#define SIR0_STATUS_TX_READY_WIDTH 1
|
||||
#define SIR1_SPEED_CDR_RATE_INDEX 12
|
||||
#define SIR1_SPEED_CDR_RATE_WIDTH 4
|
||||
#define SIR1_SPEED_DATARATE_INDEX 4
|
||||
#define SIR1_SPEED_DATARATE_WIDTH 2
|
||||
#define SIR1_SPEED_PLLSEL_INDEX 3
|
||||
#define SIR1_SPEED_PLLSEL_WIDTH 1
|
||||
#define SIR1_SPEED_RATECHANGE_INDEX 6
|
||||
#define SIR1_SPEED_RATECHANGE_WIDTH 1
|
||||
#define SIR1_SPEED_TXAMP_INDEX 8
|
||||
#define SIR1_SPEED_TXAMP_WIDTH 4
|
||||
#define SIR1_SPEED_WORDMODE_INDEX 0
|
||||
#define SIR1_SPEED_WORDMODE_WIDTH 3
|
||||
|
||||
/* SerDes RxTx register offsets */
|
||||
#define RXTX_REG6 0x0018
|
||||
#define RXTX_REG20 0x0050
|
||||
#define RXTX_REG22 0x0058
|
||||
#define RXTX_REG114 0x01c8
|
||||
#define RXTX_REG129 0x0204
|
||||
|
||||
/* SerDes RxTx register entry bit positions and sizes */
|
||||
#define RXTX_REG6_RESETB_RXD_INDEX 8
|
||||
#define RXTX_REG6_RESETB_RXD_WIDTH 1
|
||||
#define RXTX_REG20_BLWC_ENA_INDEX 2
|
||||
#define RXTX_REG20_BLWC_ENA_WIDTH 1
|
||||
#define RXTX_REG114_PQ_REG_INDEX 9
|
||||
#define RXTX_REG114_PQ_REG_WIDTH 7
|
||||
#define RXTX_REG129_RXDFE_CONFIG_INDEX 14
|
||||
#define RXTX_REG129_RXDFE_CONFIG_WIDTH 2
|
||||
|
||||
/* Descriptor/Packet entry bit positions and sizes */
|
||||
#define RX_PACKET_ERRORS_CRC_INDEX 2
|
||||
#define RX_PACKET_ERRORS_CRC_WIDTH 1
|
||||
@ -973,10 +1015,47 @@
|
||||
#define TX_NORMAL_DESC2_VLAN_INSERT 0x2
|
||||
|
||||
/* MDIO undefined or vendor specific registers */
|
||||
#ifndef MDIO_PMA_10GBR_PMD_CTRL
|
||||
#define MDIO_PMA_10GBR_PMD_CTRL 0x0096
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_PMA_10GBR_FECCTRL
|
||||
#define MDIO_PMA_10GBR_FECCTRL 0x00ab
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_XNP
|
||||
#define MDIO_AN_XNP 0x0016
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_LPX
|
||||
#define MDIO_AN_LPX 0x0019
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_COMP_STAT
|
||||
#define MDIO_AN_COMP_STAT 0x0030
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_INTMASK
|
||||
#define MDIO_AN_INTMASK 0x8001
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_AN_INT
|
||||
#define MDIO_AN_INT 0x8002
|
||||
#endif
|
||||
|
||||
#ifndef MDIO_CTRL1_SPEED1G
|
||||
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
|
||||
#endif
|
||||
|
||||
/* MDIO mask values */
|
||||
#define XGBE_XNP_MCF_NULL_MESSAGE 0x001
|
||||
#define XGBE_XNP_ACK_PROCESSED BIT(12)
|
||||
#define XGBE_XNP_MP_FORMATTED BIT(13)
|
||||
#define XGBE_XNP_NP_EXCHANGE BIT(15)
|
||||
|
||||
#define XGBE_KR_TRAINING_START BIT(0)
|
||||
#define XGBE_KR_TRAINING_ENABLE BIT(1)
|
||||
|
||||
/* Bit setting and getting macros
|
||||
* The get macro will extract the current bit field value from within
|
||||
* the variable
|
||||
@ -1118,6 +1197,82 @@ do { \
|
||||
#define XPCS_IOREAD(_pdata, _off) \
|
||||
ioread32((_pdata)->xpcs_regs + (_off))
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* within the register values of SerDes integration registers.
|
||||
*/
|
||||
#define XSIR_GET_BITS(_var, _prefix, _field) \
|
||||
GET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH)
|
||||
|
||||
#define XSIR_SET_BITS(_var, _prefix, _field, _val) \
|
||||
SET_BITS((_var), \
|
||||
_prefix##_##_field##_INDEX, \
|
||||
_prefix##_##_field##_WIDTH, (_val))
|
||||
|
||||
#define XSIR0_IOREAD(_pdata, _reg) \
|
||||
ioread16((_pdata)->sir0_regs + _reg)
|
||||
|
||||
#define XSIR0_IOREAD_BITS(_pdata, _reg, _field) \
|
||||
GET_BITS(XSIR0_IOREAD((_pdata), _reg), \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH)
|
||||
|
||||
#define XSIR0_IOWRITE(_pdata, _reg, _val) \
|
||||
iowrite16((_val), (_pdata)->sir0_regs + _reg)
|
||||
|
||||
#define XSIR0_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u16 reg_val = XSIR0_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
XSIR0_IOWRITE((_pdata), _reg, reg_val); \
|
||||
} while (0)
|
||||
|
||||
#define XSIR1_IOREAD(_pdata, _reg) \
|
||||
ioread16((_pdata)->sir1_regs + _reg)
|
||||
|
||||
#define XSIR1_IOREAD_BITS(_pdata, _reg, _field) \
|
||||
GET_BITS(XSIR1_IOREAD((_pdata), _reg), \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH)
|
||||
|
||||
#define XSIR1_IOWRITE(_pdata, _reg, _val) \
|
||||
iowrite16((_val), (_pdata)->sir1_regs + _reg)
|
||||
|
||||
#define XSIR1_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u16 reg_val = XSIR1_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
XSIR1_IOWRITE((_pdata), _reg, reg_val); \
|
||||
} while (0)
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* within the register values of SerDes RxTx registers.
|
||||
*/
|
||||
#define XRXTX_IOREAD(_pdata, _reg) \
|
||||
ioread16((_pdata)->rxtx_regs + _reg)
|
||||
|
||||
#define XRXTX_IOREAD_BITS(_pdata, _reg, _field) \
|
||||
GET_BITS(XRXTX_IOREAD((_pdata), _reg), \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH)
|
||||
|
||||
#define XRXTX_IOWRITE(_pdata, _reg, _val) \
|
||||
iowrite16((_val), (_pdata)->rxtx_regs + _reg)
|
||||
|
||||
#define XRXTX_IOWRITE_BITS(_pdata, _reg, _field, _val) \
|
||||
do { \
|
||||
u16 reg_val = XRXTX_IOREAD((_pdata), _reg); \
|
||||
SET_BITS(reg_val, \
|
||||
_reg##_##_field##_INDEX, \
|
||||
_reg##_##_field##_WIDTH, (_val)); \
|
||||
XRXTX_IOWRITE((_pdata), _reg, reg_val); \
|
||||
} while (0)
|
||||
|
||||
/* Macros for building, reading or writing register values or bits
|
||||
* using MDIO. Different from above because of the use of standardized
|
||||
* Linux include values. No shifting is performed with the bit
|
||||
|
@ -910,23 +910,6 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
|
||||
else
|
||||
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
|
||||
* management interface uses indirect addressing to access the MMD
|
||||
* register sets. This requires accessing of the PCS register in two
|
||||
|
@ -437,12 +437,31 @@ static void xgbe_tx_timer(unsigned long data)
|
||||
DBGPR("<--xgbe_tx_timer\n");
|
||||
}
|
||||
|
||||
static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata)
|
||||
static void xgbe_service(struct work_struct *work)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = container_of(work,
|
||||
struct xgbe_prv_data,
|
||||
service_work);
|
||||
|
||||
pdata->phy_if.phy_status(pdata);
|
||||
}
|
||||
|
||||
static void xgbe_service_timer(unsigned long data)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
|
||||
|
||||
schedule_work(&pdata->service_work);
|
||||
|
||||
mod_timer(&pdata->service_timer, jiffies + HZ);
|
||||
}
|
||||
|
||||
static void xgbe_init_timers(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_channel *channel;
|
||||
unsigned int i;
|
||||
|
||||
DBGPR("-->xgbe_init_tx_timers\n");
|
||||
setup_timer(&pdata->service_timer, xgbe_service_timer,
|
||||
(unsigned long)pdata);
|
||||
|
||||
channel = pdata->channel;
|
||||
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||
@ -452,16 +471,19 @@ static void xgbe_init_tx_timers(struct xgbe_prv_data *pdata)
|
||||
setup_timer(&channel->tx_timer, xgbe_tx_timer,
|
||||
(unsigned long)channel);
|
||||
}
|
||||
|
||||
DBGPR("<--xgbe_init_tx_timers\n");
|
||||
}
|
||||
|
||||
static void xgbe_stop_tx_timers(struct xgbe_prv_data *pdata)
|
||||
static void xgbe_start_timers(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
mod_timer(&pdata->service_timer, jiffies + HZ);
|
||||
}
|
||||
|
||||
static void xgbe_stop_timers(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_channel *channel;
|
||||
unsigned int i;
|
||||
|
||||
DBGPR("-->xgbe_stop_tx_timers\n");
|
||||
del_timer_sync(&pdata->service_timer);
|
||||
|
||||
channel = pdata->channel;
|
||||
for (i = 0; i < pdata->channel_count; i++, channel++) {
|
||||
@ -470,8 +492,6 @@ static void xgbe_stop_tx_timers(struct xgbe_prv_data *pdata)
|
||||
|
||||
del_timer_sync(&channel->tx_timer);
|
||||
}
|
||||
|
||||
DBGPR("<--xgbe_stop_tx_timers\n");
|
||||
}
|
||||
|
||||
void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
|
||||
@ -758,113 +778,14 @@ static void xgbe_free_rx_data(struct xgbe_prv_data *pdata)
|
||||
DBGPR("<--xgbe_free_rx_data\n");
|
||||
}
|
||||
|
||||
static void xgbe_adjust_link(struct net_device *netdev)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
struct phy_device *phydev = pdata->phydev;
|
||||
int new_state = 0;
|
||||
|
||||
if (!phydev)
|
||||
return;
|
||||
|
||||
if (phydev->link) {
|
||||
/* Flow control support */
|
||||
if (pdata->pause_autoneg) {
|
||||
if (phydev->pause || phydev->asym_pause) {
|
||||
pdata->tx_pause = 1;
|
||||
pdata->rx_pause = 1;
|
||||
} else {
|
||||
pdata->tx_pause = 0;
|
||||
pdata->rx_pause = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pdata->tx_pause != pdata->phy_tx_pause) {
|
||||
hw_if->config_tx_flow_control(pdata);
|
||||
pdata->phy_tx_pause = pdata->tx_pause;
|
||||
}
|
||||
|
||||
if (pdata->rx_pause != pdata->phy_rx_pause) {
|
||||
hw_if->config_rx_flow_control(pdata);
|
||||
pdata->phy_rx_pause = pdata->rx_pause;
|
||||
}
|
||||
|
||||
/* Speed support */
|
||||
if (phydev->speed != pdata->phy_speed) {
|
||||
new_state = 1;
|
||||
|
||||
switch (phydev->speed) {
|
||||
case SPEED_10000:
|
||||
hw_if->set_xgmii_speed(pdata);
|
||||
break;
|
||||
|
||||
case SPEED_2500:
|
||||
hw_if->set_gmii_2500_speed(pdata);
|
||||
break;
|
||||
|
||||
case SPEED_1000:
|
||||
hw_if->set_gmii_speed(pdata);
|
||||
break;
|
||||
}
|
||||
pdata->phy_speed = phydev->speed;
|
||||
}
|
||||
|
||||
if (phydev->link != pdata->phy_link) {
|
||||
new_state = 1;
|
||||
pdata->phy_link = 1;
|
||||
}
|
||||
} else if (pdata->phy_link) {
|
||||
new_state = 1;
|
||||
pdata->phy_link = 0;
|
||||
pdata->phy_speed = SPEED_UNKNOWN;
|
||||
}
|
||||
|
||||
if (new_state)
|
||||
phy_print_status(phydev);
|
||||
}
|
||||
|
||||
static int xgbe_phy_init(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct net_device *netdev = pdata->netdev;
|
||||
struct phy_device *phydev = pdata->phydev;
|
||||
int ret;
|
||||
|
||||
pdata->phy_link = -1;
|
||||
pdata->phy_speed = SPEED_UNKNOWN;
|
||||
pdata->phy_tx_pause = pdata->tx_pause;
|
||||
pdata->phy_rx_pause = pdata->rx_pause;
|
||||
|
||||
ret = phy_connect_direct(netdev, phydev, &xgbe_adjust_link,
|
||||
pdata->phy_mode);
|
||||
if (ret) {
|
||||
netdev_err(netdev, "phy_connect_direct failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!phydev->drv || (phydev->drv->phy_id == 0)) {
|
||||
netdev_err(netdev, "phy_id not valid\n");
|
||||
ret = -ENODEV;
|
||||
goto err_phy_connect;
|
||||
}
|
||||
netif_dbg(pdata, ifup, pdata->netdev,
|
||||
"phy_connect_direct succeeded for PHY %s\n",
|
||||
dev_name(&phydev->dev));
|
||||
|
||||
return 0;
|
||||
|
||||
err_phy_connect:
|
||||
phy_disconnect(phydev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
if (!pdata->phydev)
|
||||
return;
|
||||
|
||||
phy_disconnect(pdata->phydev);
|
||||
return pdata->phy_if.phy_reset(pdata);
|
||||
}
|
||||
|
||||
int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
|
||||
@ -889,13 +810,14 @@ int xgbe_powerdown(struct net_device *netdev, unsigned int caller)
|
||||
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
xgbe_stop_timers(pdata);
|
||||
flush_workqueue(pdata->dev_workqueue);
|
||||
|
||||
hw_if->powerdown_tx(pdata);
|
||||
hw_if->powerdown_rx(pdata);
|
||||
|
||||
xgbe_napi_disable(pdata, 0);
|
||||
|
||||
phy_stop(pdata->phydev);
|
||||
|
||||
pdata->power_down = 1;
|
||||
|
||||
spin_unlock_irqrestore(&pdata->lock, flags);
|
||||
@ -924,8 +846,6 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller)
|
||||
|
||||
pdata->power_down = 0;
|
||||
|
||||
phy_start(pdata->phydev);
|
||||
|
||||
xgbe_napi_enable(pdata, 0);
|
||||
|
||||
hw_if->powerup_tx(pdata);
|
||||
@ -936,6 +856,8 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller)
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
xgbe_start_timers(pdata);
|
||||
|
||||
spin_unlock_irqrestore(&pdata->lock, flags);
|
||||
|
||||
DBGPR("<--xgbe_powerup\n");
|
||||
@ -946,6 +868,7 @@ int xgbe_powerup(struct net_device *netdev, unsigned int caller)
|
||||
static int xgbe_start(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
struct xgbe_phy_if *phy_if = &pdata->phy_if;
|
||||
struct net_device *netdev = pdata->netdev;
|
||||
int ret;
|
||||
|
||||
@ -953,7 +876,9 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
|
||||
|
||||
hw_if->init(pdata);
|
||||
|
||||
phy_start(pdata->phydev);
|
||||
ret = phy_if->phy_start(pdata);
|
||||
if (ret)
|
||||
goto err_phy;
|
||||
|
||||
xgbe_napi_enable(pdata, 1);
|
||||
|
||||
@ -964,10 +889,11 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
|
||||
hw_if->enable_tx(pdata);
|
||||
hw_if->enable_rx(pdata);
|
||||
|
||||
xgbe_init_tx_timers(pdata);
|
||||
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
xgbe_start_timers(pdata);
|
||||
schedule_work(&pdata->service_work);
|
||||
|
||||
DBGPR("<--xgbe_start\n");
|
||||
|
||||
return 0;
|
||||
@ -975,8 +901,9 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
|
||||
err_napi:
|
||||
xgbe_napi_disable(pdata, 1);
|
||||
|
||||
phy_stop(pdata->phydev);
|
||||
phy_if->phy_stop(pdata);
|
||||
|
||||
err_phy:
|
||||
hw_if->exit(pdata);
|
||||
|
||||
return ret;
|
||||
@ -985,6 +912,7 @@ err_napi:
|
||||
static void xgbe_stop(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct xgbe_hw_if *hw_if = &pdata->hw_if;
|
||||
struct xgbe_phy_if *phy_if = &pdata->phy_if;
|
||||
struct xgbe_channel *channel;
|
||||
struct net_device *netdev = pdata->netdev;
|
||||
struct netdev_queue *txq;
|
||||
@ -994,7 +922,8 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
|
||||
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
xgbe_stop_tx_timers(pdata);
|
||||
xgbe_stop_timers(pdata);
|
||||
flush_workqueue(pdata->dev_workqueue);
|
||||
|
||||
hw_if->disable_tx(pdata);
|
||||
hw_if->disable_rx(pdata);
|
||||
@ -1003,7 +932,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata)
|
||||
|
||||
xgbe_napi_disable(pdata, 1);
|
||||
|
||||
phy_stop(pdata->phydev);
|
||||
phy_if->phy_stop(pdata);
|
||||
|
||||
hw_if->exit(pdata);
|
||||
|
||||
@ -1374,7 +1303,7 @@ static int xgbe_open(struct net_device *netdev)
|
||||
ret = clk_prepare_enable(pdata->sysclk);
|
||||
if (ret) {
|
||||
netdev_alert(netdev, "dma clk_prepare_enable failed\n");
|
||||
goto err_phy_init;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pdata->ptpclk);
|
||||
@ -1399,14 +1328,17 @@ static int xgbe_open(struct net_device *netdev)
|
||||
if (ret)
|
||||
goto err_channels;
|
||||
|
||||
/* Initialize the device restart and Tx timestamp work struct */
|
||||
INIT_WORK(&pdata->service_work, xgbe_service);
|
||||
INIT_WORK(&pdata->restart_work, xgbe_restart);
|
||||
INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
|
||||
xgbe_init_timers(pdata);
|
||||
|
||||
ret = xgbe_start(pdata);
|
||||
if (ret)
|
||||
goto err_rings;
|
||||
|
||||
clear_bit(XGBE_DOWN, &pdata->dev_state);
|
||||
|
||||
DBGPR("<--xgbe_open\n");
|
||||
|
||||
return 0;
|
||||
@ -1423,9 +1355,6 @@ err_ptpclk:
|
||||
err_sysclk:
|
||||
clk_disable_unprepare(pdata->sysclk);
|
||||
|
||||
err_phy_init:
|
||||
xgbe_phy_exit(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1449,8 +1378,7 @@ static int xgbe_close(struct net_device *netdev)
|
||||
clk_disable_unprepare(pdata->ptpclk);
|
||||
clk_disable_unprepare(pdata->sysclk);
|
||||
|
||||
/* Release the phy */
|
||||
xgbe_phy_exit(pdata);
|
||||
set_bit(XGBE_DOWN, &pdata->dev_state);
|
||||
|
||||
DBGPR("<--xgbe_close\n");
|
||||
|
||||
|
@ -258,7 +258,6 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
struct phy_device *phydev = pdata->phydev;
|
||||
int ret = 0;
|
||||
|
||||
DBGPR("-->xgbe_set_pauseparam\n");
|
||||
@ -268,19 +267,19 @@ static int xgbe_set_pauseparam(struct net_device *netdev,
|
||||
|
||||
pdata->pause_autoneg = pause->autoneg;
|
||||
if (pause->autoneg) {
|
||||
phydev->advertising |= ADVERTISED_Pause;
|
||||
phydev->advertising |= ADVERTISED_Asym_Pause;
|
||||
pdata->phy.advertising |= ADVERTISED_Pause;
|
||||
pdata->phy.advertising |= ADVERTISED_Asym_Pause;
|
||||
|
||||
} else {
|
||||
phydev->advertising &= ~ADVERTISED_Pause;
|
||||
phydev->advertising &= ~ADVERTISED_Asym_Pause;
|
||||
pdata->phy.advertising &= ~ADVERTISED_Pause;
|
||||
pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
|
||||
|
||||
pdata->tx_pause = pause->tx_pause;
|
||||
pdata->rx_pause = pause->rx_pause;
|
||||
}
|
||||
|
||||
if (netif_running(netdev))
|
||||
ret = phy_start_aneg(phydev);
|
||||
ret = pdata->phy_if.phy_config_aneg(pdata);
|
||||
|
||||
DBGPR("<--xgbe_set_pauseparam\n");
|
||||
|
||||
@ -291,36 +290,39 @@ static int xgbe_get_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
int ret;
|
||||
|
||||
DBGPR("-->xgbe_get_settings\n");
|
||||
|
||||
if (!pdata->phydev)
|
||||
return -ENODEV;
|
||||
cmd->phy_address = pdata->phy.address;
|
||||
|
||||
ret = phy_ethtool_gset(pdata->phydev, cmd);
|
||||
cmd->supported = pdata->phy.supported;
|
||||
cmd->advertising = pdata->phy.advertising;
|
||||
cmd->lp_advertising = pdata->phy.lp_advertising;
|
||||
|
||||
cmd->autoneg = pdata->phy.autoneg;
|
||||
ethtool_cmd_speed_set(cmd, pdata->phy.speed);
|
||||
cmd->duplex = pdata->phy.duplex;
|
||||
|
||||
cmd->port = PORT_NONE;
|
||||
cmd->transceiver = XCVR_INTERNAL;
|
||||
|
||||
DBGPR("<--xgbe_get_settings\n");
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xgbe_set_settings(struct net_device *netdev,
|
||||
struct ethtool_cmd *cmd)
|
||||
{
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
struct phy_device *phydev = pdata->phydev;
|
||||
u32 speed;
|
||||
int ret;
|
||||
|
||||
DBGPR("-->xgbe_set_settings\n");
|
||||
|
||||
if (!pdata->phydev)
|
||||
return -ENODEV;
|
||||
|
||||
speed = ethtool_cmd_speed(cmd);
|
||||
|
||||
if (cmd->phy_address != phydev->addr)
|
||||
if (cmd->phy_address != pdata->phy.address)
|
||||
return -EINVAL;
|
||||
|
||||
if ((cmd->autoneg != AUTONEG_ENABLE) &&
|
||||
@ -341,23 +343,23 @@ static int xgbe_set_settings(struct net_device *netdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd->advertising &= phydev->supported;
|
||||
cmd->advertising &= pdata->phy.supported;
|
||||
if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising)
|
||||
return -EINVAL;
|
||||
|
||||
ret = 0;
|
||||
phydev->autoneg = cmd->autoneg;
|
||||
phydev->speed = speed;
|
||||
phydev->duplex = cmd->duplex;
|
||||
phydev->advertising = cmd->advertising;
|
||||
pdata->phy.autoneg = cmd->autoneg;
|
||||
pdata->phy.speed = speed;
|
||||
pdata->phy.duplex = cmd->duplex;
|
||||
pdata->phy.advertising = cmd->advertising;
|
||||
|
||||
if (cmd->autoneg == AUTONEG_ENABLE)
|
||||
phydev->advertising |= ADVERTISED_Autoneg;
|
||||
pdata->phy.advertising |= ADVERTISED_Autoneg;
|
||||
else
|
||||
phydev->advertising &= ~ADVERTISED_Autoneg;
|
||||
pdata->phy.advertising &= ~ADVERTISED_Autoneg;
|
||||
|
||||
if (netif_running(netdev))
|
||||
ret = phy_start_aneg(phydev);
|
||||
ret = pdata->phy_if.phy_config_aneg(pdata);
|
||||
|
||||
DBGPR("<--xgbe_set_settings\n");
|
||||
|
||||
|
@ -124,9 +124,11 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/mdio.h>
|
||||
|
||||
#include "xgbe.h"
|
||||
#include "xgbe-common.h"
|
||||
@ -143,6 +145,42 @@ MODULE_PARM_DESC(debug, " Network interface message level setting");
|
||||
static const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
|
||||
NETIF_MSG_IFUP);
|
||||
|
||||
static const u32 xgbe_serdes_blwc[] = {
|
||||
XGBE_SPEED_1000_BLWC,
|
||||
XGBE_SPEED_2500_BLWC,
|
||||
XGBE_SPEED_10000_BLWC,
|
||||
};
|
||||
|
||||
static const u32 xgbe_serdes_cdr_rate[] = {
|
||||
XGBE_SPEED_1000_CDR,
|
||||
XGBE_SPEED_2500_CDR,
|
||||
XGBE_SPEED_10000_CDR,
|
||||
};
|
||||
|
||||
static const u32 xgbe_serdes_pq_skew[] = {
|
||||
XGBE_SPEED_1000_PQ,
|
||||
XGBE_SPEED_2500_PQ,
|
||||
XGBE_SPEED_10000_PQ,
|
||||
};
|
||||
|
||||
static const u32 xgbe_serdes_tx_amp[] = {
|
||||
XGBE_SPEED_1000_TXAMP,
|
||||
XGBE_SPEED_2500_TXAMP,
|
||||
XGBE_SPEED_10000_TXAMP,
|
||||
};
|
||||
|
||||
static const u32 xgbe_serdes_dfe_tap_cfg[] = {
|
||||
XGBE_SPEED_1000_DFE_TAP_CONFIG,
|
||||
XGBE_SPEED_2500_DFE_TAP_CONFIG,
|
||||
XGBE_SPEED_10000_DFE_TAP_CONFIG,
|
||||
};
|
||||
|
||||
static const u32 xgbe_serdes_dfe_tap_ena[] = {
|
||||
XGBE_SPEED_1000_DFE_TAP_ENABLE,
|
||||
XGBE_SPEED_2500_DFE_TAP_ENABLE,
|
||||
XGBE_SPEED_10000_DFE_TAP_ENABLE,
|
||||
};
|
||||
|
||||
static void xgbe_default_config(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
DBGPR("-->xgbe_default_config\n");
|
||||
@ -160,8 +198,6 @@ static void xgbe_default_config(struct xgbe_prv_data *pdata)
|
||||
pdata->rx_pause = 1;
|
||||
pdata->phy_speed = SPEED_UNKNOWN;
|
||||
pdata->power_down = 0;
|
||||
pdata->default_autoneg = AUTONEG_ENABLE;
|
||||
pdata->default_speed = SPEED_10000;
|
||||
|
||||
DBGPR("<--xgbe_default_config\n");
|
||||
}
|
||||
@ -169,6 +205,7 @@ static void xgbe_default_config(struct xgbe_prv_data *pdata)
|
||||
static void xgbe_init_all_fptrs(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
xgbe_init_function_ptrs_dev(&pdata->hw_if);
|
||||
xgbe_init_function_ptrs_phy(&pdata->phy_if);
|
||||
xgbe_init_function_ptrs_desc(&pdata->desc_if);
|
||||
}
|
||||
|
||||
@ -255,23 +292,75 @@ static int xgbe_of_support(struct xgbe_prv_data *pdata)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct device *dev = pdata->dev;
|
||||
struct device_node *phy_node;
|
||||
struct platform_device *phy_pdev;
|
||||
|
||||
phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);
|
||||
if (!phy_node) {
|
||||
dev_err(dev, "unable to locate phy device\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
phy_pdev = of_find_device_by_node(phy_node);
|
||||
of_node_put(phy_node);
|
||||
|
||||
return phy_pdev;
|
||||
}
|
||||
#else /* CONFIG_OF */
|
||||
static int xgbe_of_support(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /*CONFIG_OF */
|
||||
|
||||
static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static unsigned int xgbe_resource_count(struct platform_device *pdev,
|
||||
unsigned int type)
|
||||
{
|
||||
unsigned int count;
|
||||
int i;
|
||||
|
||||
for (i = 0, count = 0; i < pdev->num_resources; i++) {
|
||||
struct resource *res = &pdev->resource[i];
|
||||
|
||||
if (type == resource_type(res))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata)
|
||||
{
|
||||
struct platform_device *phy_pdev;
|
||||
|
||||
if (pdata->use_acpi) {
|
||||
get_device(pdata->dev);
|
||||
phy_pdev = pdata->pdev;
|
||||
} else {
|
||||
phy_pdev = xgbe_of_get_phy_pdev(pdata);
|
||||
}
|
||||
|
||||
return phy_pdev;
|
||||
}
|
||||
|
||||
static int xgbe_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct xgbe_prv_data *pdata;
|
||||
struct xgbe_hw_if *hw_if;
|
||||
struct xgbe_desc_if *desc_if;
|
||||
struct net_device *netdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device *dev = &pdev->dev, *phy_dev;
|
||||
struct platform_device *phy_pdev;
|
||||
struct resource *res;
|
||||
const char *phy_mode;
|
||||
unsigned int i;
|
||||
unsigned int i, phy_memnum, phy_irqnum;
|
||||
int ret;
|
||||
|
||||
DBGPR("--> xgbe_probe\n");
|
||||
@ -298,9 +387,34 @@ static int xgbe_probe(struct platform_device *pdev)
|
||||
|
||||
pdata->msg_enable = netif_msg_init(debug, default_msg_level);
|
||||
|
||||
set_bit(XGBE_DOWN, &pdata->dev_state);
|
||||
|
||||
/* Check if we should use ACPI or DT */
|
||||
pdata->use_acpi = (!pdata->adev || acpi_disabled) ? 0 : 1;
|
||||
|
||||
phy_pdev = xgbe_get_phy_pdev(pdata);
|
||||
if (!phy_pdev) {
|
||||
dev_err(dev, "unable to obtain phy device\n");
|
||||
ret = -EINVAL;
|
||||
goto err_phydev;
|
||||
}
|
||||
phy_dev = &phy_pdev->dev;
|
||||
|
||||
if (pdev == phy_pdev) {
|
||||
/* ACPI:
|
||||
* The XGBE and PHY resources are grouped together with
|
||||
* the PHY resources listed last
|
||||
*/
|
||||
phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
|
||||
phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1;
|
||||
} else {
|
||||
/* Device tree:
|
||||
* The XGBE and PHY resources are separate
|
||||
*/
|
||||
phy_memnum = 0;
|
||||
phy_irqnum = 0;
|
||||
}
|
||||
|
||||
/* Set and validate the number of descriptors for a ring */
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
|
||||
pdata->tx_desc_count = XGBE_TX_DESC_CNT;
|
||||
@ -340,6 +454,36 @@ static int xgbe_probe(struct platform_device *pdev)
|
||||
if (netif_msg_probe(pdata))
|
||||
dev_dbg(dev, "xpcs_regs = %p\n", pdata->xpcs_regs);
|
||||
|
||||
res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
|
||||
pdata->rxtx_regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pdata->rxtx_regs)) {
|
||||
dev_err(dev, "rxtx ioremap failed\n");
|
||||
ret = PTR_ERR(pdata->rxtx_regs);
|
||||
goto err_io;
|
||||
}
|
||||
if (netif_msg_probe(pdata))
|
||||
dev_dbg(dev, "rxtx_regs = %p\n", pdata->rxtx_regs);
|
||||
|
||||
res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
|
||||
pdata->sir0_regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pdata->sir0_regs)) {
|
||||
dev_err(dev, "sir0 ioremap failed\n");
|
||||
ret = PTR_ERR(pdata->sir0_regs);
|
||||
goto err_io;
|
||||
}
|
||||
if (netif_msg_probe(pdata))
|
||||
dev_dbg(dev, "sir0_regs = %p\n", pdata->sir0_regs);
|
||||
|
||||
res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
|
||||
pdata->sir1_regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pdata->sir1_regs)) {
|
||||
dev_err(dev, "sir1 ioremap failed\n");
|
||||
ret = PTR_ERR(pdata->sir1_regs);
|
||||
goto err_io;
|
||||
}
|
||||
if (netif_msg_probe(pdata))
|
||||
dev_dbg(dev, "sir1_regs = %p\n", pdata->sir1_regs);
|
||||
|
||||
/* Retrieve the MAC address */
|
||||
ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY,
|
||||
pdata->mac_addr,
|
||||
@ -366,6 +510,115 @@ static int xgbe_probe(struct platform_device *pdev)
|
||||
if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY))
|
||||
pdata->per_channel_irq = 1;
|
||||
|
||||
/* Retrieve the PHY speedset */
|
||||
ret = device_property_read_u32(phy_dev, XGBE_SPEEDSET_PROPERTY,
|
||||
&pdata->speed_set);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
switch (pdata->speed_set) {
|
||||
case XGBE_SPEEDSET_1000_10000:
|
||||
case XGBE_SPEEDSET_2500_10000:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
|
||||
ret = -EINVAL;
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
/* Retrieve the PHY configuration properties */
|
||||
if (device_property_present(phy_dev, XGBE_BLWC_PROPERTY)) {
|
||||
ret = device_property_read_u32_array(phy_dev,
|
||||
XGBE_BLWC_PROPERTY,
|
||||
pdata->serdes_blwc,
|
||||
XGBE_SPEEDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n",
|
||||
XGBE_BLWC_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
} else {
|
||||
memcpy(pdata->serdes_blwc, xgbe_serdes_blwc,
|
||||
sizeof(pdata->serdes_blwc));
|
||||
}
|
||||
|
||||
if (device_property_present(phy_dev, XGBE_CDR_RATE_PROPERTY)) {
|
||||
ret = device_property_read_u32_array(phy_dev,
|
||||
XGBE_CDR_RATE_PROPERTY,
|
||||
pdata->serdes_cdr_rate,
|
||||
XGBE_SPEEDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n",
|
||||
XGBE_CDR_RATE_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
} else {
|
||||
memcpy(pdata->serdes_cdr_rate, xgbe_serdes_cdr_rate,
|
||||
sizeof(pdata->serdes_cdr_rate));
|
||||
}
|
||||
|
||||
if (device_property_present(phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
|
||||
ret = device_property_read_u32_array(phy_dev,
|
||||
XGBE_PQ_SKEW_PROPERTY,
|
||||
pdata->serdes_pq_skew,
|
||||
XGBE_SPEEDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n",
|
||||
XGBE_PQ_SKEW_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
} else {
|
||||
memcpy(pdata->serdes_pq_skew, xgbe_serdes_pq_skew,
|
||||
sizeof(pdata->serdes_pq_skew));
|
||||
}
|
||||
|
||||
if (device_property_present(phy_dev, XGBE_TX_AMP_PROPERTY)) {
|
||||
ret = device_property_read_u32_array(phy_dev,
|
||||
XGBE_TX_AMP_PROPERTY,
|
||||
pdata->serdes_tx_amp,
|
||||
XGBE_SPEEDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n",
|
||||
XGBE_TX_AMP_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
} else {
|
||||
memcpy(pdata->serdes_tx_amp, xgbe_serdes_tx_amp,
|
||||
sizeof(pdata->serdes_tx_amp));
|
||||
}
|
||||
|
||||
if (device_property_present(phy_dev, XGBE_DFE_CFG_PROPERTY)) {
|
||||
ret = device_property_read_u32_array(phy_dev,
|
||||
XGBE_DFE_CFG_PROPERTY,
|
||||
pdata->serdes_dfe_tap_cfg,
|
||||
XGBE_SPEEDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n",
|
||||
XGBE_DFE_CFG_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
} else {
|
||||
memcpy(pdata->serdes_dfe_tap_cfg, xgbe_serdes_dfe_tap_cfg,
|
||||
sizeof(pdata->serdes_dfe_tap_cfg));
|
||||
}
|
||||
|
||||
if (device_property_present(phy_dev, XGBE_DFE_ENA_PROPERTY)) {
|
||||
ret = device_property_read_u32_array(phy_dev,
|
||||
XGBE_DFE_ENA_PROPERTY,
|
||||
pdata->serdes_dfe_tap_ena,
|
||||
XGBE_SPEEDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "invalid %s property\n",
|
||||
XGBE_DFE_ENA_PROPERTY);
|
||||
goto err_io;
|
||||
}
|
||||
} else {
|
||||
memcpy(pdata->serdes_dfe_tap_ena, xgbe_serdes_dfe_tap_ena,
|
||||
sizeof(pdata->serdes_dfe_tap_ena));
|
||||
}
|
||||
|
||||
/* Obtain device settings unique to ACPI/OF */
|
||||
if (pdata->use_acpi)
|
||||
ret = xgbe_acpi_support(pdata);
|
||||
@ -393,17 +646,23 @@ static int xgbe_probe(struct platform_device *pdev)
|
||||
}
|
||||
pdata->dev_irq = ret;
|
||||
|
||||
/* Get the auto-negotiation interrupt */
|
||||
ret = platform_get_irq(phy_pdev, phy_irqnum++);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "platform_get_irq phy 0 failed\n");
|
||||
goto err_io;
|
||||
}
|
||||
pdata->an_irq = ret;
|
||||
|
||||
netdev->irq = pdata->dev_irq;
|
||||
netdev->base_addr = (unsigned long)pdata->xgmac_regs;
|
||||
memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len);
|
||||
|
||||
/* Set all the function pointers */
|
||||
xgbe_init_all_fptrs(pdata);
|
||||
hw_if = &pdata->hw_if;
|
||||
desc_if = &pdata->desc_if;
|
||||
|
||||
/* Issue software reset to device */
|
||||
hw_if->exit(pdata);
|
||||
pdata->hw_if.exit(pdata);
|
||||
|
||||
/* Populate the hardware features */
|
||||
xgbe_get_all_hw_features(pdata);
|
||||
@ -458,16 +717,8 @@ static int xgbe_probe(struct platform_device *pdev)
|
||||
XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, TCP4TE, 1);
|
||||
XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
|
||||
|
||||
/* Prepare to regsiter with MDIO */
|
||||
pdata->mii_bus_id = kasprintf(GFP_KERNEL, "%s", pdev->name);
|
||||
if (!pdata->mii_bus_id) {
|
||||
dev_err(dev, "failed to allocate mii bus id\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_io;
|
||||
}
|
||||
ret = xgbe_mdio_register(pdata);
|
||||
if (ret)
|
||||
goto err_bus_id;
|
||||
/* Call MDIO/PHY initialization routine */
|
||||
pdata->phy_if.phy_init(pdata);
|
||||
|
||||
/* Set device operations */
|
||||
netdev->netdev_ops = xgbe_get_netdev_ops();
|
||||
@ -512,26 +763,52 @@ static int xgbe_probe(struct platform_device *pdev)
|
||||
ret = register_netdev(netdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "net device registration failed\n");
|
||||
goto err_reg_netdev;
|
||||
goto err_io;
|
||||
}
|
||||
|
||||
/* Create the PHY/ANEG name based on netdev name */
|
||||
snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
|
||||
netdev_name(netdev));
|
||||
|
||||
/* Create workqueues */
|
||||
pdata->dev_workqueue =
|
||||
create_singlethread_workqueue(netdev_name(netdev));
|
||||
if (!pdata->dev_workqueue) {
|
||||
netdev_err(netdev, "device workqueue creation failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_netdev;
|
||||
}
|
||||
|
||||
pdata->an_workqueue =
|
||||
create_singlethread_workqueue(pdata->an_name);
|
||||
if (!pdata->an_workqueue) {
|
||||
netdev_err(netdev, "phy workqueue creation failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_wq;
|
||||
}
|
||||
|
||||
xgbe_ptp_register(pdata);
|
||||
|
||||
xgbe_debugfs_init(pdata);
|
||||
|
||||
platform_device_put(phy_pdev);
|
||||
|
||||
netdev_notice(netdev, "net device enabled\n");
|
||||
|
||||
DBGPR("<-- xgbe_probe\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg_netdev:
|
||||
xgbe_mdio_unregister(pdata);
|
||||
err_wq:
|
||||
destroy_workqueue(pdata->dev_workqueue);
|
||||
|
||||
err_bus_id:
|
||||
kfree(pdata->mii_bus_id);
|
||||
err_netdev:
|
||||
unregister_netdev(netdev);
|
||||
|
||||
err_io:
|
||||
platform_device_put(phy_pdev);
|
||||
|
||||
err_phydev:
|
||||
free_netdev(netdev);
|
||||
|
||||
err_alloc:
|
||||
@ -551,12 +828,14 @@ static int xgbe_remove(struct platform_device *pdev)
|
||||
|
||||
xgbe_ptp_unregister(pdata);
|
||||
|
||||
flush_workqueue(pdata->an_workqueue);
|
||||
destroy_workqueue(pdata->an_workqueue);
|
||||
|
||||
flush_workqueue(pdata->dev_workqueue);
|
||||
destroy_workqueue(pdata->dev_workqueue);
|
||||
|
||||
unregister_netdev(netdev);
|
||||
|
||||
xgbe_mdio_unregister(pdata);
|
||||
|
||||
kfree(pdata->mii_bus_id);
|
||||
|
||||
free_netdev(netdev);
|
||||
|
||||
DBGPR("<--xgbe_remove\n");
|
||||
@ -568,16 +847,17 @@ static int xgbe_remove(struct platform_device *pdev)
|
||||
static int xgbe_suspend(struct device *dev)
|
||||
{
|
||||
struct net_device *netdev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
int ret = 0;
|
||||
|
||||
DBGPR("-->xgbe_suspend\n");
|
||||
|
||||
if (!netif_running(netdev)) {
|
||||
DBGPR("<--xgbe_dev_suspend\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (netif_running(netdev))
|
||||
ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
|
||||
|
||||
ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
|
||||
pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
|
||||
pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
|
||||
|
||||
DBGPR("<--xgbe_suspend\n");
|
||||
|
||||
@ -587,16 +867,16 @@ static int xgbe_suspend(struct device *dev)
|
||||
static int xgbe_resume(struct device *dev)
|
||||
{
|
||||
struct net_device *netdev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
struct xgbe_prv_data *pdata = netdev_priv(netdev);
|
||||
int ret = 0;
|
||||
|
||||
DBGPR("-->xgbe_resume\n");
|
||||
|
||||
if (!netif_running(netdev)) {
|
||||
DBGPR("<--xgbe_dev_resume\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
|
||||
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
|
||||
|
||||
ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
|
||||
if (netif_running(netdev))
|
||||
ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
|
||||
|
||||
DBGPR("<--xgbe_resume\n");
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -129,7 +129,7 @@
|
||||
#include <net/dcbnl.h>
|
||||
|
||||
#define XGBE_DRV_NAME "amd-xgbe"
|
||||
#define XGBE_DRV_VERSION "1.0.0-a"
|
||||
#define XGBE_DRV_VERSION "1.0.1"
|
||||
#define XGBE_DRV_DESC "AMD 10 Gigabit Ethernet Driver"
|
||||
|
||||
/* Descriptor related defines */
|
||||
@ -178,14 +178,17 @@
|
||||
#define XGMAC_JUMBO_PACKET_MTU 9000
|
||||
#define XGMAC_MAX_JUMBO_PACKET 9018
|
||||
|
||||
/* MDIO bus phy name */
|
||||
#define XGBE_PHY_NAME "amd_xgbe_phy"
|
||||
#define XGBE_PRTAD 0
|
||||
|
||||
/* Common property names */
|
||||
#define XGBE_MAC_ADDR_PROPERTY "mac-address"
|
||||
#define XGBE_PHY_MODE_PROPERTY "phy-mode"
|
||||
#define XGBE_DMA_IRQS_PROPERTY "amd,per-channel-interrupt"
|
||||
#define XGBE_SPEEDSET_PROPERTY "amd,speed-set"
|
||||
#define XGBE_BLWC_PROPERTY "amd,serdes-blwc"
|
||||
#define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate"
|
||||
#define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew"
|
||||
#define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp"
|
||||
#define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config"
|
||||
#define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable"
|
||||
|
||||
/* Device-tree clock names */
|
||||
#define XGBE_DMA_CLOCK "dma_clk"
|
||||
@ -241,6 +244,49 @@
|
||||
#define XGBE_RSS_LOOKUP_TABLE_TYPE 0
|
||||
#define XGBE_RSS_HASH_KEY_TYPE 1
|
||||
|
||||
/* Auto-negotiation */
|
||||
#define XGBE_AN_MS_TIMEOUT 500
|
||||
#define XGBE_LINK_TIMEOUT 10
|
||||
|
||||
#define XGBE_AN_INT_CMPLT 0x01
|
||||
#define XGBE_AN_INC_LINK 0x02
|
||||
#define XGBE_AN_PG_RCV 0x04
|
||||
#define XGBE_AN_INT_MASK 0x07
|
||||
|
||||
/* Rate-change complete wait/retry count */
|
||||
#define XGBE_RATECHANGE_COUNT 500
|
||||
|
||||
/* Default SerDes settings */
|
||||
#define XGBE_SPEED_10000_BLWC 0
|
||||
#define XGBE_SPEED_10000_CDR 0x7
|
||||
#define XGBE_SPEED_10000_PLL 0x1
|
||||
#define XGBE_SPEED_10000_PQ 0x12
|
||||
#define XGBE_SPEED_10000_RATE 0x0
|
||||
#define XGBE_SPEED_10000_TXAMP 0xa
|
||||
#define XGBE_SPEED_10000_WORD 0x7
|
||||
#define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1
|
||||
#define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f
|
||||
|
||||
#define XGBE_SPEED_2500_BLWC 1
|
||||
#define XGBE_SPEED_2500_CDR 0x2
|
||||
#define XGBE_SPEED_2500_PLL 0x0
|
||||
#define XGBE_SPEED_2500_PQ 0xa
|
||||
#define XGBE_SPEED_2500_RATE 0x1
|
||||
#define XGBE_SPEED_2500_TXAMP 0xf
|
||||
#define XGBE_SPEED_2500_WORD 0x1
|
||||
#define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3
|
||||
#define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0
|
||||
|
||||
#define XGBE_SPEED_1000_BLWC 1
|
||||
#define XGBE_SPEED_1000_CDR 0x2
|
||||
#define XGBE_SPEED_1000_PLL 0x0
|
||||
#define XGBE_SPEED_1000_PQ 0xa
|
||||
#define XGBE_SPEED_1000_RATE 0x3
|
||||
#define XGBE_SPEED_1000_TXAMP 0xf
|
||||
#define XGBE_SPEED_1000_WORD 0x1
|
||||
#define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3
|
||||
#define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0
|
||||
|
||||
struct xgbe_prv_data;
|
||||
|
||||
struct xgbe_packet_data {
|
||||
@ -412,6 +458,13 @@ struct xgbe_channel {
|
||||
struct xgbe_ring *rx_ring;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
enum xgbe_state {
|
||||
XGBE_DOWN,
|
||||
XGBE_LINK,
|
||||
XGBE_LINK_INIT,
|
||||
XGBE_LINK_ERR,
|
||||
};
|
||||
|
||||
enum xgbe_int {
|
||||
XGMAC_INT_DMA_CH_SR_TI,
|
||||
XGMAC_INT_DMA_CH_SR_TPS,
|
||||
@ -443,6 +496,55 @@ enum xgbe_mtl_fifo_size {
|
||||
XGMAC_MTL_FIFO_SIZE_256K = 0x3ff,
|
||||
};
|
||||
|
||||
enum xgbe_speed {
|
||||
XGBE_SPEED_1000 = 0,
|
||||
XGBE_SPEED_2500,
|
||||
XGBE_SPEED_10000,
|
||||
XGBE_SPEEDS,
|
||||
};
|
||||
|
||||
enum xgbe_an {
|
||||
XGBE_AN_READY = 0,
|
||||
XGBE_AN_PAGE_RECEIVED,
|
||||
XGBE_AN_INCOMPAT_LINK,
|
||||
XGBE_AN_COMPLETE,
|
||||
XGBE_AN_NO_LINK,
|
||||
XGBE_AN_ERROR,
|
||||
};
|
||||
|
||||
enum xgbe_rx {
|
||||
XGBE_RX_BPA = 0,
|
||||
XGBE_RX_XNP,
|
||||
XGBE_RX_COMPLETE,
|
||||
XGBE_RX_ERROR,
|
||||
};
|
||||
|
||||
enum xgbe_mode {
|
||||
XGBE_MODE_KR = 0,
|
||||
XGBE_MODE_KX,
|
||||
};
|
||||
|
||||
enum xgbe_speedset {
|
||||
XGBE_SPEEDSET_1000_10000 = 0,
|
||||
XGBE_SPEEDSET_2500_10000,
|
||||
};
|
||||
|
||||
struct xgbe_phy {
|
||||
u32 supported;
|
||||
u32 advertising;
|
||||
u32 lp_advertising;
|
||||
|
||||
int address;
|
||||
|
||||
int autoneg;
|
||||
int speed;
|
||||
int duplex;
|
||||
int pause;
|
||||
int asym_pause;
|
||||
|
||||
int link;
|
||||
};
|
||||
|
||||
struct xgbe_mmc_stats {
|
||||
/* Tx Stats */
|
||||
u64 txoctetcount_gb;
|
||||
@ -594,6 +696,20 @@ struct xgbe_hw_if {
|
||||
int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *);
|
||||
};
|
||||
|
||||
struct xgbe_phy_if {
|
||||
/* For initial PHY setup */
|
||||
void (*phy_init)(struct xgbe_prv_data *);
|
||||
|
||||
/* For PHY support when setting device up/down */
|
||||
int (*phy_reset)(struct xgbe_prv_data *);
|
||||
int (*phy_start)(struct xgbe_prv_data *);
|
||||
void (*phy_stop)(struct xgbe_prv_data *);
|
||||
|
||||
/* For PHY support while device is up */
|
||||
void (*phy_status)(struct xgbe_prv_data *);
|
||||
int (*phy_config_aneg)(struct xgbe_prv_data *);
|
||||
};
|
||||
|
||||
struct xgbe_desc_if {
|
||||
int (*alloc_ring_resources)(struct xgbe_prv_data *);
|
||||
void (*free_ring_resources)(struct xgbe_prv_data *);
|
||||
@ -663,6 +779,9 @@ struct xgbe_prv_data {
|
||||
/* XGMAC/XPCS related mmio registers */
|
||||
void __iomem *xgmac_regs; /* XGMAC CSRs */
|
||||
void __iomem *xpcs_regs; /* XPCS MMD registers */
|
||||
void __iomem *rxtx_regs; /* SerDes Rx/Tx CSRs */
|
||||
void __iomem *sir0_regs; /* SerDes integration registers (1/2) */
|
||||
void __iomem *sir1_regs; /* SerDes integration registers (2/2) */
|
||||
|
||||
/* Overall device lock */
|
||||
spinlock_t lock;
|
||||
@ -673,10 +792,14 @@ struct xgbe_prv_data {
|
||||
/* RSS addressing mutex */
|
||||
struct mutex rss_mutex;
|
||||
|
||||
/* Flags representing xgbe_state */
|
||||
unsigned long dev_state;
|
||||
|
||||
int dev_irq;
|
||||
unsigned int per_channel_irq;
|
||||
|
||||
struct xgbe_hw_if hw_if;
|
||||
struct xgbe_phy_if phy_if;
|
||||
struct xgbe_desc_if desc_if;
|
||||
|
||||
/* AXI DMA settings */
|
||||
@ -685,6 +808,11 @@ struct xgbe_prv_data {
|
||||
unsigned int arcache;
|
||||
unsigned int awcache;
|
||||
|
||||
/* Service routine support */
|
||||
struct workqueue_struct *dev_workqueue;
|
||||
struct work_struct service_work;
|
||||
struct timer_list service_timer;
|
||||
|
||||
/* Rings for Tx/Rx on a DMA channel */
|
||||
struct xgbe_channel *channel;
|
||||
unsigned int channel_count;
|
||||
@ -732,22 +860,6 @@ struct xgbe_prv_data {
|
||||
u32 rss_table[XGBE_RSS_MAX_TABLE_SIZE];
|
||||
u32 rss_options;
|
||||
|
||||
/* MDIO settings */
|
||||
struct module *phy_module;
|
||||
char *mii_bus_id;
|
||||
struct mii_bus *mii;
|
||||
int mdio_mmd;
|
||||
struct phy_device *phydev;
|
||||
int default_autoneg;
|
||||
int default_speed;
|
||||
|
||||
/* Current PHY settings */
|
||||
phy_interface_t phy_mode;
|
||||
int phy_link;
|
||||
int phy_speed;
|
||||
unsigned int phy_tx_pause;
|
||||
unsigned int phy_rx_pause;
|
||||
|
||||
/* Netdev related settings */
|
||||
unsigned char mac_addr[ETH_ALEN];
|
||||
netdev_features_t netdev_features;
|
||||
@ -794,6 +906,53 @@ struct xgbe_prv_data {
|
||||
/* Network interface message level setting */
|
||||
u32 msg_enable;
|
||||
|
||||
/* Current PHY settings */
|
||||
phy_interface_t phy_mode;
|
||||
int phy_link;
|
||||
int phy_speed;
|
||||
unsigned int phy_tx_pause;
|
||||
unsigned int phy_rx_pause;
|
||||
|
||||
/* MDIO/PHY related settings */
|
||||
struct xgbe_phy phy;
|
||||
int mdio_mmd;
|
||||
unsigned long link_check;
|
||||
|
||||
char an_name[IFNAMSIZ + 32];
|
||||
struct workqueue_struct *an_workqueue;
|
||||
|
||||
int an_irq;
|
||||
struct work_struct an_irq_work;
|
||||
|
||||
unsigned int speed_set;
|
||||
|
||||
/* SerDes UEFI configurable settings.
|
||||
* Switching between modes/speeds requires new values for some
|
||||
* SerDes settings. The values can be supplied as device
|
||||
* properties in array format. The first array entry is for
|
||||
* 1GbE, second for 2.5GbE and third for 10GbE
|
||||
*/
|
||||
u32 serdes_blwc[XGBE_SPEEDS];
|
||||
u32 serdes_cdr_rate[XGBE_SPEEDS];
|
||||
u32 serdes_pq_skew[XGBE_SPEEDS];
|
||||
u32 serdes_tx_amp[XGBE_SPEEDS];
|
||||
u32 serdes_dfe_tap_cfg[XGBE_SPEEDS];
|
||||
u32 serdes_dfe_tap_ena[XGBE_SPEEDS];
|
||||
|
||||
/* Auto-negotiation state machine support */
|
||||
struct mutex an_mutex;
|
||||
enum xgbe_an an_result;
|
||||
enum xgbe_an an_state;
|
||||
enum xgbe_rx kr_state;
|
||||
enum xgbe_rx kx_state;
|
||||
struct work_struct an_work;
|
||||
unsigned int an_supported;
|
||||
unsigned int parallel_detect;
|
||||
unsigned int fec_ability;
|
||||
unsigned long an_start;
|
||||
|
||||
unsigned int lpm_ctrl; /* CTRL1 for resume */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *xgbe_debugfs;
|
||||
|
||||
@ -807,6 +966,7 @@ struct xgbe_prv_data {
|
||||
/* Function prototypes*/
|
||||
|
||||
void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *);
|
||||
void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *);
|
||||
void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
|
||||
struct net_device_ops *xgbe_get_netdev_ops(void);
|
||||
struct ethtool_ops *xgbe_get_ethtool_ops(void);
|
||||
@ -814,9 +974,6 @@ struct ethtool_ops *xgbe_get_ethtool_ops(void);
|
||||
const struct dcbnl_rtnl_ops *xgbe_get_dcbnl_ops(void);
|
||||
#endif
|
||||
|
||||
int xgbe_mdio_register(struct xgbe_prv_data *);
|
||||
void xgbe_mdio_unregister(struct xgbe_prv_data *);
|
||||
void xgbe_dump_phy_registers(struct xgbe_prv_data *);
|
||||
void xgbe_ptp_register(struct xgbe_prv_data *);
|
||||
void xgbe_ptp_unregister(struct xgbe_prv_data *);
|
||||
void xgbe_dump_tx_desc(struct xgbe_prv_data *, struct xgbe_ring *,
|
||||
|
@ -24,13 +24,6 @@ config AMD_PHY
|
||||
---help---
|
||||
Currently supports the am79c874
|
||||
|
||||
config AMD_XGBE_PHY
|
||||
tristate "Driver for the AMD 10GbE (amd-xgbe) PHYs"
|
||||
depends on (OF || ACPI) && HAS_IOMEM
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
---help---
|
||||
Currently supports the AMD 10GbE PHY
|
||||
|
||||
config MARVELL_PHY
|
||||
tristate "Drivers for Marvell PHYs"
|
||||
---help---
|
||||
|
@ -33,5 +33,4 @@ obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
|
||||
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
|
||||
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
|
||||
obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
|
||||
obj-$(CONFIG_AMD_XGBE_PHY) += amd-xgbe-phy.o
|
||||
obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user