Skip to content

Commit 2321d69

Browse files
dthompsokuba-moo
authored andcommitted
mlxbf_gige: add MDIO support for BlueField-3
This patch adds initial MDIO support for the BlueField-3 SoC. Separate header files for the BlueField-2 and the BlueField-3 SoCs have been created. These header files hold the SoC-specific MDIO macros since the register offsets and bit fields have changed. Also, in BlueField-3 there is a separate register for writing and reading the MDIO data. Finally, instead of having "if" statements everywhere to differentiate between SoC-specific logic, a mlxbf_gige_mdio_gw_t struct was created for this purpose. Signed-off-by: David Thompson <[email protected]> Signed-off-by: Asmaa Mnebhi <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent e2a9575 commit 2321d69

File tree

6 files changed

+251
-50
lines changed

6 files changed

+251
-50
lines changed

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

+19
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ struct mlxbf_gige_stats {
6767
u64 rx_filter_discard_pkts;
6868
};
6969

70+
struct mlxbf_gige_reg_param {
71+
u32 mask;
72+
u32 shift;
73+
};
74+
75+
struct mlxbf_gige_mdio_gw {
76+
u32 gw_address;
77+
u32 read_data_address;
78+
struct mlxbf_gige_reg_param busy;
79+
struct mlxbf_gige_reg_param write_data;
80+
struct mlxbf_gige_reg_param read_data;
81+
struct mlxbf_gige_reg_param devad;
82+
struct mlxbf_gige_reg_param partad;
83+
struct mlxbf_gige_reg_param opcode;
84+
struct mlxbf_gige_reg_param st1;
85+
};
86+
7087
struct mlxbf_gige {
7188
void __iomem *base;
7289
void __iomem *llu_base;
@@ -102,6 +119,8 @@ struct mlxbf_gige {
102119
u8 valid_polarity;
103120
struct napi_struct napi;
104121
struct mlxbf_gige_stats stats;
122+
u8 hw_version;
123+
struct mlxbf_gige_mdio_gw *mdio_gw;
105124
};
106125

107126
/* Rx Work Queue Element definitions */

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

+2
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
315315

316316
spin_lock_init(&priv->lock);
317317

318+
priv->hw_version = readq(base + MLXBF_GIGE_VERSION);
319+
318320
/* Attach MDIO device */
319321
err = mlxbf_gige_mdio_probe(pdev, priv);
320322
if (err)

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

+122-50
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,75 @@
2323

2424
#include "mlxbf_gige.h"
2525
#include "mlxbf_gige_regs.h"
26+
#include "mlxbf_gige_mdio_bf2.h"
27+
#include "mlxbf_gige_mdio_bf3.h"
2628

27-
#define MLXBF_GIGE_MDIO_GW_OFFSET 0x0
28-
#define MLXBF_GIGE_MDIO_CFG_OFFSET 0x4
29+
static struct mlxbf_gige_mdio_gw mlxbf_gige_mdio_gw_t[] = {
30+
[MLXBF_GIGE_VERSION_BF2] = {
31+
.gw_address = MLXBF2_GIGE_MDIO_GW_OFFSET,
32+
.read_data_address = MLXBF2_GIGE_MDIO_GW_OFFSET,
33+
.busy = {
34+
.mask = MLXBF2_GIGE_MDIO_GW_BUSY_MASK,
35+
.shift = MLXBF2_GIGE_MDIO_GW_BUSY_SHIFT,
36+
},
37+
.read_data = {
38+
.mask = MLXBF2_GIGE_MDIO_GW_AD_MASK,
39+
.shift = MLXBF2_GIGE_MDIO_GW_AD_SHIFT,
40+
},
41+
.write_data = {
42+
.mask = MLXBF2_GIGE_MDIO_GW_AD_MASK,
43+
.shift = MLXBF2_GIGE_MDIO_GW_AD_SHIFT,
44+
},
45+
.devad = {
46+
.mask = MLXBF2_GIGE_MDIO_GW_DEVAD_MASK,
47+
.shift = MLXBF2_GIGE_MDIO_GW_DEVAD_SHIFT,
48+
},
49+
.partad = {
50+
.mask = MLXBF2_GIGE_MDIO_GW_PARTAD_MASK,
51+
.shift = MLXBF2_GIGE_MDIO_GW_PARTAD_SHIFT,
52+
},
53+
.opcode = {
54+
.mask = MLXBF2_GIGE_MDIO_GW_OPCODE_MASK,
55+
.shift = MLXBF2_GIGE_MDIO_GW_OPCODE_SHIFT,
56+
},
57+
.st1 = {
58+
.mask = MLXBF2_GIGE_MDIO_GW_ST1_MASK,
59+
.shift = MLXBF2_GIGE_MDIO_GW_ST1_SHIFT,
60+
},
61+
},
62+
[MLXBF_GIGE_VERSION_BF3] = {
63+
.gw_address = MLXBF3_GIGE_MDIO_GW_OFFSET,
64+
.read_data_address = MLXBF3_GIGE_MDIO_DATA_READ,
65+
.busy = {
66+
.mask = MLXBF3_GIGE_MDIO_GW_BUSY_MASK,
67+
.shift = MLXBF3_GIGE_MDIO_GW_BUSY_SHIFT,
68+
},
69+
.read_data = {
70+
.mask = MLXBF3_GIGE_MDIO_GW_DATA_READ_MASK,
71+
.shift = MLXBF3_GIGE_MDIO_GW_DATA_READ_SHIFT,
72+
},
73+
.write_data = {
74+
.mask = MLXBF3_GIGE_MDIO_GW_DATA_MASK,
75+
.shift = MLXBF3_GIGE_MDIO_GW_DATA_SHIFT,
76+
},
77+
.devad = {
78+
.mask = MLXBF3_GIGE_MDIO_GW_DEVAD_MASK,
79+
.shift = MLXBF3_GIGE_MDIO_GW_DEVAD_SHIFT,
80+
},
81+
.partad = {
82+
.mask = MLXBF3_GIGE_MDIO_GW_PARTAD_MASK,
83+
.shift = MLXBF3_GIGE_MDIO_GW_PARTAD_SHIFT,
84+
},
85+
.opcode = {
86+
.mask = MLXBF3_GIGE_MDIO_GW_OPCODE_MASK,
87+
.shift = MLXBF3_GIGE_MDIO_GW_OPCODE_SHIFT,
88+
},
89+
.st1 = {
90+
.mask = MLXBF3_GIGE_MDIO_GW_ST1_MASK,
91+
.shift = MLXBF3_GIGE_MDIO_GW_ST1_SHIFT,
92+
},
93+
},
94+
};
2995

3096
#define MLXBF_GIGE_MDIO_FREQ_REFERENCE 156250000ULL
3197
#define MLXBF_GIGE_MDIO_COREPLL_CONST 16384ULL
@@ -47,37 +113,22 @@
47113
/* Busy bit is set by software and cleared by hardware */
48114
#define MLXBF_GIGE_MDIO_SET_BUSY 0x1
49115

50-
/* MDIO GW register bits */
51-
#define MLXBF_GIGE_MDIO_GW_AD_MASK GENMASK(15, 0)
52-
#define MLXBF_GIGE_MDIO_GW_DEVAD_MASK GENMASK(20, 16)
53-
#define MLXBF_GIGE_MDIO_GW_PARTAD_MASK GENMASK(25, 21)
54-
#define MLXBF_GIGE_MDIO_GW_OPCODE_MASK GENMASK(27, 26)
55-
#define MLXBF_GIGE_MDIO_GW_ST1_MASK GENMASK(28, 28)
56-
#define MLXBF_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30)
57-
58-
/* MDIO config register bits */
59-
#define MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0)
60-
#define MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK GENMASK(2, 2)
61-
#define MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(4, 4)
62-
#define MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(15, 8)
63-
#define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16)
64-
#define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24)
65-
66-
#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
67-
FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
68-
FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
69-
FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
70-
FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
71-
72116
#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30
73117
#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c
118+
#define MLXBF_GIGE_BF3_COREPLL_ADDR 0x13409824
119+
#define MLXBF_GIGE_BF3_COREPLL_SIZE 0x00000010
74120

75121
static struct resource corepll_params[] = {
76122
[MLXBF_GIGE_VERSION_BF2] = {
77123
.start = MLXBF_GIGE_BF2_COREPLL_ADDR,
78124
.end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1,
79125
.name = "COREPLL_RES"
80126
},
127+
[MLXBF_GIGE_VERSION_BF3] = {
128+
.start = MLXBF_GIGE_BF3_COREPLL_ADDR,
129+
.end = MLXBF_GIGE_BF3_COREPLL_ADDR + MLXBF_GIGE_BF3_COREPLL_SIZE - 1,
130+
.name = "COREPLL_RES"
131+
}
81132
};
82133

83134
/* Returns core clock i1clk in Hz */
@@ -134,19 +185,23 @@ static u8 mdio_period_map(struct mlxbf_gige *priv)
134185
return mdio_period;
135186
}
136187

