2 * AMD 10Gb Ethernet driver
4 * This file is available to you under your choice of the following two
9 * Copyright (c) 2014 Advanced Micro Devices, Inc.
11 * This file is free software; you may copy, redistribute and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or (at
14 * your option) any later version.
16 * This file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * This file incorporates work covered by the following copyright and
26 * The Synopsys DWC ETHER XGMAC Software Driver and documentation
27 * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
28 * Inc. unless otherwise expressly agreed to in writing between Synopsys
31 * The Software IS NOT an item of Licensed Software or Licensed Product
32 * under any End User Software License Agreement or Agreement for Licensed
33 * Product with Synopsys or any supplement thereto. Permission is hereby
34 * granted, free of charge, to any person obtaining a copy of this software
35 * annotated with this license and the Software, to deal in the Software
36 * without restriction, including without limitation the rights to use,
37 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
38 * of the Software, and to permit persons to whom the Software is furnished
39 * to do so, subject to the following conditions:
41 * The above copyright notice and this permission notice shall be included
42 * in all copies or substantial portions of the Software.
44 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
45 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
48 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
54 * THE POSSIBILITY OF SUCH DAMAGE.
57 * License 2: Modified BSD
59 * Copyright (c) 2014 Advanced Micro Devices, Inc.
60 * All rights reserved.
62 * Redistribution and use in source and binary forms, with or without
63 * modification, are permitted provided that the following conditions are met:
64 * * Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 * * Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution.
69 * * Neither the name of Advanced Micro Devices, Inc. nor the
70 * names of its contributors may be used to endorse or promote products
71 * derived from this software without specific prior written permission.
73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
74 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
79 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
80 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
84 * This file incorporates work covered by the following copyright and
86 * The Synopsys DWC ETHER XGMAC Software Driver and documentation
87 * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
88 * Inc. unless otherwise expressly agreed to in writing between Synopsys
91 * The Software IS NOT an item of Licensed Software or Licensed Product
92 * under any End User Software License Agreement or Agreement for Licensed
93 * Product with Synopsys or any supplement thereto. Permission is hereby
94 * granted, free of charge, to any person obtaining a copy of this software
95 * annotated with this license and the Software, to deal in the Software
96 * without restriction, including without limitation the rights to use,
97 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
98 * of the Software, and to permit persons to whom the Software is furnished
99 * to do so, subject to the following conditions:
101 * The above copyright notice and this permission notice shall be included
102 * in all copies or substantial portions of the Software.
104 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
105 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
106 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
107 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
108 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
109 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
110 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
111 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
112 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
113 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
114 * THE POSSIBILITY OF SUCH DAMAGE.
117 #include <linux/module.h>
118 #include <linux/kmod.h>
119 #include <linux/spinlock.h>
120 #include <linux/mdio.h>
121 #include <linux/phy.h>
122 #include <linux/of.h>
125 #include "xgbe-common.h"
128 static int xgbe_mdio_read(struct mii_bus
*mii
, int prtad
, int mmd_reg
)
130 struct xgbe_prv_data
*pdata
= mii
->priv
;
131 struct xgbe_hw_if
*hw_if
= &pdata
->hw_if
;
134 DBGPR_MDIO("-->xgbe_mdio_read: prtad=%#x mmd_reg=%#x\n",
137 mmd_data
= hw_if
->read_mmd_regs(pdata
, prtad
, mmd_reg
);
139 DBGPR_MDIO("<--xgbe_mdio_read: mmd_data=%#x\n", mmd_data
);
144 static int xgbe_mdio_write(struct mii_bus
*mii
, int prtad
, int mmd_reg
,
147 struct xgbe_prv_data
*pdata
= mii
->priv
;
148 struct xgbe_hw_if
*hw_if
= &pdata
->hw_if
;
149 int mmd_data
= mmd_val
;
151 DBGPR_MDIO("-->xgbe_mdio_write: prtad=%#x mmd_reg=%#x mmd_data=%#x\n",
152 prtad
, mmd_reg
, mmd_data
);
154 hw_if
->write_mmd_regs(pdata
, prtad
, mmd_reg
, mmd_data
);
156 DBGPR_MDIO("<--xgbe_mdio_write\n");
161 static void xgbe_adjust_link(struct net_device
*netdev
)
163 struct xgbe_prv_data
*pdata
= netdev_priv(netdev
);
164 struct xgbe_hw_if
*hw_if
= &pdata
->hw_if
;
165 struct phy_device
*phydev
= pdata
->phydev
;
171 DBGPR_MDIO("-->xgbe_adjust_link: address=%d, newlink=%d, curlink=%d\n",
172 phydev
->addr
, phydev
->link
, pdata
->phy_link
);
175 /* Flow control support */
176 if (pdata
->pause_autoneg
) {
177 if (phydev
->pause
|| phydev
->asym_pause
) {
186 if (pdata
->tx_pause
!= pdata
->phy_tx_pause
) {
187 hw_if
->config_tx_flow_control(pdata
);
188 pdata
->phy_tx_pause
= pdata
->tx_pause
;
191 if (pdata
->rx_pause
!= pdata
->phy_rx_pause
) {
192 hw_if
->config_rx_flow_control(pdata
);
193 pdata
->phy_rx_pause
= pdata
->rx_pause
;
197 if (phydev
->speed
!= pdata
->phy_speed
) {
200 switch (phydev
->speed
) {
202 hw_if
->set_xgmii_speed(pdata
);
206 hw_if
->set_gmii_2500_speed(pdata
);
210 hw_if
->set_gmii_speed(pdata
);
213 pdata
->phy_speed
= phydev
->speed
;
216 if (phydev
->link
!= pdata
->phy_link
) {
220 } else if (pdata
->phy_link
) {
223 pdata
->phy_speed
= SPEED_UNKNOWN
;
227 phy_print_status(phydev
);
229 DBGPR_MDIO("<--xgbe_adjust_link\n");
232 void xgbe_dump_phy_registers(struct xgbe_prv_data
*pdata
)
234 struct device
*dev
= pdata
->dev
;
235 struct phy_device
*phydev
= pdata
->mii
->phy_map
[XGBE_PRTAD
];
238 dev_alert(dev
, "\n************* PHY Reg dump **********************\n");
240 dev_alert(dev
, "PCS Control Reg (%#04x) = %#04x\n", MDIO_CTRL1
,
241 XMDIO_READ(pdata
, MDIO_MMD_PCS
, MDIO_CTRL1
));
242 dev_alert(dev
, "PCS Status Reg (%#04x) = %#04x\n", MDIO_STAT1
,
243 XMDIO_READ(pdata
, MDIO_MMD_PCS
, MDIO_STAT1
));
244 dev_alert(dev
, "Phy Id (PHYS ID 1 %#04x)= %#04x\n", MDIO_DEVID1
,
245 XMDIO_READ(pdata
, MDIO_MMD_PCS
, MDIO_DEVID1
));
246 dev_alert(dev
, "Phy Id (PHYS ID 2 %#04x)= %#04x\n", MDIO_DEVID2
,
247 XMDIO_READ(pdata
, MDIO_MMD_PCS
, MDIO_DEVID2
));
248 dev_alert(dev
, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS1
,
249 XMDIO_READ(pdata
, MDIO_MMD_PCS
, MDIO_DEVS1
));
250 dev_alert(dev
, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS2
,
251 XMDIO_READ(pdata
, MDIO_MMD_PCS
, MDIO_DEVS2
));
253 dev_alert(dev
, "Auto-Neg Control Reg (%#04x) = %#04x\n", MDIO_CTRL1
,
254 XMDIO_READ(pdata
, MDIO_MMD_AN
, MDIO_CTRL1
));
255 dev_alert(dev
, "Auto-Neg Status Reg (%#04x) = %#04x\n", MDIO_STAT1
,
256 XMDIO_READ(pdata
, MDIO_MMD_AN
, MDIO_STAT1
));
257 dev_alert(dev
, "Auto-Neg Ad Reg 1 (%#04x) = %#04x\n",
259 XMDIO_READ(pdata
, MDIO_MMD_AN
, MDIO_AN_ADVERTISE
));
260 dev_alert(dev
, "Auto-Neg Ad Reg 2 (%#04x) = %#04x\n",
261 MDIO_AN_ADVERTISE
+ 1,
262 XMDIO_READ(pdata
, MDIO_MMD_AN
, MDIO_AN_ADVERTISE
+ 1));
263 dev_alert(dev
, "Auto-Neg Ad Reg 3 (%#04x) = %#04x\n",
264 MDIO_AN_ADVERTISE
+ 2,
265 XMDIO_READ(pdata
, MDIO_MMD_AN
, MDIO_AN_ADVERTISE
+ 2));
266 dev_alert(dev
, "Auto-Neg Completion Reg (%#04x) = %#04x\n",
268 XMDIO_READ(pdata
, MDIO_MMD_AN
, MDIO_AN_COMP_STAT
));
270 dev_alert(dev
, "MMD Device Mask = %#x\n",
271 phydev
->c45_ids
.devices_in_package
);
272 for (i
= 0; i
< ARRAY_SIZE(phydev
->c45_ids
.device_ids
); i
++)
273 dev_alert(dev
, " MMD %d: ID = %#08x\n", i
,
274 phydev
->c45_ids
.device_ids
[i
]);
276 dev_alert(dev
, "\n*************************************************\n");
279 int xgbe_mdio_register(struct xgbe_prv_data
*pdata
)
281 struct net_device
*netdev
= pdata
->netdev
;
282 struct device_node
*phy_node
;
284 struct phy_device
*phydev
;
287 DBGPR("-->xgbe_mdio_register\n");
289 /* Retrieve the phy-handle */
290 phy_node
= of_parse_phandle(pdata
->dev
->of_node
, "phy-handle", 0);
292 dev_err(pdata
->dev
, "unable to parse phy-handle\n");
296 /* Register with the MDIO bus */
297 mii
= mdiobus_alloc();
299 dev_err(pdata
->dev
, "mdiobus_alloc failed\n");
304 /* Register on the MDIO bus (don't probe any PHYs) */
305 mii
->name
= XGBE_PHY_NAME
;
306 mii
->read
= xgbe_mdio_read
;
307 mii
->write
= xgbe_mdio_write
;
308 snprintf(mii
->id
, sizeof(mii
->id
), "%s", pdata
->mii_bus_id
);
311 mii
->parent
= pdata
->dev
;
312 ret
= mdiobus_register(mii
);
314 dev_err(pdata
->dev
, "mdiobus_register failed\n");
315 goto err_mdiobus_alloc
;
317 DBGPR(" mdiobus_register succeeded for %s\n", pdata
->mii_bus_id
);
319 /* Probe the PCS using Clause 45 */
320 phydev
= get_phy_device(mii
, XGBE_PRTAD
, true);
321 if (IS_ERR(phydev
) || !phydev
||
322 !phydev
->c45_ids
.device_ids
[MDIO_MMD_PCS
]) {
323 dev_err(pdata
->dev
, "get_phy_device failed\n");
324 ret
= phydev
? PTR_ERR(phydev
) : -ENOLINK
;
325 goto err_mdiobus_register
;
327 request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT
,
328 MDIO_ID_ARGS(phydev
->c45_ids
.device_ids
[MDIO_MMD_PCS
]));
330 of_node_get(phy_node
);
331 phydev
->dev
.of_node
= phy_node
;
332 ret
= phy_device_register(phydev
);
334 dev_err(pdata
->dev
, "phy_device_register failed\n");
335 of_node_put(phy_node
);
339 /* Add a reference to the PHY driver so it can't be unloaded */
340 pdata
->phy_module
= phydev
->dev
.driver
?
341 phydev
->dev
.driver
->owner
: NULL
;
342 if (!try_module_get(pdata
->phy_module
)) {
343 dev_err(pdata
->dev
, "try_module_get failed\n");
349 pdata
->mdio_mmd
= MDIO_MMD_PCS
;
351 pdata
->phy_link
= -1;
352 pdata
->phy_speed
= SPEED_UNKNOWN
;
353 pdata
->phy_tx_pause
= pdata
->tx_pause
;
354 pdata
->phy_rx_pause
= pdata
->rx_pause
;
356 ret
= phy_connect_direct(netdev
, phydev
, &xgbe_adjust_link
,
359 netdev_err(netdev
, "phy_connect_direct failed\n");
363 if (!phydev
->drv
|| (phydev
->drv
->phy_id
== 0)) {
364 netdev_err(netdev
, "phy_id not valid\n");
366 goto err_phy_connect
;
368 DBGPR(" phy_connect_direct succeeded for PHY %s, link=%d\n",
369 dev_name(&phydev
->dev
), phydev
->link
);
371 phydev
->autoneg
= pdata
->default_autoneg
;
372 if (phydev
->autoneg
== AUTONEG_DISABLE
) {
373 phydev
->speed
= pdata
->default_speed
;
374 phydev
->duplex
= DUPLEX_FULL
;
376 phydev
->advertising
&= ~ADVERTISED_Autoneg
;
379 pdata
->phydev
= phydev
;
381 of_node_put(phy_node
);
385 DBGPR("<--xgbe_mdio_register\n");
390 phy_disconnect(phydev
);
393 phy_device_free(phydev
);
395 err_mdiobus_register
:
396 mdiobus_unregister(mii
);
402 of_node_put(phy_node
);
407 void xgbe_mdio_unregister(struct xgbe_prv_data
*pdata
)
409 DBGPR("-->xgbe_mdio_unregister\n");
411 phy_disconnect(pdata
->phydev
);
412 pdata
->phydev
= NULL
;
414 module_put(pdata
->phy_module
);
415 pdata
->phy_module
= NULL
;
417 mdiobus_unregister(pdata
->mii
);
418 pdata
->mii
->priv
= NULL
;
420 mdiobus_free(pdata
->mii
);
423 DBGPR("<--xgbe_mdio_unregister\n");