net: fman: Use physical address for userspace interfaces
[platform/kernel/linux-starfive.git] / drivers / net / ethernet / freescale / fman / mac.c
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
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
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  */
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  */
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
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(&eth_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(&eth_lock);
254
255         return pdev;
256
257 err:
258         platform_device_put(pdev);
259 no_mem:
260         mutex_unlock(&eth_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
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, &params);
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
490 static struct platform_driver mac_driver = {
491         .driver = {
492                 .name           = KBUILD_MODNAME,
493                 .of_match_table = mac_match,
494         },
495         .probe          = mac_probe,
496 };
497
498 builtin_platform_driver(mac_driver);