Skip to content

Commit 6517798

Browse files
claudiu-mdavem330
authored andcommitted
enetc: Make MDIO accessors more generic and export to include/linux/fsl
Within the LS1028A SoC, the register map for the ENETC MDIO controller is instantiated a few times: for the central (external) MDIO controller, for the internal bus of each standalone ENETC port, and for the internal bus of the Felix switch. Refactoring is needed to support multiple MDIO buses from multiple drivers. The enetc_hw structure is made an opaque type and a smaller enetc_mdio_priv is created. 'mdio_base' - MDIO registers base address - is being parameterized, to be able to work with different MDIO register bases. The ENETC MDIO bus operations are exported from the fsl-enetc-mdio kernel object, the same that registers the central MDIO controller (the dedicated PF). The ENETC main driver has been changed to select it, and use its exported helpers to further register its private MDIO bus. The DSA Felix driver will do the same. Signed-off-by: Claudiu Manoil <[email protected]> Signed-off-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 787cac3 commit 6517798

File tree

9 files changed

+176
-99
lines changed

9 files changed

+176
-99
lines changed

drivers/net/ethernet/freescale/enetc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
config FSL_ENETC
33
tristate "ENETC PF driver"
44
depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST)
5+
select FSL_ENETC_MDIO
56
select PHYLIB
67
help
78
This driver supports NXP ENETC gigabit ethernet controller PCIe

drivers/net/ethernet/freescale/enetc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
common-objs := enetc.o enetc_cbdr.o enetc_ethtool.o
44

55
obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
6-
fsl-enetc-y := enetc_pf.o enetc_mdio.o $(common-objs)
6+
fsl-enetc-y := enetc_pf.o $(common-objs)
77
fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
88
fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
99

drivers/net/ethernet/freescale/enetc/enetc_hw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ enum enetc_bdr_type {TX, RX};
200200
#define ENETC_PFPMR 0x1900
201201
#define ENETC_PFPMR_PMACE BIT(1)
202202
#define ENETC_PFPMR_MWLM BIT(0)
203+
#define ENETC_EMDIO_BASE 0x1c00
203204
#define ENETC_PSIUMHFR0(n, err) (((err) ? 0x1d08 : 0x1d00) + (n) * 0x10)
204205
#define ENETC_PSIUMHFR1(n) (0x1d04 + (n) * 0x10)
205206
#define ENETC_PSIMMHFR0(n, err) (((err) ? 0x1d00 : 0x1d08) + (n) * 0x10)
Lines changed: 45 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
22
/* Copyright 2019 NXP */
33

4+
#include <linux/fsl/enetc_mdio.h>
45
#include <linux/mdio.h>
56
#include <linux/of_mdio.h>
67
#include <linux/iopoll.h>
78
#include <linux/of.h>
89

9-
#include "enetc_mdio.h"
10+
#include "enetc_pf.h"
1011

11-
#define ENETC_MDIO_REG_OFFSET 0x1c00
1212
#define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */
1313
#define ENETC_MDIO_CTL 0x4 /* MDIO control */
1414
#define ENETC_MDIO_DATA 0x8 /* MDIO data */
1515
#define ENETC_MDIO_ADDR 0xc /* MDIO address */
1616

17-
#define enetc_mdio_rd(hw, off) \
18-
enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET)
19-
#define enetc_mdio_wr(hw, off, val) \
20-
enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val)
21-
#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off)
17+
static inline u32 _enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
18+
{
19+
return enetc_port_rd(mdio_priv->hw, mdio_priv->mdio_base + off);
20+
}
21+
22+
static inline void _enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
23+
u32 val)
24+
{
25+
enetc_port_wr(mdio_priv->hw, mdio_priv->mdio_base + off, val);
26+
}
27+
28+
#define enetc_mdio_rd(mdio_priv, off) \
29+
_enetc_mdio_rd(mdio_priv, ENETC_##off)
30+
#define enetc_mdio_wr(mdio_priv, off, val) \
31+
_enetc_mdio_wr(mdio_priv, ENETC_##off, val)
32+
#define enetc_mdio_rd_reg(off) enetc_mdio_rd(mdio_priv, off)
2233

2334
#define ENETC_MDC_DIV 258
2435

@@ -35,7 +46,7 @@
3546
#define MDIO_DATA(x) ((x) & 0xffff)
3647

3748
#define TIMEOUT 1000
38-
static int enetc_mdio_wait_complete(struct enetc_hw *hw)
49+
static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
3950
{
4051
u32 val;
4152

@@ -46,7 +57,6 @@ static int enetc_mdio_wait_complete(struct enetc_hw *hw)
4657
int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
4758
{
4859
struct enetc_mdio_priv *mdio_priv = bus->priv;
49-
struct enetc_hw *hw = mdio_priv->hw;
5060
u32 mdio_ctl, mdio_cfg;
5161
u16 dev_addr;
5262
int ret;
@@ -61,39 +71,39 @@ int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
6171
mdio_cfg &= ~MDIO_CFG_ENC45;
6272
}
6373

64-
enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
74+
enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg);
6575

66-
ret = enetc_mdio_wait_complete(hw);
76+
ret = enetc_mdio_wait_complete(mdio_priv);
6777
if (ret)
6878
return ret;
6979

7080
/* set port and dev addr */
7181
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
72-
enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
82+
enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl);
7383

7484
/* set the register address */
7585
if (regnum & MII_ADDR_C45) {
76-
enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
86+
enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff);
7787

78-
ret = enetc_mdio_wait_complete(hw);
88+
ret = enetc_mdio_wait_complete(mdio_priv);
7989
if (ret)
8090
return ret;
8191
}
8292

