1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/platform_device.h>
22#include <linux/module.h>
23#include <linux/io.h>
24#include <linux/of.h>
25#include <linux/of_net.h>
26#include <linux/of_device.h>
27#include <linux/of_mdio.h>
28
29#include "stmmac.h"
30#include "stmmac_platform.h"
31
32#ifdef CONFIG_OF
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47static int dwmac1000_validate_mcast_bins(struct device *dev, int mcast_bins)
48{
49 int x = mcast_bins;
50
51 switch (x) {
52 case HASH_TABLE_SIZE:
53 case 128:
54 case 256:
55 break;
56 default:
57 x = 0;
58 dev_info(dev, "Hash table entries set to unexpected value %d\n",
59 mcast_bins);
60 break;
61 }
62 return x;
63}
64
65
66
67
68
69
70
71
72
73
74
75
76
77static int dwmac1000_validate_ucast_entries(struct device *dev,
78 int ucast_entries)
79{
80 int x = ucast_entries;
81
82 switch (x) {
83 case 1 ... 32:
84 case 64:
85 case 128:
86 break;
87 default:
88 x = 1;
89 dev_info(dev, "Unicast table entries set to unexpected value %d\n",
90 ucast_entries);
91 break;
92 }
93 return x;
94}
95
96
97
98
99
100
101
102
103static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev)
104{
105 struct device_node *np;
106 struct stmmac_axi *axi;
107
108 np = of_parse_phandle(pdev->dev.of_node, "snps,axi-config", 0);
109 if (!np)
110 return NULL;
111
112 axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL);
113 if (!axi) {
114 of_node_put(np);
115 return ERR_PTR(-ENOMEM);
116 }
117
118 axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en");
119 axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm");
120 axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe");
121 axi->axi_fb = of_property_read_bool(np, "snps,axi_fb");
122 axi->axi_mb = of_property_read_bool(np, "snps,axi_mb");
123 axi->axi_rb = of_property_read_bool(np, "snps,axi_rb");
124
125 if (of_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt))
126 axi->axi_wr_osr_lmt = 1;
127 if (of_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt))
128 axi->axi_rd_osr_lmt = 1;
129 of_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN);
130 of_node_put(np);
131
132 return axi;
133}
134
135
136
137
138
139static int stmmac_mtl_setup(struct platform_device *pdev,
140 struct plat_stmmacenet_data *plat)
141{
142 struct device_node *q_node;
143 struct device_node *rx_node;
144 struct device_node *tx_node;
145 u8 queue = 0;
146 int ret = 0;
147
148
149
150
151
152 plat->rx_queues_to_use = 1;
153 plat->tx_queues_to_use = 1;
154
155
156
157
158
159 plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
160 plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
161
162 rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0);
163 if (!rx_node)
164 return ret;
165
166 tx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-tx-config", 0);
167 if (!tx_node) {
168 of_node_put(rx_node);
169 return ret;
170 }
171
172
173 if (of_property_read_u32(rx_node, "snps,rx-queues-to-use",
174 &plat->rx_queues_to_use))
175 plat->rx_queues_to_use = 1;
176
177 if (of_property_read_bool(rx_node, "snps,rx-sched-sp"))
178 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
179 else if (of_property_read_bool(rx_node, "snps,rx-sched-wsp"))
180 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_WSP;
181 else
182 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
183
184
185 for_each_child_of_node(rx_node, q_node) {
186 if (queue >= plat->rx_queues_to_use)
187 break;
188
189 if (of_property_read_bool(q_node, "snps,dcb-algorithm"))
190 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
191 else if (of_property_read_bool(q_node, "snps,avb-algorithm"))
192 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
193 else
194 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
195
196 if (of_property_read_u32(q_node, "snps,map-to-dma-channel",
197 &plat->rx_queues_cfg[queue].chan))
198 plat->rx_queues_cfg[queue].chan = queue;
199
200
201 if (of_property_read_u32(q_node, "snps,priority",
202 &plat->rx_queues_cfg[queue].prio)) {
203 plat->rx_queues_cfg[queue].prio = 0;
204 plat->rx_queues_cfg[queue].use_prio = false;
205 } else {
206 plat->rx_queues_cfg[queue].use_prio = true;
207 }
208
209
210 if (of_property_read_bool(q_node, "snps,route-avcp"))
211 plat->rx_queues_cfg[queue].pkt_route = PACKET_AVCPQ;
212 else if (of_property_read_bool(q_node, "snps,route-ptp"))
213 plat->rx_queues_cfg[queue].pkt_route = PACKET_PTPQ;
214 else if (of_property_read_bool(q_node, "snps,route-dcbcp"))
215 plat->rx_queues_cfg[queue].pkt_route = PACKET_DCBCPQ;
216 else if (of_property_read_bool(q_node, "snps,route-up"))
217 plat->rx_queues_cfg[queue].pkt_route = PACKET_UPQ;
218 else if (of_property_read_bool(q_node, "snps,route-multi-broad"))
219 plat->rx_queues_cfg[queue].pkt_route = PACKET_MCBCQ;
220 else
221 plat->rx_queues_cfg[queue].pkt_route = 0x0;
222
223 queue++;
224 }
225 if (queue != plat->rx_queues_to_use) {
226 ret = -EINVAL;
227 dev_err(&pdev->dev, "Not all RX queues were configured\n");
228 goto out;
229 }
230
231
232 if (of_property_read_u32(tx_node, "snps,tx-queues-to-use",
233 &plat->tx_queues_to_use))
234 plat->tx_queues_to_use = 1;
235
236 if (of_property_read_bool(tx_node, "snps,tx-sched-wrr"))
237 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR;
238 else if (of_property_read_bool(tx_node, "snps,tx-sched-wfq"))
239 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WFQ;
240 else if (of_property_read_bool(tx_node, "snps,tx-sched-dwrr"))
241 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_DWRR;
242 else if (of_property_read_bool(tx_node, "snps,tx-sched-sp"))
243 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
244 else
245 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
246
247 queue = 0;
248
249
250 for_each_child_of_node(tx_node, q_node) {
251 if (queue >= plat->tx_queues_to_use)
252 break;
253
254 if (of_property_read_u32(q_node, "snps,weight",
255 &plat->tx_queues_cfg[queue].weight))
256 plat->tx_queues_cfg[queue].weight = 0x10 + queue;
257
258 if (of_property_read_bool(q_node, "snps,dcb-algorithm")) {
259 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
260 } else if (of_property_read_bool(q_node,
261 "snps,avb-algorithm")) {
262 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
263
264
265 if (of_property_read_u32(q_node, "snps,send_slope",
266 &plat->tx_queues_cfg[queue].send_slope))
267 plat->tx_queues_cfg[queue].send_slope = 0x0;
268 if (of_property_read_u32(q_node, "snps,idle_slope",
269 &plat->tx_queues_cfg[queue].idle_slope))
270 plat->tx_queues_cfg[queue].idle_slope = 0x0;
271 if (of_property_read_u32(q_node, "snps,high_credit",
272 &plat->tx_queues_cfg[queue].high_credit))
273 plat->tx_queues_cfg[queue].high_credit = 0x0;
274 if (of_property_read_u32(q_node, "snps,low_credit",
275 &plat->tx_queues_cfg[queue].low_credit))
276 plat->tx_queues_cfg[queue].low_credit = 0x0;
277 } else {
278 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
279 }
280
281 if (of_property_read_u32(q_node, "snps,priority",
282 &plat->tx_queues_cfg[queue].prio)) {
283 plat->tx_queues_cfg[queue].prio = 0;
284 plat->tx_queues_cfg[queue].use_prio = false;
285 } else {
286 plat->tx_queues_cfg[queue].use_prio = true;
287 }
288
289 queue++;
290 }
291 if (queue != plat->tx_queues_to_use) {
292 ret = -EINVAL;
293 dev_err(&pdev->dev, "Not all TX queues were configured\n");
294 goto out;
295 }
296
297out:
298 of_node_put(rx_node);
299 of_node_put(tx_node);
300 of_node_put(q_node);
301
302 return ret;
303}
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
331 struct device_node *np, struct device *dev)
332{
333 bool mdio = !of_phy_is_fixed_link(np);
334 static const struct of_device_id need_mdio_ids[] = {
335 { .compatible = "snps,dwc-qos-ethernet-4.10" },
336 {},
337 };
338
339 if (of_match_node(need_mdio_ids, np)) {
340 plat->mdio_node = of_get_child_by_name(np, "mdio");
341 } else {
342
343
344
345
346 for_each_child_of_node(np, plat->mdio_node) {
347 if (of_device_is_compatible(plat->mdio_node,
348 "snps,dwmac-mdio"))
349 break;
350 }
351 }
352
353 if (plat->mdio_node) {
354 dev_dbg(dev, "Found MDIO subnode\n");
355 mdio = true;
356 }
357
358 if (mdio) {
359 plat->mdio_bus_data =
360 devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data),
361 GFP_KERNEL);
362 if (!plat->mdio_bus_data)
363 return -ENOMEM;
364
365 plat->mdio_bus_data->needs_reset = true;
366 }
367
368 return 0;
369}
370
371
372
373
374
375
376
377
378
379
380static int stmmac_of_get_mac_mode(struct device_node *np)
381{
382 const char *pm;
383 int err, i;
384
385 err = of_property_read_string(np, "mac-mode", &pm);
386 if (err < 0)
387 return err;
388
389 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
390 if (!strcasecmp(pm, phy_modes(i)))
391 return i;
392 }
393
394 return -ENODEV;
395}
396
397
398
399
400
401
402
403
404
405struct plat_stmmacenet_data *
406stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
407{
408 struct device_node *np = pdev->dev.of_node;
409 struct plat_stmmacenet_data *plat;
410 struct stmmac_dma_cfg *dma_cfg;
411 int rc;
412
413 plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
414 if (!plat)
415 return ERR_PTR(-ENOMEM);
416
417 rc = of_get_mac_address(np, mac);
418 if (rc) {
419 if (rc == -EPROBE_DEFER)
420 return ERR_PTR(rc);
421
422 eth_zero_addr(mac);
423 }
424
425 plat->phy_interface = device_get_phy_mode(&pdev->dev);
426 if (plat->phy_interface < 0)
427 return ERR_PTR(plat->phy_interface);
428
429 plat->interface = stmmac_of_get_mac_mode(np);
430 if (plat->interface < 0)
431 plat->interface = plat->phy_interface;
432
433
434
435 plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
436
437
438 plat->phylink_node = np;
439
440
441 if (of_property_read_u32(np, "max-speed", &plat->max_speed))
442 plat->max_speed = -1;
443
444 plat->bus_id = of_alias_get_id(np, "ethernet");
445 if (plat->bus_id < 0)
446 plat->bus_id = 0;
447
448
449 plat->phy_addr = -1;
450
451
452
453
454 plat->clk_csr = -1;
455 of_property_read_u32(np, "clk_csr", &plat->clk_csr);
456
457
458
459
460 if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
461 dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
462
463
464 rc = stmmac_dt_phy(plat, np, &pdev->dev);
465 if (rc)
466 return ERR_PTR(rc);
467
468 of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
469
470 of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
471
472 plat->force_sf_dma_mode =
473 of_property_read_bool(np, "snps,force_sf_dma_mode");
474
475 plat->en_tx_lpi_clockgating =
476 of_property_read_bool(np, "snps,en-tx-lpi-clockgating");
477
478
479
480
481 plat->maxmtu = JUMBO_LEN;
482
483
484 plat->multicast_filter_bins = HASH_TABLE_SIZE;
485
486
487 plat->unicast_filter_entries = 1;
488
489
490
491
492
493
494 if (of_device_is_compatible(np, "st,spear600-gmac") ||
495 of_device_is_compatible(np, "snps,dwmac-3.50a") ||
496 of_device_is_compatible(np, "snps,dwmac-3.70a") ||
497 of_device_is_compatible(np, "snps,dwmac")) {
498
499
500
501
502
503
504
505 of_property_read_u32(np, "max-frame-size", &plat->maxmtu);
506 of_property_read_u32(np, "snps,multicast-filter-bins",
507 &plat->multicast_filter_bins);
508 of_property_read_u32(np, "snps,perfect-filter-entries",
509 &plat->unicast_filter_entries);
510 plat->unicast_filter_entries = dwmac1000_validate_ucast_entries(
511 &pdev->dev, plat->unicast_filter_entries);
512 plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
513 &pdev->dev, plat->multicast_filter_bins);
514 plat->has_gmac = 1;
515 plat->pmt = 1;
516 }
517
518 if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
519 of_device_is_compatible(np, "snps,dwmac-4.10a") ||
520 of_device_is_compatible(np, "snps,dwmac-4.20a")) {
521 plat->has_gmac4 = 1;
522 plat->has_gmac = 0;
523 plat->pmt = 1;
524 plat->tso_en = of_property_read_bool(np, "snps,tso");
525 }
526
527 if (of_device_is_compatible(np, "snps,dwmac-3.610") ||
528 of_device_is_compatible(np, "snps,dwmac-3.710")) {
529 plat->enh_desc = 1;
530 plat->bugged_jumbo = 1;
531 plat->force_sf_dma_mode = 1;
532 }
533
534 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
535 GFP_KERNEL);
536 if (!dma_cfg) {
537 stmmac_remove_config_dt(pdev, plat);
538 return ERR_PTR(-ENOMEM);
539 }
540 plat->dma_cfg = dma_cfg;
541
542 of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
543 if (!dma_cfg->pbl)
544 dma_cfg->pbl = DEFAULT_DMA_PBL;
545 of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
546 of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
547 dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8");
548
549 dma_cfg->aal = of_property_read_bool(np, "snps,aal");
550 dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst");
551 dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst");
552
553 plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
554 if (plat->force_thresh_dma_mode) {
555 plat->force_sf_dma_mode = 0;
556 dev_warn(&pdev->dev,
557 "force_sf_dma_mode is ignored if force_thresh_dma_mode is set.\n");
558 }
559
560 of_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
561
562 plat->axi = stmmac_axi_setup(pdev);
563
564 rc = stmmac_mtl_setup(pdev, plat);
565 if (rc) {
566 stmmac_remove_config_dt(pdev, plat);
567 return ERR_PTR(rc);
568 }
569
570
571 if (!of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) {
572 plat->stmmac_clk = devm_clk_get(&pdev->dev,
573 STMMAC_RESOURCE_NAME);
574 if (IS_ERR(plat->stmmac_clk)) {
575 dev_warn(&pdev->dev, "Cannot get CSR clock\n");
576 plat->stmmac_clk = NULL;
577 }
578 clk_prepare_enable(plat->stmmac_clk);
579 }
580
581 plat->pclk = devm_clk_get(&pdev->dev, "pclk");
582 if (IS_ERR(plat->pclk)) {
583 if (PTR_ERR(plat->pclk) == -EPROBE_DEFER)
584 goto error_pclk_get;
585
586 plat->pclk = NULL;
587 }
588 clk_prepare_enable(plat->pclk);
589
590
591 plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "ptp_ref");
592 if (IS_ERR(plat->clk_ptp_ref)) {
593 plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk);
594 plat->clk_ptp_ref = NULL;
595 dev_info(&pdev->dev, "PTP uses main clock\n");
596 } else {
597 plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref);
598 dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate);
599 }
600
601 plat->stmmac_rst = devm_reset_control_get(&pdev->dev,
602 STMMAC_RESOURCE_NAME);
603 if (IS_ERR(plat->stmmac_rst)) {
604 if (PTR_ERR(plat->stmmac_rst) == -EPROBE_DEFER)
605 goto error_hw_init;
606
607 dev_info(&pdev->dev, "no reset control found\n");
608 plat->stmmac_rst = NULL;
609 }
610
611 return plat;
612
613error_hw_init:
614 clk_disable_unprepare(plat->pclk);
615error_pclk_get:
616 clk_disable_unprepare(plat->stmmac_clk);
617
618 return ERR_PTR(-EPROBE_DEFER);
619}
620
621
622
623
624
625
626
627
628void stmmac_remove_config_dt(struct platform_device *pdev,
629 struct plat_stmmacenet_data *plat)
630{
631 of_node_put(plat->phy_node);
632 of_node_put(plat->mdio_node);
633}
634#else
635struct plat_stmmacenet_data *
636stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
637{
638 return ERR_PTR(-EINVAL);
639}
640
641void stmmac_remove_config_dt(struct platform_device *pdev,
642 struct plat_stmmacenet_data *plat)
643{
644}
645#endif
646EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
647EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
648
649int stmmac_get_platform_resources(struct platform_device *pdev,
650 struct stmmac_resources *stmmac_res)
651{
652 memset(stmmac_res, 0, sizeof(*stmmac_res));
653
654
655
656
657 stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
658 if (stmmac_res->irq < 0) {
659 if (stmmac_res->irq != -EPROBE_DEFER) {
660 dev_err(&pdev->dev,
661 "MAC IRQ configuration information not found\n");
662 }
663 return stmmac_res->irq;
664 }
665
666
667
668
669
670
671
672
673 stmmac_res->wol_irq =
674 platform_get_irq_byname_optional(pdev, "eth_wake_irq");
675 if (stmmac_res->wol_irq < 0) {
676 if (stmmac_res->wol_irq == -EPROBE_DEFER)
677 return -EPROBE_DEFER;
678 dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n");
679 stmmac_res->wol_irq = stmmac_res->irq;
680 }
681
682 stmmac_res->lpi_irq =
683 platform_get_irq_byname_optional(pdev, "eth_lpi");
684 if (stmmac_res->lpi_irq < 0) {
685 if (stmmac_res->lpi_irq == -EPROBE_DEFER)
686 return -EPROBE_DEFER;
687 dev_info(&pdev->dev, "IRQ eth_lpi not found\n");
688 }
689
690 stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0);
691
692 return PTR_ERR_OR_ZERO(stmmac_res->addr);
693}
694EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
695
696
697
698
699
700
701
702int stmmac_pltfr_remove(struct platform_device *pdev)
703{
704 struct net_device *ndev = platform_get_drvdata(pdev);
705 struct stmmac_priv *priv = netdev_priv(ndev);
706 struct plat_stmmacenet_data *plat = priv->plat;
707 int ret = stmmac_dvr_remove(&pdev->dev);
708
709 if (plat->exit)
710 plat->exit(pdev, plat->bsp_priv);
711
712 stmmac_remove_config_dt(pdev, plat);
713
714 return ret;
715}
716EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
717
718
719
720
721
722
723
724
725static int __maybe_unused stmmac_pltfr_suspend(struct device *dev)
726{
727 int ret;
728 struct net_device *ndev = dev_get_drvdata(dev);
729 struct stmmac_priv *priv = netdev_priv(ndev);
730 struct platform_device *pdev = to_platform_device(dev);
731
732 ret = stmmac_suspend(dev);
733 if (priv->plat->exit)
734 priv->plat->exit(pdev, priv->plat->bsp_priv);
735
736 return ret;
737}
738
739
740
741
742
743
744
745
746static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
747{
748 struct net_device *ndev = dev_get_drvdata(dev);
749 struct stmmac_priv *priv = netdev_priv(ndev);
750 struct platform_device *pdev = to_platform_device(dev);
751
752 if (priv->plat->init)
753 priv->plat->init(pdev, priv->plat->bsp_priv);
754
755 return stmmac_resume(dev);
756}
757
758static int __maybe_unused stmmac_runtime_suspend(struct device *dev)
759{
760 struct net_device *ndev = dev_get_drvdata(dev);
761 struct stmmac_priv *priv = netdev_priv(ndev);
762
763 stmmac_bus_clks_config(priv, false);
764
765 return 0;
766}
767
768static int __maybe_unused stmmac_runtime_resume(struct device *dev)
769{
770 struct net_device *ndev = dev_get_drvdata(dev);
771 struct stmmac_priv *priv = netdev_priv(ndev);
772
773 return stmmac_bus_clks_config(priv, true);
774}
775
776const struct dev_pm_ops stmmac_pltfr_pm_ops = {
777 SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
778 SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
779};
780EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
781
782MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
783MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
784MODULE_LICENSE("GPL");
785