137-
static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add,
188+
static u32 mlxbf_gige_mdio_create_cmd(struct mlxbf_gige_mdio_gw *mdio_gw, u16 data, int phy_add,
138189
int phy_reg, u32 opcode)
139190
{
140191
u32 gw_reg = 0;
141192

142-
gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_AD_MASK, data);
143-
gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_DEVAD_MASK, phy_reg);
144-
gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_PARTAD_MASK, phy_add);
145-
gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_OPCODE_MASK, opcode);
146-
gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_ST1_MASK,
147-
MLXBF_GIGE_MDIO_CL22_ST1);
148-
gw_reg |= FIELD_PREP(MLXBF_GIGE_MDIO_GW_BUSY_MASK,
149-
MLXBF_GIGE_MDIO_SET_BUSY);
193+
gw_reg |= ((data << mdio_gw->write_data.shift) &
194+
mdio_gw->write_data.mask);
195+
gw_reg |= ((phy_reg << mdio_gw->devad.shift) &
196+
mdio_gw->devad.mask);
197+
gw_reg |= ((phy_add << mdio_gw->partad.shift) &
198+
mdio_gw->partad.mask);
199+
gw_reg |= ((opcode << mdio_gw->opcode.shift) &
200+
mdio_gw->opcode.mask);
201+
gw_reg |= ((MLXBF_GIGE_MDIO_CL22_ST1 << mdio_gw->st1.shift) &
202+
mdio_gw->st1.mask);
203+
gw_reg |= ((MLXBF_GIGE_MDIO_SET_BUSY << mdio_gw->busy.shift) &
204+
mdio_gw->busy.mask);
150205