8393
/* write the value */
84-
enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value));
94+
enetc_mdio_wr(mdio_priv, MDIO_DATA, MDIO_DATA(value));
8595

86-
ret = enetc_mdio_wait_complete(hw);
96+
ret = enetc_mdio_wait_complete(mdio_priv);
8797
if (ret)
8898
return ret;
8999

90100
return 0;
91101
}
102+
EXPORT_SYMBOL_GPL(enetc_mdio_write);
92103

93104
int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
94105
{
95106
struct enetc_mdio_priv *mdio_priv = bus->priv;
96-
struct enetc_hw *hw = mdio_priv->hw;
97107
u32 mdio_ctl, mdio_cfg;
98108
u16 dev_addr, value;
99109
int ret;
@@ -107,86 +117,56 @@ int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
107117
mdio_cfg &= ~MDIO_CFG_ENC45;
108118
}
109119

110-
enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
120+
enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg);
111121

112-
ret = enetc_mdio_wait_complete(hw);
122+
ret = enetc_mdio_wait_complete(mdio_priv);
113123
if (ret)
114124
return ret;
115125

116126
/* set port and device addr */
117127
mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
118-
enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
128+
enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl);
119129

120130
/* set the register address */
121131
if (regnum & MII_ADDR_C45) {
122-
enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
132+
enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff);
123133

124-
ret = enetc_mdio_wait_complete(hw);
134+
ret = enetc_mdio_wait_complete(mdio_priv);
125135
if (ret)
126136
return ret;
127137
}
128138

129139
/* initiate the read */
130-
enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
140+
enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
131141

132-
ret = enetc_mdio_wait_complete(hw);
142+
ret = enetc_mdio_wait_complete(mdio_priv);
133143
if (ret)
134144
return ret;
135145

136146
/* return all Fs if nothing was there */
137-
if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) {
147+
if (enetc_mdio_rd(mdio_priv, MDIO_CFG) & MDIO_CFG_RD_ER) {
138148
dev_dbg(&bus->dev,
139149
"Error while reading PHY%d reg at %d.%hhu\n",
140150
phy_id, dev_addr, regnum);
141151
return 0xffff;
142152
}
143153

144-
value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff;
154+
value = enetc_mdio_rd(mdio_priv, MDIO_DATA) & 0xffff;
145155

146156
return value;
147157
}
158+
EXPORT_SYMBOL_GPL(enetc_mdio_read);
148159

149-
int enetc_mdio_probe(struct enetc_pf *pf)
160+
struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
150161
{
151-
struct device *dev = &pf->si->pdev->dev;
152-
struct enetc_mdio_priv *mdio_priv;
153-
struct device_node *np;
154-
struct mii_bus *bus;
155-
int err;
156-
157-
bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
158-
if (!bus)
159-
return -ENOMEM;
160-
161-
bus->name = "Freescale ENETC MDIO Bus";
162-
bus->read = enetc_mdio_read;
163-
bus->write = enetc_mdio_write;
164-
bus->parent = dev;
165-
mdio_priv = bus->priv;
166-
mdio_priv->hw = &pf->si->hw;
167-
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
168-
169-
np = of_get_child_by_name(dev->of_node, "mdio");
170-
if (!np) {
171-
dev_err(dev, "MDIO node missing\n");
172-
return -EINVAL;
173-
}
174-
175-
err = of_mdiobus_register(bus, np);
176-
if (err) {
177-
of_node_put(np);
178-
dev_err(dev, "cannot register MDIO bus\n");
179-
return err;
180-
}
162+
struct enetc_hw *hw;
181163

182-
of_node_put(np);
183-
pf->mdio = bus;
164+
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
165+
if (!hw)
166+
return ERR_PTR(-ENOMEM);
184167

185-
return 0;
186-
}
168+
hw->port = port_regs;
187169

