Skip to content

Commit 20d03d4

Browse files
dthompsokuba-moo
authored andcommitted
mlxbf_gige: support 10M/100M/1G speeds on BlueField-3
The BlueField-3 OOB interface supports 10Mbps, 100Mbps, and 1Gbps speeds. The external PHY is responsible for autonegotiating the speed with the link partner. Once the autonegotiation is done, the BlueField PLU needs to be configured accordingly. This patch does two things: 1) Initialize the advertised control flow/duplex/speed in the probe based on the BlueField SoC generation (2 or 3) 2) Adjust the PLU speed config in the PHY interrupt handler Signed-off-by: David Thompson <[email protected]> Signed-off-by: Asmaa Mnebhi <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 2321d69 commit 20d03d4

File tree

3 files changed

+119
-15
lines changed

3 files changed

+119
-15
lines changed

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/irqreturn.h>
1515
#include <linux/netdevice.h>
1616
#include <linux/irq.h>
17+
#include <linux/phy.h>
1718

1819
/* The silicon design supports a maximum RX ring size of
1920
* 32K entries. Based on current testing this maximum size
@@ -84,6 +85,12 @@ struct mlxbf_gige_mdio_gw {
8485
struct mlxbf_gige_reg_param st1;
8586
};
8687

88+
struct mlxbf_gige_link_cfg {
89+
void (*set_phy_link_mode)(struct phy_device *phydev);
90+
void (*adjust_link)(struct net_device *netdev);
91+
phy_interface_t phy_mode;
92+
};
93+
8794
struct mlxbf_gige {
8895
void __iomem *base;
8996
void __iomem *llu_base;
@@ -121,6 +128,7 @@ struct mlxbf_gige {
121128
struct mlxbf_gige_stats stats;
122129
u8 hw_version;
123130
struct mlxbf_gige_mdio_gw *mdio_gw;
131+
int prev_speed;
124132
};
125133

126134
/* Rx Work Queue Element definitions */

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c

+90-15
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,99 @@ static const struct net_device_ops mlxbf_gige_netdev_ops = {
263263
.ndo_get_stats64 = mlxbf_gige_get_stats64,
264264
};
265265

266-
static void mlxbf_gige_adjust_link(struct net_device *netdev)
266+
static void mlxbf_gige_bf2_adjust_link(struct net_device *netdev)
267267
{
268268
struct phy_device *phydev = netdev->phydev;
269269

270270
phy_print_status(phydev);
271271
}
272272

