]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*******************************************************************************
3 STMMAC Ethernet Driver -- MDIO bus implementation
4 Provides Bus interface for MII registers
6 Copyright (C) 2007-2009 STMicroelectronics Ltd
9 Author: Carl Shaw <carl.shaw@st.com>
10 Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
11 *******************************************************************************/
13 #include <linux/gpio/consumer.h>
15 #include <linux/iopoll.h>
16 #include <linux/mii.h>
17 #include <linux/of_mdio.h>
18 #include <linux/phy.h>
19 #include <linux/property.h>
20 #include <linux/slab.h>
25 #define MII_BUSY 0x00000001
26 #define MII_WRITE 0x00000002
27 #define MII_DATA_MASK GENMASK(15, 0)
30 #define MII_GMAC4_GOC_SHIFT 2
31 #define MII_GMAC4_REG_ADDR_SHIFT 16
32 #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)
33 #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)
34 #define MII_GMAC4_C45E BIT(1)
37 #define MII_XGMAC_SADDR BIT(18)
38 #define MII_XGMAC_CMD_SHIFT 16
39 #define MII_XGMAC_WRITE (1 << MII_XGMAC_CMD_SHIFT)
40 #define MII_XGMAC_READ (3 << MII_XGMAC_CMD_SHIFT)
41 #define MII_XGMAC_BUSY BIT(22)
42 #define MII_XGMAC_MAX_C22ADDR 3
43 #define MII_XGMAC_C22P_MASK GENMASK(MII_XGMAC_MAX_C22ADDR, 0)
44 #define MII_XGMAC_PA_SHIFT 16
45 #define MII_XGMAC_DA_SHIFT 21
47 static int stmmac_xgmac2_c45_format(struct stmmac_priv
*priv
, int phyaddr
,
48 int phyreg
, u32
*hw_addr
)
52 /* Set port as Clause 45 */
53 tmp
= readl(priv
->ioaddr
+ XGMAC_MDIO_C22P
);
55 writel(tmp
, priv
->ioaddr
+ XGMAC_MDIO_C22P
);
57 *hw_addr
= (phyaddr
<< MII_XGMAC_PA_SHIFT
) | (phyreg
& 0xffff);
58 *hw_addr
|= (phyreg
>> MII_DEVADDR_C45_SHIFT
) << MII_XGMAC_DA_SHIFT
;
62 static int stmmac_xgmac2_c22_format(struct stmmac_priv
*priv
, int phyaddr
,
63 int phyreg
, u32
*hw_addr
)
67 /* HW does not support C22 addr >= 4 */
68 if (phyaddr
> MII_XGMAC_MAX_C22ADDR
)
71 /* Set port as Clause 22 */
72 tmp
= readl(priv
->ioaddr
+ XGMAC_MDIO_C22P
);
73 tmp
&= ~MII_XGMAC_C22P_MASK
;
75 writel(tmp
, priv
->ioaddr
+ XGMAC_MDIO_C22P
);
77 *hw_addr
= (phyaddr
<< MII_XGMAC_PA_SHIFT
) | (phyreg
& 0x1f);
81 static int stmmac_xgmac2_mdio_read(struct mii_bus
*bus
, int phyaddr
, int phyreg
)
83 struct net_device
*ndev
= bus
->priv
;
84 struct stmmac_priv
*priv
= netdev_priv(ndev
);
85 unsigned int mii_address
= priv
->hw
->mii
.addr
;
86 unsigned int mii_data
= priv
->hw
->mii
.data
;
87 u32 tmp
, addr
, value
= MII_XGMAC_BUSY
;
90 /* Wait until any existing MII operation is complete */
91 if (readl_poll_timeout(priv
->ioaddr
+ mii_data
, tmp
,
92 !(tmp
& MII_XGMAC_BUSY
), 100, 10000))
95 if (phyreg
& MII_ADDR_C45
) {
96 phyreg
&= ~MII_ADDR_C45
;
98 ret
= stmmac_xgmac2_c45_format(priv
, phyaddr
, phyreg
, &addr
);
102 ret
= stmmac_xgmac2_c22_format(priv
, phyaddr
, phyreg
, &addr
);
106 value
|= MII_XGMAC_SADDR
;
109 value
|= (priv
->clk_csr
<< priv
->hw
->mii
.clk_csr_shift
)
110 & priv
->hw
->mii
.clk_csr_mask
;
111 value
|= MII_XGMAC_READ
;
113 /* Wait until any existing MII operation is complete */
114 if (readl_poll_timeout(priv
->ioaddr
+ mii_data
, tmp
,
115 !(tmp
& MII_XGMAC_BUSY
), 100, 10000))
118 /* Set the MII address register to read */
119 writel(addr
, priv
->ioaddr
+ mii_address
);
120 writel(value
, priv
->ioaddr
+ mii_data
);
122 /* Wait until any existing MII operation is complete */
123 if (readl_poll_timeout(priv
->ioaddr
+ mii_data
, tmp
,
124 !(tmp
& MII_XGMAC_BUSY
), 100, 10000))
127 /* Read the data from the MII data register */
128 return readl(priv
->ioaddr
+ mii_data
) & GENMASK(15, 0);
131 static int stmmac_xgmac2_mdio_write(struct mii_bus
*bus
, int phyaddr
,
132 int phyreg
, u16 phydata
)
134 struct net_device
*ndev
= bus
->priv
;
135 struct stmmac_priv
*priv
= netdev_priv(ndev
);
136 unsigned int mii_address
= priv
->hw
->mii
.addr
;
137 unsigned int mii_data
= priv
->hw
->mii
.data
;
138 u32 addr
, tmp
, value
= MII_XGMAC_BUSY
;
141 /* Wait until any existing MII operation is complete */
142 if (readl_poll_timeout(priv
->ioaddr
+ mii_data
, tmp
,
143 !(tmp
& MII_XGMAC_BUSY
), 100, 10000))
146 if (phyreg
& MII_ADDR_C45
) {
147 phyreg
&= ~MII_ADDR_C45
;
149 ret
= stmmac_xgmac2_c45_format(priv
, phyaddr
, phyreg
, &addr
);
153 ret
= stmmac_xgmac2_c22_format(priv
, phyaddr
, phyreg
, &addr
);
157 value
|= MII_XGMAC_SADDR
;
160 value
|= (priv
->clk_csr
<< priv
->hw
->mii
.clk_csr_shift
)
161 & priv
->hw
->mii
.clk_csr_mask
;
163 value
|= MII_XGMAC_WRITE
;
165 /* Wait until any existing MII operation is complete */
166 if (readl_poll_timeout(priv
->ioaddr
+ mii_data
, tmp
,
167 !(tmp
& MII_XGMAC_BUSY
), 100, 10000))
170 /* Set the MII address register to write */
171 writel(addr
, priv
->ioaddr
+ mii_address
);
172 writel(value
, priv
->ioaddr
+ mii_data
);
174 /* Wait until any existing MII operation is complete */
175 return readl_poll_timeout(priv
->ioaddr
+ mii_data
, tmp
,
176 !(tmp
& MII_XGMAC_BUSY
), 100, 10000);
181 * @bus: points to the mii_bus structure
184 * Description: it reads data from the MII register from within the phy device.
185 * For the 7111 GMAC, we must set the bit 0 in the MII address register while
186 * accessing the PHY registers.
187 * Fortunately, it seems this has no drawback for the 7109 MAC.
189 static int stmmac_mdio_read(struct mii_bus
*bus
, int phyaddr
, int phyreg
)
191 struct net_device
*ndev
= bus
->priv
;
192 struct stmmac_priv
*priv
= netdev_priv(ndev
);
193 unsigned int mii_address
= priv
->hw
->mii
.addr
;
194 unsigned int mii_data
= priv
->hw
->mii
.data
;
195 u32 value
= MII_BUSY
;
199 value
|= (phyaddr
<< priv
->hw
->mii
.addr_shift
)
200 & priv
->hw
->mii
.addr_mask
;
201 value
|= (phyreg
<< priv
->hw
->mii
.reg_shift
) & priv
->hw
->mii
.reg_mask
;
202 value
|= (priv
->clk_csr
<< priv
->hw
->mii
.clk_csr_shift
)
203 & priv
->hw
->mii
.clk_csr_mask
;
204 if (priv
->plat
->has_gmac4
) {
205 value
|= MII_GMAC4_READ
;
206 if (phyreg
& MII_ADDR_C45
) {
207 value
|= MII_GMAC4_C45E
;
208 value
&= ~priv
->hw
->mii
.reg_mask
;
209 value
|= ((phyreg
>> MII_DEVADDR_C45_SHIFT
) <<
210 priv
->hw
->mii
.reg_shift
) &
211 priv
->hw
->mii
.reg_mask
;
213 data
|= (phyreg
& MII_REGADDR_C45_MASK
) <<
214 MII_GMAC4_REG_ADDR_SHIFT
;
218 if (readl_poll_timeout(priv
->ioaddr
+ mii_address
, v
, !(v
& MII_BUSY
),
222 writel(data
, priv
->ioaddr
+ mii_data
);
223 writel(value
, priv
->ioaddr
+ mii_address
);
225 if (readl_poll_timeout(priv
->ioaddr
+ mii_address
, v
, !(v
& MII_BUSY
),
229 /* Read the data from the MII data register */
230 data
= (int)readl(priv
->ioaddr
+ mii_data
) & MII_DATA_MASK
;
237 * @bus: points to the mii_bus structure
241 * Description: it writes the data into the MII register from within the device.
243 static int stmmac_mdio_write(struct mii_bus
*bus
, int phyaddr
, int phyreg
,
246 struct net_device
*ndev
= bus
->priv
;
247 struct stmmac_priv
*priv
= netdev_priv(ndev
);
248 unsigned int mii_address
= priv
->hw
->mii
.addr
;
249 unsigned int mii_data
= priv
->hw
->mii
.data
;
250 u32 value
= MII_BUSY
;
254 value
|= (phyaddr
<< priv
->hw
->mii
.addr_shift
)
255 & priv
->hw
->mii
.addr_mask
;
256 value
|= (phyreg
<< priv
->hw
->mii
.reg_shift
) & priv
->hw
->mii
.reg_mask
;
258 value
|= (priv
->clk_csr
<< priv
->hw
->mii
.clk_csr_shift
)
259 & priv
->hw
->mii
.clk_csr_mask
;
260 if (priv
->plat
->has_gmac4
) {
261 value
|= MII_GMAC4_WRITE
;
262 if (phyreg
& MII_ADDR_C45
) {
263 value
|= MII_GMAC4_C45E
;
264 value
&= ~priv
->hw
->mii
.reg_mask
;
265 value
|= ((phyreg
>> MII_DEVADDR_C45_SHIFT
) <<
266 priv
->hw
->mii
.reg_shift
) &
267 priv
->hw
->mii
.reg_mask
;
269 data
|= (phyreg
& MII_REGADDR_C45_MASK
) <<
270 MII_GMAC4_REG_ADDR_SHIFT
;
276 /* Wait until any existing MII operation is complete */
277 if (readl_poll_timeout(priv
->ioaddr
+ mii_address
, v
, !(v
& MII_BUSY
),
281 /* Set the MII address register to write */
282 writel(data
, priv
->ioaddr
+ mii_data
);
283 writel(value
, priv
->ioaddr
+ mii_address
);
285 /* Wait until any existing MII operation is complete */
286 return readl_poll_timeout(priv
->ioaddr
+ mii_address
, v
, !(v
& MII_BUSY
),
292 * @bus: points to the mii_bus structure
293 * Description: reset the MII bus
295 int stmmac_mdio_reset(struct mii_bus
*bus
)
297 #if IS_ENABLED(CONFIG_STMMAC_PLATFORM)
298 struct net_device
*ndev
= bus
->priv
;
299 struct stmmac_priv
*priv
= netdev_priv(ndev
);
300 unsigned int mii_address
= priv
->hw
->mii
.addr
;
303 if (priv
->device
->of_node
) {
304 struct gpio_desc
*reset_gpio
;
305 u32 delays
[3] = { 0, 0, 0 };
307 reset_gpio
= devm_gpiod_get_optional(priv
->device
,
310 if (IS_ERR(reset_gpio
))
311 return PTR_ERR(reset_gpio
);
313 device_property_read_u32_array(priv
->device
,
314 "snps,reset-delays-us",
315 delays
, ARRAY_SIZE(delays
));
318 msleep(DIV_ROUND_UP(delays
[0], 1000));
320 gpiod_set_value_cansleep(reset_gpio
, 1);
322 msleep(DIV_ROUND_UP(delays
[1], 1000));
324 gpiod_set_value_cansleep(reset_gpio
, 0);
326 msleep(DIV_ROUND_UP(delays
[2], 1000));
330 /* This is a workaround for problems with the STE101P PHY.
331 * It doesn't complete its reset until at least one clock cycle
332 * on MDC, so perform a dummy mdio read. To be updated for GMAC4
335 if (!priv
->plat
->has_gmac4
)
336 writel(0, priv
->ioaddr
+ mii_address
);
342 * stmmac_mdio_register
343 * @ndev: net device structure
344 * Description: it registers the MII bus
346 int stmmac_mdio_register(struct net_device
*ndev
)
349 struct mii_bus
*new_bus
;
350 struct stmmac_priv
*priv
= netdev_priv(ndev
);
351 struct stmmac_mdio_bus_data
*mdio_bus_data
= priv
->plat
->mdio_bus_data
;
352 struct device_node
*mdio_node
= priv
->plat
->mdio_node
;
353 struct device
*dev
= ndev
->dev
.parent
;
354 int addr
, found
, max_addr
;
359 new_bus
= mdiobus_alloc();
363 if (mdio_bus_data
->irqs
)
364 memcpy(new_bus
->irq
, mdio_bus_data
->irqs
, sizeof(new_bus
->irq
));
366 new_bus
->name
= "stmmac";
368 if (priv
->plat
->has_xgmac
) {
369 new_bus
->read
= &stmmac_xgmac2_mdio_read
;
370 new_bus
->write
= &stmmac_xgmac2_mdio_write
;
372 /* Right now only C22 phys are supported */
373 max_addr
= MII_XGMAC_MAX_C22ADDR
+ 1;
375 /* Check if DT specified an unsupported phy addr */
376 if (priv
->plat
->phy_addr
> MII_XGMAC_MAX_C22ADDR
)
377 dev_err(dev
, "Unsupported phy_addr (max=%d)\n",
378 MII_XGMAC_MAX_C22ADDR
);
380 new_bus
->read
= &stmmac_mdio_read
;
381 new_bus
->write
= &stmmac_mdio_write
;
382 max_addr
= PHY_MAX_ADDR
;
385 if (mdio_bus_data
->needs_reset
)
386 new_bus
->reset
= &stmmac_mdio_reset
;
388 snprintf(new_bus
->id
, MII_BUS_ID_SIZE
, "%s-%x",
389 new_bus
->name
, priv
->plat
->bus_id
);
390 new_bus
->priv
= ndev
;
391 new_bus
->phy_mask
= mdio_bus_data
->phy_mask
;
392 new_bus
->parent
= priv
->device
;
394 err
= of_mdiobus_register(new_bus
, mdio_node
);
396 dev_err(dev
, "Cannot register the MDIO bus\n");
397 goto bus_register_fail
;
400 /* Looks like we need a dummy read for XGMAC only and C45 PHYs */
401 if (priv
->plat
->has_xgmac
)
402 stmmac_xgmac2_mdio_read(new_bus
, 0, MII_ADDR_C45
);
404 if (priv
->plat
->phy_node
|| mdio_node
)
405 goto bus_register_done
;
408 for (addr
= 0; addr
< max_addr
; addr
++) {
409 struct phy_device
*phydev
= mdiobus_get_phy(new_bus
, addr
);
415 * If an IRQ was provided to be assigned after
416 * the bus probe, do it here.
418 if (!mdio_bus_data
->irqs
&&
419 (mdio_bus_data
->probed_phy_irq
> 0)) {
420 new_bus
->irq
[addr
] = mdio_bus_data
->probed_phy_irq
;
421 phydev
->irq
= mdio_bus_data
->probed_phy_irq
;
425 * If we're going to bind the MAC to this PHY bus,
426 * and no PHY number was provided to the MAC,
427 * use the one probed here.
429 if (priv
->plat
->phy_addr
== -1)
430 priv
->plat
->phy_addr
= addr
;
432 phy_attached_info(phydev
);
436 if (!found
&& !mdio_node
) {
437 dev_warn(dev
, "No PHY found\n");
438 mdiobus_unregister(new_bus
);
439 mdiobus_free(new_bus
);
449 mdiobus_free(new_bus
);
454 * stmmac_mdio_unregister
455 * @ndev: net device structure
456 * Description: it unregisters the MII bus
458 int stmmac_mdio_unregister(struct net_device
*ndev
)
460 struct stmmac_priv
*priv
= netdev_priv(ndev
);
465 mdiobus_unregister(priv
->mii
);
466 priv
->mii
->priv
= NULL
;
467 mdiobus_free(priv
->mii
);