188-
void enetc_mdio_remove(struct enetc_pf *pf)
189-
{
190-
if (pf->mdio)
191-
mdiobus_unregister(pf->mdio);
170+
return hw;
192171
}
172+
EXPORT_SYMBOL_GPL(enetc_hw_alloc);

drivers/net/ethernet/freescale/enetc/enetc_mdio.h

Lines changed: 0 additions & 12 deletions
This file was deleted.

drivers/net/ethernet/freescale/enetc/enetc_pci_mdio.c

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
22
/* Copyright 2019 NXP */
3+
#include <linux/fsl/enetc_mdio.h>
34
#include <linux/of_mdio.h>
4-
#include "enetc_mdio.h"
5+
#include "enetc_pf.h"
56

67
#define ENETC_MDIO_DEV_ID 0xee01
78
#define ENETC_MDIO_DEV_NAME "FSL PCIe IE Central MDIO"
@@ -13,31 +14,44 @@ static int enetc_pci_mdio_probe(struct pci_dev *pdev,
1314
{
1415
struct enetc_mdio_priv *mdio_priv;
1516
struct device *dev = &pdev->dev;
17+
void __iomem *port_regs;
1618
struct enetc_hw *hw;
1719
struct mii_bus *bus;
1820
int err;
1921

20-
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
21-
if (!hw)
22-
return -ENOMEM;
22+
port_regs = pci_iomap(pdev, 0, 0);
23+
if (!port_regs) {
24+
dev_err(dev, "iomap failed\n");
25+
err = -ENXIO;
26+
goto err_ioremap;
27+
}
28+
29+
hw = enetc_hw_alloc(dev, port_regs);
30+
if (IS_ERR(enetc_hw_alloc)) {
31+
err = PTR_ERR(hw);
32+
goto err_hw_alloc;
33+
}
2334

2435
bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
25-
if (!bus)
26-
return -ENOMEM;
36+
if (!bus) {
37+
err = -ENOMEM;
38+
goto err_mdiobus_alloc;
39+
}
2740

2841
bus->name = ENETC_MDIO_BUS_NAME;
2942
bus->read = enetc_mdio_read;
3043
bus->write = enetc_mdio_write;
3144
bus->parent = dev;
3245
mdio_priv = bus->priv;
3346
mdio_priv->hw = hw;
47+
mdio_priv->mdio_base = ENETC_EMDIO_BASE;
3448
snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
3549

3650
pcie_flr(pdev);
3751
err = pci_enable_device_mem(pdev);
3852
if (err) {
3953
dev_err(dev, "device enable failed\n");
40-
return err;
54+
goto err_pci_enable;
4155
}
4256

4357
err = pci_request_region(pdev, 0, KBUILD_MODNAME);
@@ -46,13 +60,6 @@ static int enetc_pci_mdio_probe(struct pci_dev *pdev,
4660
goto err_pci_mem_reg;
4761
}
4862

49-
hw->port = pci_iomap(pdev, 0, 0);
50-
if (!hw->port) {
51-
err = -ENXIO;
52-
dev_err(dev, "iomap failed\n");
53-
goto err_ioremap;
54-
}
55-
5663
err = of_mdiobus_register(bus, dev->of_node);
5764
if (err)
5865
goto err_mdiobus_reg;
@@ -62,12 +69,14 @@ static int enetc_pci_mdio_probe(struct pci_dev *pdev,
6269
return 0;
6370

6471
err_mdiobus_reg:
65-
iounmap(mdio_priv->hw->port);
66-
err_ioremap:
6772
pci_release_mem_regions(pdev);
6873
err_pci_mem_reg:
6974
pci_disable_device(pdev);
70-
75+
err_pci_enable:
76+
err_mdiobus_alloc:
77+
iounmap(port_regs);
78+
err_hw_alloc:
79+
err_ioremap:
7180
return err;
7281
}
7382

0 commit comments

Comments
 (0)