1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
2 /*
3 * Copyright 2008 - 2015 Freescale Semiconductor Inc.
4 */
5
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7
8 #include <linux/init.h>
9 #include <linux/module.h>
10 #include <linux/of_address.h>
11 #include <linux/of_platform.h>
12 #include <linux/of_net.h>
13 #include <linux/of_mdio.h>
14 #include <linux/device.h>
15 #include <linux/phy.h>
16 #include <linux/netdevice.h>
17 #include <linux/phy_fixed.h>
18 #include <linux/etherdevice.h>
19 #include <linux/libfdt_env.h>
20
21 #include "mac.h"
22 #include "fman_mac.h"
23 #include "fman_dtsec.h"
24 #include "fman_tgec.h"
25 #include "fman_memac.h"
26
27 MODULE_LICENSE("Dual BSD/GPL");
28 MODULE_DESCRIPTION("FSL FMan MAC API based driver");
29
30 struct mac_priv_s {
31 u8 cell_index;
32 struct fman *fman;
33 /* List of multicast addresses */
34 struct list_head mc_addr_list;
35 struct platform_device *eth_dev;
36 u16 speed;
37 };
38
39 struct mac_address {
40 u8 addr[ETH_ALEN];
41 struct list_head list;
42 };
43
mac_exception(struct mac_device * mac_dev,enum fman_mac_exceptions ex)44 static void mac_exception(struct mac_device *mac_dev,
45 enum fman_mac_exceptions ex)
46 {
47 if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) {
48 /* don't flag RX FIFO after the first */
49 mac_dev->set_exception(mac_dev->fman_mac,
50 FM_MAC_EX_10G_RX_FIFO_OVFL, false);
51 dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex);
52 }
53
54 dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
55 __func__, ex);
56 }
57
fman_set_multi(struct net_device * net_dev,struct mac_device * mac_dev)58 int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
59 {
60 struct mac_priv_s *priv;
61 struct mac_address *old_addr, *tmp;
62 struct netdev_hw_addr *ha;
63 int err;
64 enet_addr_t *addr;
65
66 priv = mac_dev->priv;
67
68 /* Clear previous address list */
69 list_for_each_entry_safe(old_addr, tmp, &priv->mc_addr_list, list) {
70 addr = (enet_addr_t *)old_addr->addr;
71 err = mac_dev->remove_hash_mac_addr(mac_dev->fman_mac, addr);
72 if (err < 0)
73 return err;
74
75 list_del(&old_addr->list);
76 kfree(old_addr);
77 }
78
79 /* Add all the addresses from the new list */
80 netdev_for_each_mc_addr(ha, net_dev) {
81 addr = (enet_addr_t *)ha->addr;
82 err = mac_dev->add_hash_mac_addr(mac_dev->fman_mac, addr);
83 if (err < 0)
84 return err;
85
86 tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
87 if (!tmp)
88 return -ENOMEM;
89
90 ether_addr_copy(tmp->addr, ha->addr);
91 list_add(&tmp->list, &priv->mc_addr_list);
92 }
93 return 0;
94 }
95
96 /**
97 * fman_set_mac_active_pause
98 * @mac_dev: A pointer to the MAC device
99 * @rx: Pause frame setting for RX
100 * @tx: Pause frame setting for TX
101 *
102 * Set the MAC RX/TX PAUSE frames settings
103 *
104 * Avoid redundant calls to FMD, if the MAC driver already contains the desired
105 * active PAUSE settings. Otherwise, the new active settings should be reflected
106 * in FMan.
107 *
108 * Return: 0 on success; Error code otherwise.
109 */
fman_set_mac_active_pause(struct mac_device * mac_dev,bool rx,bool tx)110 int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx)
111 {
112 struct fman_mac *fman_mac = mac_dev->fman_mac;
113 int err = 0;
114
115 if (rx != mac_dev->rx_pause_active) {
116 err = mac_dev->set_rx_pause(fman_mac, rx);
117 if (likely(err == 0))
118 mac_dev->rx_pause_active = rx;
119 }
120
121 if (tx != mac_dev->tx_pause_active) {
122 u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE :
123 FSL_FM_PAUSE_TIME_DISABLE);
124
125 err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0);
126
127 if (likely(err == 0))
128 mac_dev->tx_pause_active = tx;
129 }
130
131 return err;
132 }
133 EXPORT_SYMBOL(fman_set_mac_active_pause);
134
135 /**
136 * fman_get_pause_cfg
137 * @mac_dev: A pointer to the MAC device
138 * @rx_pause: Return value for RX setting
139 * @tx_pause: Return value for TX setting
140 *
141 * Determine the MAC RX/TX PAUSE frames settings based on PHY
142 * autonegotiation or values set by eththool.
143 *
144 * Return: Pointer to FMan device.
145 */
fman_get_pause_cfg(struct mac_device * mac_dev,bool * rx_pause,bool * tx_pause)146 void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
147 bool *tx_pause)
148 {
149 struct phy_device *phy_dev = mac_dev->phy_dev;
150 u16 lcl_adv, rmt_adv;
151 u8 flowctrl;
152
153 *rx_pause = *tx_pause = false;
154
155 if (!phy_dev->duplex)
156 return;
157
158 /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings
159 * are those set by ethtool.
160 */
161 if (!mac_dev->autoneg_pause) {
162 *rx_pause = mac_dev->rx_pause_req;
163 *tx_pause = mac_dev->tx_pause_req;
164 return;
165 }
166
167 /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE
168 * settings depend on the result of the link negotiation.
169 */
170
171 /* get local capabilities */
172 lcl_adv = linkmode_adv_to_lcl_adv_t(phy_dev->advertising);
173
174 /* get link partner capabilities */
175 rmt_adv = 0;
176 if (phy_dev->pause)
177 rmt_adv |= LPA_PAUSE_CAP;
178 if (phy_dev->asym_pause)
179 rmt_adv |= LPA_PAUSE_ASYM;
180
181 /* Calculate TX/RX settings based on local and peer advertised
182 * symmetric/asymmetric PAUSE capabilities.
183 */
184 flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
185 if (flowctrl & FLOW_CTRL_RX)
186 *rx_pause = true;
187 if (flowctrl & FLOW_CTRL_TX)
188 *tx_pause = true;
189 }
190 EXPORT_SYMBOL(fman_get_pause_cfg);
191
192 #define DTSEC_SUPPORTED \
193 (SUPPORTED_10baseT_Half \
194 | SUPPORTED_10baseT_Full \
195 | SUPPORTED_100baseT_Half \
196 | SUPPORTED_100baseT_Full \
197 | SUPPORTED_Autoneg \
198 | SUPPORTED_Pause \
199 | SUPPORTED_Asym_Pause \
200 | SUPPORTED_FIBRE \
201 | SUPPORTED_MII)
202
203 static DEFINE_MUTEX(eth_lock);
204
205 static const u16 phy2speed[] = {
206 [PHY_INTERFACE_MODE_MII] = SPEED_100,
207 [PHY_INTERFACE_MODE_GMII] = SPEED_1000,
208 [PHY_INTERFACE_MODE_SGMII] = SPEED_1000,
209 [PHY_INTERFACE_MODE_TBI] = SPEED_1000,
210 [PHY_INTERFACE_MODE_RMII] = SPEED_100,
211 [PHY_INTERFACE_MODE_RGMII] = SPEED_1000,
212 [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000,
213 [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000,
214 [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000,
215 [PHY_INTERFACE_MODE_RTBI] = SPEED_1000,
216 [PHY_INTERFACE_MODE_QSGMII] = SPEED_1000,
217 [PHY_INTERFACE_MODE_XGMII] = SPEED_10000
218 };
219
dpaa_eth_add_device(int fman_id,struct mac_device * mac_dev)220 static struct platform_device *dpaa_eth_add_device(int fman_id,
221 struct mac_device *mac_dev)
222 {
223 struct platform_device *pdev;
224 struct dpaa_eth_data data;
225 struct mac_priv_s *priv;
226 static int dpaa_eth_dev_cnt;
227 int ret;
228
229 priv = mac_dev->priv;
230
231 data.mac_dev = mac_dev;
232 data.mac_hw_id = priv->cell_index;
233 data.fman_hw_id = fman_id;
234
235 mutex_lock(ð_lock);
236 pdev = platform_device_alloc("dpaa-ethernet", dpaa_eth_dev_cnt);
237 if (!pdev) {
238 ret = -ENOMEM;
239 goto no_mem;
240 }
241
242 pdev->dev.parent = mac_dev->dev;
243
244 ret = platform_device_add_data(pdev, &data, sizeof(data));
245 if (ret)
246 goto err;
247
248 ret = platform_device_add(pdev);
249 if (ret)
250 goto err;
251
252 dpaa_eth_dev_cnt++;
253 mutex_unlock(ð_lock);
254
255 return pdev;
256
257 err:
258 platform_device_put(pdev);
259 no_mem:
260 mutex_unlock(ð_lock);
261
262 return ERR_PTR(ret);
263 }
264
265 static const struct of_device_id mac_match[] = {
266 { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization },
267 { .compatible = "fsl,fman-xgec", .data = tgec_initialization },
268 { .compatible = "fsl,fman-memac", .data = memac_initialization },
269 {}
270 };
271 MODULE_DEVICE_TABLE(of, mac_match);
272
mac_probe(struct platform_device * _of_dev)273 static int mac_probe(struct platform_device *_of_dev)
274 {
275 int err, i, nph;
276 int (*init)(struct mac_device *mac_dev, struct device_node *mac_node,
277 struct fman_mac_params *params);
278 struct device *dev;
279 struct device_node *mac_node, *dev_node;
280 struct mac_device *mac_dev;
281 struct platform_device *of_dev;
282 struct mac_priv_s *priv;
283 struct fman_mac_params params;
284 u32 val;
285 u8 fman_id;
286 phy_interface_t phy_if;
287
288 dev = &_of_dev->dev;
289 mac_node = dev->of_node;
290 init = of_device_get_match_data(dev);
291
292 mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
293 if (!mac_dev)
294 return -ENOMEM;
295 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
296 if (!priv)
297 return -ENOMEM;
298
299 /* Save private information */
300 mac_dev->priv = priv;
301 mac_dev->dev = dev;
302
303 INIT_LIST_HEAD(&priv->mc_addr_list);
304
305 /* Get the FM node */
306 dev_node = of_get_parent(mac_node);
307 if (!dev_node) {
308 dev_err(dev, "of_get_parent(%pOF) failed\n",
309 mac_node);
310 return -EINVAL;
311 }
312
313 of_dev = of_find_device_by_node(dev_node);
314 if (!of_dev) {
315 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", dev_node);
316 err = -EINVAL;
317 goto _return_of_node_put;
318 }
319
320 /* Get the FMan cell-index */
321 err = of_property_read_u32(dev_node, "cell-index", &val);
322 if (err) {
323 dev_err(dev, "failed to read cell-index for %pOF\n", dev_node);
324 err = -EINVAL;
325 goto _return_of_node_put;
326 }
327 /* cell-index 0 => FMan id 1 */
328 fman_id = (u8)(val + 1);
329
330 priv->fman = fman_bind(&of_dev->dev);
331 if (!priv->fman) {
332 dev_err(dev, "fman_bind(%pOF) failed\n", dev_node);
333 err = -ENODEV;
334 goto _return_of_node_put;
335 }
336
337 of_node_put(dev_node);
338
339 /* Get the address of the memory mapped registers */
340 mac_dev->res = platform_get_mem_or_io(_of_dev, 0);
341 if (!mac_dev->res) {
342 dev_err(dev, "could not get registers\n");
343 return -EINVAL;
344 }
345
346 err = devm_request_resource(dev, fman_get_mem_region(priv->fman),
347 mac_dev->res);
348 if (err) {
349 dev_err_probe(dev, err, "could not request resource\n");
350 return err;
351 }
352
353 mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start,
354 resource_size(mac_dev->res));
355 if (!mac_dev->vaddr) {
356 dev_err(dev, "devm_ioremap() failed\n");
357 return -EIO;
358 }
359
360 if (!of_device_is_available(mac_node))
361 return -ENODEV;
362
363 /* Get the cell-index */
364 err = of_property_read_u32(mac_node, "cell-index", &val);
365 if (err) {
366 dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
367 return -EINVAL;
368 }
369 priv->cell_index = (u8)val;
370
371 /* Get the MAC address */
372 err = of_get_mac_address(mac_node, mac_dev->addr);
373 if (err)
374 dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node);
375
376 /* Get the port handles */
377 nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL);
378 if (unlikely(nph < 0)) {
379 dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
380 mac_node);
381 return nph;
382 }
383
384 if (nph != ARRAY_SIZE(mac_dev->port)) {
385 dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
386 mac_node);
387 return -EINVAL;
388 }
389
390 for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
391 /* Find the port node */
392 dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i);
393 if (!dev_node) {
394 dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n",
395 mac_node);
396 return -EINVAL;
397 }
398
399 of_dev = of_find_device_by_node(dev_node);
400 if (!of_dev) {
401 dev_err(dev, "of_find_device_by_node(%pOF) failed\n",
402 dev_node);
403 err = -EINVAL;
404 goto _return_of_node_put;
405 }
406
407 mac_dev->port[i] = fman_port_bind(&of_dev->dev);
408 if (!mac_dev->port[i]) {
409 dev_err(dev, "dev_get_drvdata(%pOF) failed\n",
410 dev_node);
411 err = -EINVAL;
412 goto _return_of_node_put;
413 }
414 of_node_put(dev_node);
415 }
416
417 /* Get the PHY connection type */
418 err = of_get_phy_mode(mac_node, &phy_if);
419 if (err) {
420 dev_warn(dev,
421 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n",
422 mac_node);
423 phy_if = PHY_INTERFACE_MODE_SGMII;
424 }
425 mac_dev->phy_if = phy_if;
426
427 priv->speed = phy2speed[mac_dev->phy_if];
428 params.max_speed = priv->speed;
429 mac_dev->if_support = DTSEC_SUPPORTED;
430 /* We don't support half-duplex in SGMII mode */
431 if (mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII)
432 mac_dev->if_support &= ~(SUPPORTED_10baseT_Half |
433 SUPPORTED_100baseT_Half);
434
435 /* Gigabit support (no half-duplex) */
436 if (params.max_speed == 1000)
437 mac_dev->if_support |= SUPPORTED_1000baseT_Full;
438
439 /* The 10G interface only supports one mode */
440 if (mac_dev->phy_if == PHY_INTERFACE_MODE_XGMII)
441 mac_dev->if_support = SUPPORTED_10000baseT_Full;
442
443 /* Get the rest of the PHY information */
444 mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
445
446 params.basex_if = false;
447 params.mac_id = priv->cell_index;
448 params.fm = (void *)priv->fman;
449 params.exception_cb = mac_exception;
450 params.event_cb = mac_exception;
451
452 err = init(mac_dev, mac_node, ¶ms);
453 if (err < 0) {
454 dev_err(dev, "mac_dev->init() = %d\n", err);
455 of_node_put(mac_dev->phy_node);
456 return err;
457 }
458
459 /* pause frame autonegotiation enabled */
460 mac_dev->autoneg_pause = true;
461
462 /* By intializing the values to false, force FMD to enable PAUSE frames
463 * on RX and TX
464 */
465 mac_dev->rx_pause_req = true;
466 mac_dev->tx_pause_req = true;
467 mac_dev->rx_pause_active = false;
468 mac_dev->tx_pause_active = false;
469 err = fman_set_mac_active_pause(mac_dev, true, true);
470 if (err < 0)
471 dev_err(dev, "fman_set_mac_active_pause() = %d\n", err);
472
473 if (!is_zero_ether_addr(mac_dev->addr))
474 dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
475
476 priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev);
477 if (IS_ERR(priv->eth_dev)) {
478 dev_err(dev, "failed to add Ethernet platform device for MAC %d\n",
479 priv->cell_index);
480 priv->eth_dev = NULL;
481 }
482
483 return err;
484
485 _return_of_node_put:
486 of_node_put(dev_node);
487 return err;
488 }
489
mac_remove(struct platform_device * pdev)490 static int mac_remove(struct platform_device *pdev)
491 {
492 struct mac_device *mac_dev = platform_get_drvdata(pdev);
493
494 platform_device_unregister(mac_dev->priv->eth_dev);
495 return 0;
496 }
497
498 static struct platform_driver mac_driver = {
499 .driver = {
500 .name = KBUILD_MODNAME,
501 .of_match_table = mac_match,
502 },
503 .probe = mac_probe,
504 .remove = mac_remove,
505 };
506
507 builtin_platform_driver(mac_driver);
508