273+
static void mlxbf_gige_bf3_adjust_link(struct net_device *netdev)
274+
{
275+
struct mlxbf_gige *priv = netdev_priv(netdev);
276+
struct phy_device *phydev = netdev->phydev;
277+
u8 sgmii_mode;
278+
u16 ipg_size;
279+
u32 val;
280+
281+
if (phydev->link && phydev->speed != priv->prev_speed) {
282+
switch (phydev->speed) {
283+
case 1000:
284+
ipg_size = MLXBF_GIGE_1G_IPG_SIZE;
285+
sgmii_mode = MLXBF_GIGE_1G_SGMII_MODE;
286+
break;
287+
case 100:
288+
ipg_size = MLXBF_GIGE_100M_IPG_SIZE;
289+
sgmii_mode = MLXBF_GIGE_100M_SGMII_MODE;
290+
break;
291+
case 10:
292+
ipg_size = MLXBF_GIGE_10M_IPG_SIZE;
293+
sgmii_mode = MLXBF_GIGE_10M_SGMII_MODE;
294+
break;
295+
default:
296+
return;
297+
}
298+
299+
val = readl(priv->plu_base + MLXBF_GIGE_PLU_TX_REG0);
300+
val &= ~(MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK | MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK);
301+
val |= FIELD_PREP(MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK, ipg_size);
302+
val |= FIELD_PREP(MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK, sgmii_mode);
303+
writel(val, priv->plu_base + MLXBF_GIGE_PLU_TX_REG0);
304+
305+
val = readl(priv->plu_base + MLXBF_GIGE_PLU_RX_REG0);
306+
val &= ~MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK;
307+
val |= FIELD_PREP(MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK, sgmii_mode);
308+
writel(val, priv->plu_base + MLXBF_GIGE_PLU_RX_REG0);
309+
310+
priv->prev_speed = phydev->speed;
311+
}
312+
313+
phy_print_status(phydev);
314+
}
315+
316+
static void mlxbf_gige_bf2_set_phy_link_mode(struct phy_device *phydev)
317+
{
318+
/* MAC only supports 1000T full duplex mode */
319+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
320+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT);
321+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
322+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
323+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
324+
325+
/* Only symmetric pause with flow control enabled is supported so no
326+
* need to negotiate pause.
327+
*/
328+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising);
329+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising);
330+
}
331+
332+
static void mlxbf_gige_bf3_set_phy_link_mode(struct phy_device *phydev)
333+
{
334+
/* MAC only supports full duplex mode */
335+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
336+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
337+
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
338+
339+
/* Only symmetric pause with flow control enabled is supported so no
340+
* need to negotiate pause.
341+
*/
342+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising);
343+
linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising);
344+
}
345+
346+
static struct mlxbf_gige_link_cfg mlxbf_gige_link_cfgs[] = {
347+
[MLXBF_GIGE_VERSION_BF2] = {
348+
.set_phy_link_mode = mlxbf_gige_bf2_set_phy_link_mode,
349+
.adjust_link = mlxbf_gige_bf2_adjust_link,
350+
.phy_mode = PHY_INTERFACE_MODE_GMII
351+
},
352+
[MLXBF_GIGE_VERSION_BF3] = {
353+
.set_phy_link_mode = mlxbf_gige_bf3_set_phy_link_mode,
354+
.adjust_link = mlxbf_gige_bf3_adjust_link,
355+
.phy_mode = PHY_INTERFACE_MODE_SGMII
356+
}
357+
};
358+
273359
static int mlxbf_gige_probe(struct platform_device *pdev)
274360
{
275361
struct phy_device *phydev;
@@ -359,25 +445,14 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
359445
phydev->irq = phy_irq;
360446

361447
err = phy_connect_direct(netdev, phydev,
362-
mlxbf_gige_adjust_link,
363-
PHY_INTERFACE_MODE_GMII);
448+
mlxbf_gige_link_cfgs[priv->hw_version].adjust_link,
449+
mlxbf_gige_link_cfgs[priv->hw_version].phy_mode);
364450
if (err) {
365451
dev_err(&pdev->dev, "Could not attach to PHY\n");
366452
goto out;
367453
}
368454

369-
/* MAC only supports 1000T full duplex mode */
370-
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
371-
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT);
372-
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
373-
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
374-
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
375-
376-
/* Only symmetric pause with flow control enabled is supported so no
377-
* need to negotiate pause.
378-
*/
379-
linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising);
380-
linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising);
455+
mlxbf_gige_link_cfgs[priv->hw_version].set_phy_link_mode(phydev);
381456

382457
/* Display information about attached PHY device */
383458
phy_attached_info(phydev);

drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h

+21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#ifndef __MLXBF_GIGE_REGS_H__
99
#define __MLXBF_GIGE_REGS_H__
1010

11+
#include <linux/bitfield.h>
12+
1113
#define MLXBF_GIGE_VERSION 0x0000
1214
#define MLXBF_GIGE_VERSION_BF2 0x0
1315
#define MLXBF_GIGE_VERSION_BF3 0x1
@@ -78,4 +80,23 @@
7880
*/
7981
#define MLXBF_GIGE_MMIO_REG_SZ (MLXBF_GIGE_MAC_CFG + 8)
8082

83+
#define MLXBF_GIGE_PLU_TX_REG0 0x80
84+
#define MLXBF_GIGE_PLU_TX_IPG_SIZE_MASK GENMASK(11, 0)
85+
#define MLXBF_GIGE_PLU_TX_SGMII_MODE_MASK GENMASK(15, 14)
86+
87+
#define MLXBF_GIGE_PLU_RX_REG0 0x10
88+
#define MLXBF_GIGE_PLU_RX_SGMII_MODE_MASK GENMASK(25, 24)
89+
90+
#define MLXBF_GIGE_1G_SGMII_MODE 0x0
91+
#define MLXBF_GIGE_10M_SGMII_MODE 0x1
92+
#define MLXBF_GIGE_100M_SGMII_MODE 0x2
93+
94+
/* ipg_size default value for 1G is fixed by HW to 11 + End = 12.
95+
* So for 100M it is 12 * 10 - 1 = 119
96+
* For 10M, it is 12 * 100 - 1 = 1199
97+
*/
98+
#define MLXBF_GIGE_1G_IPG_SIZE 11
99+
#define MLXBF_GIGE_100M_IPG_SIZE 119
100+
#define MLXBF_GIGE_10M_IPG_SIZE 1199
101+
81102
#endif /* !defined(__MLXBF_GIGE_REGS_H__) */

0 commit comments

Comments
 (0)