151206
return gw_reg;
152207
}
@@ -162,25 +217,26 @@ static int mlxbf_gige_mdio_read(struct mii_bus *bus, int phy_add, int phy_reg)
162217
return -EOPNOTSUPP;
163218

164219
/* Send mdio read request */
165-
cmd = mlxbf_gige_mdio_create_cmd(0, phy_add, phy_reg, MLXBF_GIGE_MDIO_CL22_READ);
220+
cmd = mlxbf_gige_mdio_create_cmd(priv->mdio_gw, 0, phy_add, phy_reg,
221+
MLXBF_GIGE_MDIO_CL22_READ);
166222

167-
writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
223+
writel(cmd, priv->mdio_io + priv->mdio_gw->gw_address);
168224

169-
ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET,
170-
val, !(val & MLXBF_GIGE_MDIO_GW_BUSY_MASK),
225+
ret = readl_poll_timeout_atomic(priv->mdio_io + priv->mdio_gw->gw_address,
226+
val, !(val & priv->mdio_gw->busy.mask),
171227
5, 1000000);
172228

173229
if (ret) {
174-
writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
230+
writel(0, priv->mdio_io + priv->mdio_gw->gw_address);
175231
return ret;
176232
}
177233

178-
ret = readl(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
234+
ret = readl(priv->mdio_io + priv->mdio_gw->read_data_address);
179235
/* Only return ad bits of the gw register */
180-
ret &= MLXBF_GIGE_MDIO_GW_AD_MASK;
236+
ret &= priv->mdio_gw->read_data.mask;
181237

182238
/* The MDIO lock is set on read. To release it, clear gw register */
183-
writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
239+
writel(0, priv->mdio_io + priv->mdio_gw->gw_address);
184240

185241
return ret;
186242
}
@@ -197,17 +253,17 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
197253
return -EOPNOTSUPP;
198254

199255
/* Send mdio write request */
200-
cmd = mlxbf_gige_mdio_create_cmd(val, phy_add, phy_reg,
256+
cmd = mlxbf_gige_mdio_create_cmd(priv->mdio_gw, val, phy_add, phy_reg,
201257
MLXBF_GIGE_MDIO_CL22_WRITE);
202-
writel(cmd, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
258+
writel(cmd, priv->mdio_io + priv->mdio_gw->gw_address);
203259

204260
/* If the poll timed out, drop the request */
205-
ret = readl_poll_timeout_atomic(priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET,
206-
temp, !(temp & MLXBF_GIGE_MDIO_GW_BUSY_MASK),
261+
ret = readl_poll_timeout_atomic(priv->mdio_io + priv->mdio_gw->gw_address,
262+
temp, !(temp & priv->mdio_gw->busy.mask),
207263
5, 1000000);
208264

209265
/* The MDIO lock is set on read. To release it, clear gw register */
210-
writel(0, priv->mdio_io + MLXBF_GIGE_MDIO_GW_OFFSET);
266+
writel(0, priv->mdio_io + priv->mdio_gw->gw_address);
211267

212268
return ret;
213269
}
@@ -219,9 +275,20 @@ static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv)
219275

220276
mdio_period = mdio_period_map(priv);
221277

222-
val = MLXBF_GIGE_MDIO_CFG_VAL;
223-
val |= FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period);
224-
writel(val, priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
278+
if (priv->hw_version == MLXBF_GIGE_VERSION_BF2) {
279+
val = MLXBF2_GIGE_MDIO_CFG_VAL;
280+
val |= FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period);
281+
writel(val, priv->mdio_io + MLXBF2_GIGE_MDIO_CFG_OFFSET);
282+
} else {
283+
val = FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) |
284+
FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1);
285+
writel(val, priv->mdio_io + MLXBF3_GIGE_MDIO_CFG_REG0);
286+
val = FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period);
287+
writel(val, priv->mdio_io + MLXBF3_GIGE_MDIO_CFG_REG1);
288+
val = FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) |
289+
FIELD_PREP(MLXBF3_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13);
290+
writel(val, priv->mdio_io + MLXBF3_GIGE_MDIO_CFG_REG2);
291+
}
225292
}
226293

