Skip to content

Commit 298bfe2

Browse files
committed
Merge branch 'mlxbf_gige-add-bluefield-3-support'
David Thompson says: ==================== mlxbf_gige: add BlueField-3 support This patch series adds driver logic to the "mlxbf_gige" Ethernet driver in order to support the third generation BlueField SoC (BF3). The existing "mlxbf_gige" driver is extended with BF3-specific logic and run-time decisions are made by the driver depending on the SoC generation (BF2 vs. BF3). The BF3 SoC is similar to BF2 SoC with regards to transmit and receive packet processing: * Driver rings usage; consumer & producer indices * Single queue for receive and transmit * DMA operation The differences between BF3 and BF2 SoC are: * In addition to supporting 1Gbps interface speed, the BF3 SoC adds support for 10Mbps and 100Mbps interface speeds * BF3 requires SerDes config logic to support its SGMII interface * BF3 adds support for "ethtool -s" for interface speed config * BF3 utilizes different MDIO logic for accessing the board-level PHY device Testing - Successful build of kernel for ARM64, ARM32, X86_64 - Tested ARM64 build on FastModels, Palladium, SoC ==================== Link: https://lore.kernel.org/r/20230112202609.21331-1-davthompson@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents e2a9575 + e1cc8ce commit 298bfe2

File tree

7 files changed

+372
-66
lines changed

7 files changed

+372
-66
lines changed

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

Lines changed: 27 additions & 0 deletions
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
@@ -67,6 +68,29 @@ struct mlxbf_gige_stats {
6768
u64 rx_filter_discard_pkts;
6869
};
6970

71+
struct mlxbf_gige_reg_param {
72+
u32 mask;
73+
u32 shift;
74+
};
75+
76+
struct mlxbf_gige_mdio_gw {
77+
u32 gw_address;
78+
u32 read_data_address;
79+
struct mlxbf_gige_reg_param busy;
80+
struct mlxbf_gige_reg_param write_data;
81+
struct mlxbf_gige_reg_param read_data;
82+
struct mlxbf_gige_reg_param devad;
83+
struct mlxbf_gige_reg_param partad;
84+
struct mlxbf_gige_reg_param opcode;
85+
struct mlxbf_gige_reg_param st1;
86+
};
87+
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+
7094
struct mlxbf_gige {
7195
void __iomem *base;
7296
void __iomem *llu_base;
@@ -102,6 +126,9 @@ struct mlxbf_gige {
102126
u8 valid_polarity;
103127
struct napi_struct napi;
104128
struct mlxbf_gige_stats stats;
129+
u8 hw_version;
130+
struct mlxbf_gige_mdio_gw *mdio_gw;
131+
int prev_speed;
105132
};
106133

107134
/* Rx Work Queue Element definitions */

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,5 @@ const struct ethtool_ops mlxbf_gige_ethtool_ops = {
135135
.nway_reset = phy_ethtool_nway_reset,
136136
.get_pauseparam = mlxbf_gige_get_pauseparam,
137137
.get_link_ksettings = phy_ethtool_get_link_ksettings,
138+
.set_link_ksettings = phy_ethtool_set_link_ksettings,
138139
};

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

Lines changed: 93 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ static int mlxbf_gige_stop(struct net_device *netdev)
205205
}
206206

207207
static int mlxbf_gige_eth_ioctl(struct net_device *netdev,
208-
struct ifreq *ifr, int cmd)
208+
struct ifreq *ifr, int cmd)
209209
{
210210
if (!(netif_running(netdev)))
211211
return -EINVAL;
@@ -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;
@@ -315,6 +401,8 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
315401

316402
spin_lock_init(&priv->lock);
317403

404+
priv->hw_version = readq(base + MLXBF_GIGE_VERSION);
405+
318406
/* Attach MDIO device */
319407
err = mlxbf_gige_mdio_probe(pdev, priv);
320408
if (err)
@@ -357,25 +445,14 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
357445
phydev->irq = phy_irq;
358446

359447
err = phy_connect_direct(netdev, phydev,
360-
mlxbf_gige_adjust_link,
361-
PHY_INTERFACE_MODE_GMII);
448+
mlxbf_gige_link_cfgs[priv->hw_version].adjust_link,
449+
mlxbf_gige_link_cfgs[priv->hw_version].phy_mode);
362450
if (err) {
363451
dev_err(&pdev->dev, "Could not attach to PHY\n");
364452
goto out;
365453
}
366454

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

380457
/* Display information about attached PHY device */
381458
phy_attached_info(phydev);

0 commit comments

Comments
 (0)