forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'net-lan969x-add-rgmii-support'
Daniel Machon says: ==================== net: lan969x: add RGMII support == Description: This series is the fourth of a multi-part series, that prepares and adds support for the new lan969x switch driver. The upstreaming efforts is split into multiple series (might change a bit as we go along): 1) Prepare the Sparx5 driver for lan969x (merged) 2) Add support for lan969x (same basic features as Sparx5 provides excl. FDMA and VCAP, merged). 3) Add lan969x VCAP functionality (merged). --> 4) Add RGMII support. 5) Add FDMA support. == RGMII support: The lan969x switch device includes two RGMII port interfaces (port 28 and 29) supporting data speeds of 1 Gbps, 100 Mbps and 10 Mbps. == Patch breakdown: Patch #1 does some preparation work. Patch #2 adds new function: is_port_rgmii() to the match data ops. Patch #3 uses the is_port_rgmii() in a number of places. Patch #4 makes sure that we do not configure an RGMII device as a low-speed device, when doing a port config. Patch #5 makes sure we only return the PCS if the port mode requires it. Patch #6 adds checks for RGMII PHY modes in sparx5_verify_speeds(). Patch #7 adds registers required to configure RGMII. Patch #8 adds RGMII implementation. Patch #9 documents RGMII delays in the dt-bindings. Details are in the commit description of the individual patches v4: https://lore.kernel.org/20241213-sparx5-lan969x-switch-driver-4-v4-0-d1a72c9c4714@microchip.com v3: https://lore.kernel.org/20241118-sparx5-lan969x-switch-driver-4-v3-0-3cefee5e7e3a@microchip.com v2: https://lore.kernel.org/20241113-sparx5-lan969x-switch-driver-4-v2-0-0db98ac096d1@microchip.com v1: https://lore.kernel.org/20241106-sparx5-lan969x-switch-driver-4-v1-0-f7f7316436bd@microchip.com ==================== Link: https://patch.msgid.link/20241220-sparx5-lan969x-switch-driver-4-v5-0-fa8ba5dff732@microchip.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
- Loading branch information
Showing
11 changed files
with
484 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
224 changes: 224 additions & 0 deletions
224
drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
// SPDX-License-Identifier: GPL-2.0+ | ||
/* Microchip lan969x Switch driver | ||
* | ||
* Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries. | ||
*/ | ||
|
||
#include "lan969x.h" | ||
|
||
/* Tx clock selectors */ | ||
#define LAN969X_RGMII_TX_CLK_SEL_125MHZ 1 /* 1000Mbps */ | ||
#define LAN969X_RGMII_TX_CLK_SEL_25MHZ 2 /* 100Mbps */ | ||
#define LAN969X_RGMII_TX_CLK_SEL_2M5MHZ 3 /* 10Mbps */ | ||
|
||
/* Port speed selectors */ | ||
#define LAN969X_RGMII_SPEED_SEL_10 0 /* Select 10Mbps speed */ | ||
#define LAN969X_RGMII_SPEED_SEL_100 1 /* Select 100Mbps speed */ | ||
#define LAN969X_RGMII_SPEED_SEL_1000 2 /* Select 1000Mbps speed */ | ||
|
||
/* Clock delay selectors */ | ||
#define LAN969X_RGMII_CLK_DELAY_SEL_1_0_NS 2 /* Phase shift 45deg */ | ||
#define LAN969X_RGMII_CLK_DELAY_SEL_1_7_NS 3 /* Phase shift 77deg */ | ||
#define LAN969X_RGMII_CLK_DELAY_SEL_2_0_NS 4 /* Phase shift 90deg */ | ||
#define LAN969X_RGMII_CLK_DELAY_SEL_2_5_NS 5 /* Phase shift 112deg */ | ||
#define LAN969X_RGMII_CLK_DELAY_SEL_3_0_NS 6 /* Phase shift 135deg */ | ||
#define LAN969X_RGMII_CLK_DELAY_SEL_3_3_NS 7 /* Phase shift 147deg */ | ||
|
||
#define LAN969X_RGMII_PORT_START_IDX 28 /* Index of the first RGMII port */ | ||
#define LAN969X_RGMII_IFG_TX 4 /* TX Inter Frame Gap value */ | ||
#define LAN969X_RGMII_IFG_RX1 5 /* RX1 Inter Frame Gap value */ | ||
#define LAN969X_RGMII_IFG_RX2 1 /* RX2 Inter Frame Gap value */ | ||
|
||
#define RGMII_PORT_IDX(port) ((port)->portno - LAN969X_RGMII_PORT_START_IDX) | ||
|
||
/* Get the tx clock selector based on the port speed. */ | ||
static int lan969x_rgmii_get_clk_sel(int speed) | ||
{ | ||
return (speed == SPEED_10 ? LAN969X_RGMII_TX_CLK_SEL_2M5MHZ : | ||
speed == SPEED_100 ? LAN969X_RGMII_TX_CLK_SEL_25MHZ : | ||
LAN969X_RGMII_TX_CLK_SEL_125MHZ); | ||
} | ||
|
||
/* Get the port speed selector based on the port speed. */ | ||
static int lan969x_rgmii_get_speed_sel(int speed) | ||
{ | ||
return (speed == SPEED_10 ? LAN969X_RGMII_SPEED_SEL_10 : | ||
speed == SPEED_100 ? LAN969X_RGMII_SPEED_SEL_100 : | ||
LAN969X_RGMII_SPEED_SEL_1000); | ||
} | ||
|
||
/* Get the clock delay selector based on the clock delay in picoseconds. */ | ||
static int lan969x_rgmii_get_clk_delay_sel(struct sparx5_port *port, | ||
u32 delay_ps, u32 *clk_delay_sel) | ||
{ | ||
switch (delay_ps) { | ||
case 0: | ||
/* Hardware default selector. */ | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_2_5_NS; | ||
break; | ||
case 1000: | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_1_0_NS; | ||
break; | ||
case 1700: | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_1_7_NS; | ||
break; | ||
case 2000: | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_2_0_NS; | ||
break; | ||
case 2500: | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_2_5_NS; | ||
break; | ||
case 3000: | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_3_0_NS; | ||
break; | ||
case 3300: | ||
*clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_3_3_NS; | ||
break; | ||
default: | ||
dev_err(port->sparx5->dev, "Invalid RGMII delay: %u", delay_ps); | ||
return -EINVAL; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/* Configure the RGMII tx clock frequency. */ | ||
static void lan969x_rgmii_tx_clk_config(struct sparx5_port *port, | ||
struct sparx5_port_config *conf) | ||
{ | ||
u32 clk_sel = lan969x_rgmii_get_clk_sel(conf->speed); | ||
u32 idx = RGMII_PORT_IDX(port); | ||
|
||
/* Take the RGMII clock domain out of reset and set tx clock | ||
* frequency. | ||
*/ | ||
spx5_rmw(HSIO_WRAP_RGMII_CFG_TX_CLK_CFG_SET(clk_sel) | | ||
HSIO_WRAP_RGMII_CFG_RGMII_TX_RST_SET(0) | | ||
HSIO_WRAP_RGMII_CFG_RGMII_RX_RST_SET(0), | ||
HSIO_WRAP_RGMII_CFG_TX_CLK_CFG | | ||
HSIO_WRAP_RGMII_CFG_RGMII_TX_RST | | ||
HSIO_WRAP_RGMII_CFG_RGMII_RX_RST, | ||
port->sparx5, HSIO_WRAP_RGMII_CFG(idx)); | ||
} | ||
|
||
/* Configure the RGMII port device. */ | ||
static void lan969x_rgmii_port_device_config(struct sparx5_port *port, | ||
struct sparx5_port_config *conf) | ||
{ | ||
u32 dtag, dotag, etype, speed_sel, idx = RGMII_PORT_IDX(port); | ||
|
||
speed_sel = lan969x_rgmii_get_speed_sel(conf->speed); | ||
|
||
etype = (port->vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ? | ||
port->custom_etype : | ||
port->vlan_type == SPX5_VLAN_PORT_TYPE_C ? | ||
ETH_P_8021Q : ETH_P_8021AD); | ||
|
||
dtag = port->max_vlan_tags == SPX5_PORT_MAX_TAGS_TWO; | ||
dotag = port->max_vlan_tags != SPX5_PORT_MAX_TAGS_NONE; | ||
|
||
/* Enable the MAC. */ | ||
spx5_wr(DEVRGMII_MAC_ENA_CFG_RX_ENA_SET(1) | | ||
DEVRGMII_MAC_ENA_CFG_TX_ENA_SET(1), | ||
port->sparx5, DEVRGMII_MAC_ENA_CFG(idx)); | ||
|
||
/* Configure the Inter Frame Gap. */ | ||
spx5_wr(DEVRGMII_MAC_IFG_CFG_TX_IFG_SET(LAN969X_RGMII_IFG_TX) | | ||
DEVRGMII_MAC_IFG_CFG_RX_IFG1_SET(LAN969X_RGMII_IFG_RX1) | | ||
DEVRGMII_MAC_IFG_CFG_RX_IFG2_SET(LAN969X_RGMII_IFG_RX2), | ||
port->sparx5, DEVRGMII_MAC_IFG_CFG(idx)); | ||
|
||
/* Configure port data rate. */ | ||
spx5_wr(DEVRGMII_DEV_RST_CTRL_SPEED_SEL_SET(speed_sel), | ||
port->sparx5, DEVRGMII_DEV_RST_CTRL(idx)); | ||
|
||
/* Configure VLAN awareness. */ | ||
spx5_wr(DEVRGMII_MAC_TAGS_CFG_TAG_ID_SET(etype) | | ||
DEVRGMII_MAC_TAGS_CFG_PB_ENA_SET(dtag) | | ||
DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(dotag) | | ||
DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA_SET(dotag), | ||
port->sparx5, | ||
DEVRGMII_MAC_TAGS_CFG(idx)); | ||
} | ||
|
||
/* Configure the RGMII delay lines in the MAC. | ||
* | ||
* We use the rx-internal-delay-ps" and "tx-internal-delay-ps" properties to | ||
* configure the rx and tx delays for the MAC. If these properties are missing | ||
* or set to zero, the MAC will not apply any delay. | ||
* | ||
* The PHY side delays are determined by the PHY mode | ||
* (e.g. PHY_INTERFACE_MODE_RGMII_{ID, RXID, TXID}), and ignored by the MAC side | ||
* entirely. | ||
*/ | ||
static int lan969x_rgmii_delay_config(struct sparx5_port *port, | ||
struct sparx5_port_config *conf) | ||
{ | ||
u32 tx_clk_sel, rx_clk_sel, tx_delay_ps = 0, rx_delay_ps = 0; | ||
u32 idx = RGMII_PORT_IDX(port); | ||
int err; | ||
|
||
of_property_read_u32(port->of_node, "rx-internal-delay-ps", | ||
&rx_delay_ps); | ||
|
||
of_property_read_u32(port->of_node, "tx-internal-delay-ps", | ||
&tx_delay_ps); | ||
|
||
err = lan969x_rgmii_get_clk_delay_sel(port, rx_delay_ps, &rx_clk_sel); | ||
if (err) | ||
return err; | ||
|
||
err = lan969x_rgmii_get_clk_delay_sel(port, tx_delay_ps, &tx_clk_sel); | ||
if (err) | ||
return err; | ||
|
||
/* Configure rx delay. */ | ||
spx5_rmw(HSIO_WRAP_DLL_CFG_DLL_RST_SET(0) | | ||
HSIO_WRAP_DLL_CFG_DLL_ENA_SET(1) | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_ENA_SET(!!rx_delay_ps) | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_SEL_SET(rx_clk_sel), | ||
HSIO_WRAP_DLL_CFG_DLL_RST | | ||
HSIO_WRAP_DLL_CFG_DLL_ENA | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_ENA | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_SEL, | ||
port->sparx5, HSIO_WRAP_DLL_CFG(idx, 0)); | ||
|
||
/* Configure tx delay. */ | ||
spx5_rmw(HSIO_WRAP_DLL_CFG_DLL_RST_SET(0) | | ||
HSIO_WRAP_DLL_CFG_DLL_ENA_SET(1) | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_ENA_SET(!!tx_delay_ps) | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_SEL_SET(tx_clk_sel), | ||
HSIO_WRAP_DLL_CFG_DLL_RST | | ||
HSIO_WRAP_DLL_CFG_DLL_ENA | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_ENA | | ||
HSIO_WRAP_DLL_CFG_DLL_CLK_SEL, | ||
port->sparx5, HSIO_WRAP_DLL_CFG(idx, 1)); | ||
|
||
return 0; | ||
} | ||
|
||
/* Configure GPIO's to be used as RGMII interface. */ | ||
static void lan969x_rgmii_gpio_config(struct sparx5_port *port) | ||
{ | ||
u32 idx = RGMII_PORT_IDX(port); | ||
|
||
/* Enable the RGMII on the GPIOs. */ | ||
spx5_wr(HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG_SET(1), port->sparx5, | ||
HSIO_WRAP_XMII_CFG(!idx)); | ||
} | ||
|
||
int lan969x_port_config_rgmii(struct sparx5_port *port, | ||
struct sparx5_port_config *conf) | ||
{ | ||
int err; | ||
|
||
err = lan969x_rgmii_delay_config(port, conf); | ||
if (err) | ||
return err; | ||
|
||
lan969x_rgmii_tx_clk_config(port, conf); | ||
lan969x_rgmii_gpio_config(port); | ||
lan969x_rgmii_port_device_config(port, conf); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.