227294
int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
@@ -230,6 +297,9 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
230297
struct resource *res;
231298
int ret;
232299

300+
if (priv->hw_version > MLXBF_GIGE_VERSION_BF3)
301+
return -ENODEV;
302+
233303
priv->mdio_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MDIO9);
234304
if (IS_ERR(priv->mdio_io))
235305
return PTR_ERR(priv->mdio_io);
@@ -242,13 +312,15 @@ int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
242312
/* For backward compatibility with older ACPI tables, also keep
243313
* CLK resource internal to the driver.
244314
*/
245-
res = &corepll_params[MLXBF_GIGE_VERSION_BF2];
315+
res = &corepll_params[priv->hw_version];
246316
}
247317

248318
priv->clk_io = devm_ioremap(dev, res->start, resource_size(res));
249319
if (!priv->clk_io)
250320
return -ENOMEM;
251321

322+
priv->mdio_gw = &mlxbf_gige_mdio_gw_t[priv->hw_version];
323+
252324
mlxbf_gige_mdio_cfg(priv);
253325

254326
priv->mdiobus = devm_mdiobus_alloc(dev);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
2+
3+
/* MDIO support for Mellanox Gigabit Ethernet driver
4+
*
5+
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES, ALL RIGHTS RESERVED.
6+
*
7+
* This software product is a proprietary product of NVIDIA CORPORATION &
8+
* AFFILIATES (the "Company") and all right, title, and interest in and to the
9+
* software product, including all associated intellectual property rights, are
10+
* and shall remain exclusively with the Company.
11+
*
12+
* This software product is governed by the End User License Agreement
13+
* provided with the software product.
14+
*/
15+
16+
#ifndef __MLXBF_GIGE_MDIO_BF2_H__
17+
#define __MLXBF_GIGE_MDIO_BF2_H__
18+
19+
#include <linux/bitfield.h>
20+
21+
#define MLXBF2_GIGE_MDIO_GW_OFFSET 0x0
22+
#define MLXBF2_GIGE_MDIO_CFG_OFFSET 0x4
23+
24+
/* MDIO GW register bits */
25+
#define MLXBF2_GIGE_MDIO_GW_AD_MASK GENMASK(15, 0)
26+
#define MLXBF2_GIGE_MDIO_GW_DEVAD_MASK GENMASK(20, 16)
27+
#define MLXBF2_GIGE_MDIO_GW_PARTAD_MASK GENMASK(25, 21)
28+
#define MLXBF2_GIGE_MDIO_GW_OPCODE_MASK GENMASK(27, 26)
29+
#define MLXBF2_GIGE_MDIO_GW_ST1_MASK GENMASK(28, 28)
30+
#define MLXBF2_GIGE_MDIO_GW_BUSY_MASK GENMASK(30, 30)
31+
32+
#define MLXBF2_GIGE_MDIO_GW_AD_SHIFT 0
33+
#define MLXBF2_GIGE_MDIO_GW_DEVAD_SHIFT 16
34+
#define MLXBF2_GIGE_MDIO_GW_PARTAD_SHIFT 21
35+
#define MLXBF2_GIGE_MDIO_GW_OPCODE_SHIFT 26
36+
#define MLXBF2_GIGE_MDIO_GW_ST1_SHIFT 28
37+
#define MLXBF2_GIGE_MDIO_GW_BUSY_SHIFT 30
38+
39+
/* MDIO config register bits */
40+
#define MLXBF2_GIGE_MDIO_CFG_MDIO_MODE_MASK GENMASK(1, 0)
41+
#define MLXBF2_GIGE_MDIO_CFG_MDIO3_3_MASK GENMASK(2, 2)
42+
#define MLXBF2_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK GENMASK(4, 4)
43+
#define MLXBF2_GIGE_MDIO_CFG_MDC_PERIOD_MASK GENMASK(15, 8)
44+
#define MLXBF2_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK GENMASK(23, 16)
45+
#define MLXBF2_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK GENMASK(31, 24)
46+
47+
#define MLXBF2_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
48+
FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
49+
FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
50+
FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
51+
FIELD_PREP(MLXBF2_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
52+
53+
#endif /* __MLXBF_GIGE_MDIO_BF2_H__ */

0 commit comments

Comments
 (0)