0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/platform_device.h>
0012 #include <linux/pm_runtime.h>
0013 #include <linux/module.h>
0014 #include <linux/io.h>
0015 #include <linux/of.h>
0016 #include <linux/of_net.h>
0017 #include <linux/of_device.h>
0018 #include <linux/of_mdio.h>
0019
0020 #include "stmmac.h"
0021 #include "stmmac_platform.h"
0022
0023 #ifdef CONFIG_OF
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 static int dwmac1000_validate_mcast_bins(struct device *dev, int mcast_bins)
0039 {
0040 int x = mcast_bins;
0041
0042 switch (x) {
0043 case HASH_TABLE_SIZE:
0044 case 128:
0045 case 256:
0046 break;
0047 default:
0048 x = 0;
0049 dev_info(dev, "Hash table entries set to unexpected value %d\n",
0050 mcast_bins);
0051 break;
0052 }
0053 return x;
0054 }
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 static int dwmac1000_validate_ucast_entries(struct device *dev,
0069 int ucast_entries)
0070 {
0071 int x = ucast_entries;
0072
0073 switch (x) {
0074 case 1 ... 32:
0075 case 64:
0076 case 128:
0077 break;
0078 default:
0079 x = 1;
0080 dev_info(dev, "Unicast table entries set to unexpected value %d\n",
0081 ucast_entries);
0082 break;
0083 }
0084 return x;
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094 static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev)
0095 {
0096 struct device_node *np;
0097 struct stmmac_axi *axi;
0098
0099 np = of_parse_phandle(pdev->dev.of_node, "snps,axi-config", 0);
0100 if (!np)
0101 return NULL;
0102
0103 axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL);
0104 if (!axi) {
0105 of_node_put(np);
0106 return ERR_PTR(-ENOMEM);
0107 }
0108
0109 axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en");
0110 axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm");
0111 axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe");
0112 axi->axi_fb = of_property_read_bool(np, "snps,axi_fb");
0113 axi->axi_mb = of_property_read_bool(np, "snps,axi_mb");
0114 axi->axi_rb = of_property_read_bool(np, "snps,axi_rb");
0115
0116 if (of_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt))
0117 axi->axi_wr_osr_lmt = 1;
0118 if (of_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt))
0119 axi->axi_rd_osr_lmt = 1;
0120 of_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN);
0121 of_node_put(np);
0122
0123 return axi;
0124 }
0125
0126
0127
0128
0129
0130
0131 static int stmmac_mtl_setup(struct platform_device *pdev,
0132 struct plat_stmmacenet_data *plat)
0133 {
0134 struct device_node *q_node;
0135 struct device_node *rx_node;
0136 struct device_node *tx_node;
0137 u8 queue = 0;
0138 int ret = 0;
0139
0140
0141
0142
0143
0144 plat->rx_queues_to_use = 1;
0145 plat->tx_queues_to_use = 1;
0146
0147
0148
0149
0150
0151 plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
0152 plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
0153
0154 rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0);
0155 if (!rx_node)
0156 return ret;
0157
0158 tx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-tx-config", 0);
0159 if (!tx_node) {
0160 of_node_put(rx_node);
0161 return ret;
0162 }
0163
0164
0165 if (of_property_read_u32(rx_node, "snps,rx-queues-to-use",
0166 &plat->rx_queues_to_use))
0167 plat->rx_queues_to_use = 1;
0168
0169 if (of_property_read_bool(rx_node, "snps,rx-sched-sp"))
0170 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
0171 else if (of_property_read_bool(rx_node, "snps,rx-sched-wsp"))
0172 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_WSP;
0173 else
0174 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
0175
0176
0177 for_each_child_of_node(rx_node, q_node) {
0178 if (queue >= plat->rx_queues_to_use)
0179 break;
0180
0181 if (of_property_read_bool(q_node, "snps,dcb-algorithm"))
0182 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
0183 else if (of_property_read_bool(q_node, "snps,avb-algorithm"))
0184 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
0185 else
0186 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
0187
0188 if (of_property_read_u32(q_node, "snps,map-to-dma-channel",
0189 &plat->rx_queues_cfg[queue].chan))
0190 plat->rx_queues_cfg[queue].chan = queue;
0191
0192
0193 if (of_property_read_u32(q_node, "snps,priority",
0194 &plat->rx_queues_cfg[queue].prio)) {
0195 plat->rx_queues_cfg[queue].prio = 0;
0196 plat->rx_queues_cfg[queue].use_prio = false;
0197 } else {
0198 plat->rx_queues_cfg[queue].use_prio = true;
0199 }
0200
0201
0202 if (of_property_read_bool(q_node, "snps,route-avcp"))
0203 plat->rx_queues_cfg[queue].pkt_route = PACKET_AVCPQ;
0204 else if (of_property_read_bool(q_node, "snps,route-ptp"))
0205 plat->rx_queues_cfg[queue].pkt_route = PACKET_PTPQ;
0206 else if (of_property_read_bool(q_node, "snps,route-dcbcp"))
0207 plat->rx_queues_cfg[queue].pkt_route = PACKET_DCBCPQ;
0208 else if (of_property_read_bool(q_node, "snps,route-up"))
0209 plat->rx_queues_cfg[queue].pkt_route = PACKET_UPQ;
0210 else if (of_property_read_bool(q_node, "snps,route-multi-broad"))
0211 plat->rx_queues_cfg[queue].pkt_route = PACKET_MCBCQ;
0212 else
0213 plat->rx_queues_cfg[queue].pkt_route = 0x0;
0214
0215 queue++;
0216 }
0217 if (queue != plat->rx_queues_to_use) {
0218 ret = -EINVAL;
0219 dev_err(&pdev->dev, "Not all RX queues were configured\n");
0220 goto out;
0221 }
0222
0223
0224 if (of_property_read_u32(tx_node, "snps,tx-queues-to-use",
0225 &plat->tx_queues_to_use))
0226 plat->tx_queues_to_use = 1;
0227
0228 if (of_property_read_bool(tx_node, "snps,tx-sched-wrr"))
0229 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR;
0230 else if (of_property_read_bool(tx_node, "snps,tx-sched-wfq"))
0231 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WFQ;
0232 else if (of_property_read_bool(tx_node, "snps,tx-sched-dwrr"))
0233 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_DWRR;
0234 else
0235 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP;
0236
0237 queue = 0;
0238
0239
0240 for_each_child_of_node(tx_node, q_node) {
0241 if (queue >= plat->tx_queues_to_use)
0242 break;
0243
0244 if (of_property_read_u32(q_node, "snps,weight",
0245 &plat->tx_queues_cfg[queue].weight))
0246 plat->tx_queues_cfg[queue].weight = 0x10 + queue;
0247
0248 if (of_property_read_bool(q_node, "snps,dcb-algorithm")) {
0249 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
0250 } else if (of_property_read_bool(q_node,
0251 "snps,avb-algorithm")) {
0252 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
0253
0254
0255 if (of_property_read_u32(q_node, "snps,send_slope",
0256 &plat->tx_queues_cfg[queue].send_slope))
0257 plat->tx_queues_cfg[queue].send_slope = 0x0;
0258 if (of_property_read_u32(q_node, "snps,idle_slope",
0259 &plat->tx_queues_cfg[queue].idle_slope))
0260 plat->tx_queues_cfg[queue].idle_slope = 0x0;
0261 if (of_property_read_u32(q_node, "snps,high_credit",
0262 &plat->tx_queues_cfg[queue].high_credit))
0263 plat->tx_queues_cfg[queue].high_credit = 0x0;
0264 if (of_property_read_u32(q_node, "snps,low_credit",
0265 &plat->tx_queues_cfg[queue].low_credit))
0266 plat->tx_queues_cfg[queue].low_credit = 0x0;
0267 } else {
0268 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
0269 }
0270
0271 if (of_property_read_u32(q_node, "snps,priority",
0272 &plat->tx_queues_cfg[queue].prio)) {
0273 plat->tx_queues_cfg[queue].prio = 0;
0274 plat->tx_queues_cfg[queue].use_prio = false;
0275 } else {
0276 plat->tx_queues_cfg[queue].use_prio = true;
0277 }
0278
0279 queue++;
0280 }
0281 if (queue != plat->tx_queues_to_use) {
0282 ret = -EINVAL;
0283 dev_err(&pdev->dev, "Not all TX queues were configured\n");
0284 goto out;
0285 }
0286
0287 out:
0288 of_node_put(rx_node);
0289 of_node_put(tx_node);
0290 of_node_put(q_node);
0291
0292 return ret;
0293 }
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320 static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
0321 struct device_node *np, struct device *dev)
0322 {
0323 bool mdio = !of_phy_is_fixed_link(np);
0324 static const struct of_device_id need_mdio_ids[] = {
0325 { .compatible = "snps,dwc-qos-ethernet-4.10" },
0326 {},
0327 };
0328
0329 if (of_match_node(need_mdio_ids, np)) {
0330 plat->mdio_node = of_get_child_by_name(np, "mdio");
0331 } else {
0332
0333
0334
0335
0336 for_each_child_of_node(np, plat->mdio_node) {
0337 if (of_device_is_compatible(plat->mdio_node,
0338 "snps,dwmac-mdio"))
0339 break;
0340 }
0341 }
0342
0343 if (plat->mdio_node) {
0344 dev_dbg(dev, "Found MDIO subnode\n");
0345 mdio = true;
0346 }
0347
0348 if (mdio) {
0349 plat->mdio_bus_data =
0350 devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data),
0351 GFP_KERNEL);
0352 if (!plat->mdio_bus_data)
0353 return -ENOMEM;
0354
0355 plat->mdio_bus_data->needs_reset = true;
0356 }
0357
0358 return 0;
0359 }
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370 static int stmmac_of_get_mac_mode(struct device_node *np)
0371 {
0372 const char *pm;
0373 int err, i;
0374
0375 err = of_property_read_string(np, "mac-mode", &pm);
0376 if (err < 0)
0377 return err;
0378
0379 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) {
0380 if (!strcasecmp(pm, phy_modes(i)))
0381 return i;
0382 }
0383
0384 return -ENODEV;
0385 }
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395 struct plat_stmmacenet_data *
0396 stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
0397 {
0398 struct device_node *np = pdev->dev.of_node;
0399 struct plat_stmmacenet_data *plat;
0400 struct stmmac_dma_cfg *dma_cfg;
0401 int phy_mode;
0402 void *ret;
0403 int rc;
0404
0405 plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
0406 if (!plat)
0407 return ERR_PTR(-ENOMEM);
0408
0409 rc = of_get_mac_address(np, mac);
0410 if (rc) {
0411 if (rc == -EPROBE_DEFER)
0412 return ERR_PTR(rc);
0413
0414 eth_zero_addr(mac);
0415 }
0416
0417 phy_mode = device_get_phy_mode(&pdev->dev);
0418 if (phy_mode < 0)
0419 return ERR_PTR(phy_mode);
0420
0421 plat->phy_interface = phy_mode;
0422 plat->interface = stmmac_of_get_mac_mode(np);
0423 if (plat->interface < 0)
0424 plat->interface = plat->phy_interface;
0425
0426
0427
0428 plat->phy_node = of_parse_phandle(np, "phy-handle", 0);
0429
0430
0431 plat->phylink_node = np;
0432
0433
0434 of_property_read_u32(np, "max-speed", &plat->max_speed);
0435
0436 plat->bus_id = of_alias_get_id(np, "ethernet");
0437 if (plat->bus_id < 0)
0438 plat->bus_id = 0;
0439
0440
0441 plat->phy_addr = -1;
0442
0443
0444
0445
0446 plat->clk_csr = -1;
0447 of_property_read_u32(np, "clk_csr", &plat->clk_csr);
0448
0449
0450
0451
0452 if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
0453 dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
0454
0455
0456 rc = stmmac_dt_phy(plat, np, &pdev->dev);
0457 if (rc)
0458 return ERR_PTR(rc);
0459
0460 of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
0461
0462 of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size);
0463
0464 plat->force_sf_dma_mode =
0465 of_property_read_bool(np, "snps,force_sf_dma_mode");
0466
0467 plat->en_tx_lpi_clockgating =
0468 of_property_read_bool(np, "snps,en-tx-lpi-clockgating");
0469
0470
0471
0472
0473 plat->maxmtu = JUMBO_LEN;
0474
0475
0476 plat->multicast_filter_bins = HASH_TABLE_SIZE;
0477
0478
0479 plat->unicast_filter_entries = 1;
0480
0481
0482
0483
0484
0485
0486 if (of_device_is_compatible(np, "st,spear600-gmac") ||
0487 of_device_is_compatible(np, "snps,dwmac-3.50a") ||
0488 of_device_is_compatible(np, "snps,dwmac-3.70a") ||
0489 of_device_is_compatible(np, "snps,dwmac")) {
0490
0491
0492
0493
0494
0495
0496
0497 of_property_read_u32(np, "max-frame-size", &plat->maxmtu);
0498 of_property_read_u32(np, "snps,multicast-filter-bins",
0499 &plat->multicast_filter_bins);
0500 of_property_read_u32(np, "snps,perfect-filter-entries",
0501 &plat->unicast_filter_entries);
0502 plat->unicast_filter_entries = dwmac1000_validate_ucast_entries(
0503 &pdev->dev, plat->unicast_filter_entries);
0504 plat->multicast_filter_bins = dwmac1000_validate_mcast_bins(
0505 &pdev->dev, plat->multicast_filter_bins);
0506 plat->has_gmac = 1;
0507 plat->pmt = 1;
0508 }
0509
0510 if (of_device_is_compatible(np, "snps,dwmac-3.40a")) {
0511 plat->has_gmac = 1;
0512 plat->enh_desc = 1;
0513 plat->tx_coe = 1;
0514 plat->bugged_jumbo = 1;
0515 plat->pmt = 1;
0516 }
0517
0518 if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
0519 of_device_is_compatible(np, "snps,dwmac-4.10a") ||
0520 of_device_is_compatible(np, "snps,dwmac-4.20a") ||
0521 of_device_is_compatible(np, "snps,dwmac-5.10a")) {
0522 plat->has_gmac4 = 1;
0523 plat->has_gmac = 0;
0524 plat->pmt = 1;
0525 plat->tso_en = of_property_read_bool(np, "snps,tso");
0526 }
0527
0528 if (of_device_is_compatible(np, "snps,dwmac-3.610") ||
0529 of_device_is_compatible(np, "snps,dwmac-3.710")) {
0530 plat->enh_desc = 1;
0531 plat->bugged_jumbo = 1;
0532 plat->force_sf_dma_mode = 1;
0533 }
0534
0535 if (of_device_is_compatible(np, "snps,dwxgmac")) {
0536 plat->has_xgmac = 1;
0537 plat->pmt = 1;
0538 plat->tso_en = of_property_read_bool(np, "snps,tso");
0539 }
0540
0541 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
0542 GFP_KERNEL);
0543 if (!dma_cfg) {
0544 stmmac_remove_config_dt(pdev, plat);
0545 return ERR_PTR(-ENOMEM);
0546 }
0547 plat->dma_cfg = dma_cfg;
0548
0549 of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
0550 if (!dma_cfg->pbl)
0551 dma_cfg->pbl = DEFAULT_DMA_PBL;
0552 of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl);
0553 of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl);
0554 dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8");
0555
0556 dma_cfg->aal = of_property_read_bool(np, "snps,aal");
0557 dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst");
0558 dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst");
0559
0560 plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
0561 if (plat->force_thresh_dma_mode) {
0562 plat->force_sf_dma_mode = 0;
0563 dev_warn(&pdev->dev,
0564 "force_sf_dma_mode is ignored if force_thresh_dma_mode is set.\n");
0565 }
0566
0567 of_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed);
0568
0569 plat->axi = stmmac_axi_setup(pdev);
0570
0571 rc = stmmac_mtl_setup(pdev, plat);
0572 if (rc) {
0573 stmmac_remove_config_dt(pdev, plat);
0574 return ERR_PTR(rc);
0575 }
0576
0577
0578 if (!of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) {
0579 plat->stmmac_clk = devm_clk_get(&pdev->dev,
0580 STMMAC_RESOURCE_NAME);
0581 if (IS_ERR(plat->stmmac_clk)) {
0582 dev_warn(&pdev->dev, "Cannot get CSR clock\n");
0583 plat->stmmac_clk = NULL;
0584 }
0585 clk_prepare_enable(plat->stmmac_clk);
0586 }
0587
0588 plat->pclk = devm_clk_get_optional(&pdev->dev, "pclk");
0589 if (IS_ERR(plat->pclk)) {
0590 ret = plat->pclk;
0591 goto error_pclk_get;
0592 }
0593 clk_prepare_enable(plat->pclk);
0594
0595
0596 plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "ptp_ref");
0597 if (IS_ERR(plat->clk_ptp_ref)) {
0598 plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk);
0599 plat->clk_ptp_ref = NULL;
0600 dev_info(&pdev->dev, "PTP uses main clock\n");
0601 } else {
0602 plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref);
0603 dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate);
0604 }
0605
0606 plat->stmmac_rst = devm_reset_control_get_optional(&pdev->dev,
0607 STMMAC_RESOURCE_NAME);
0608 if (IS_ERR(plat->stmmac_rst)) {
0609 ret = plat->stmmac_rst;
0610 goto error_hw_init;
0611 }
0612
0613 plat->stmmac_ahb_rst = devm_reset_control_get_optional_shared(
0614 &pdev->dev, "ahb");
0615 if (IS_ERR(plat->stmmac_ahb_rst)) {
0616 ret = plat->stmmac_ahb_rst;
0617 goto error_hw_init;
0618 }
0619
0620 return plat;
0621
0622 error_hw_init:
0623 clk_disable_unprepare(plat->pclk);
0624 error_pclk_get:
0625 clk_disable_unprepare(plat->stmmac_clk);
0626
0627 return ret;
0628 }
0629
0630
0631
0632
0633
0634
0635
0636
0637 void stmmac_remove_config_dt(struct platform_device *pdev,
0638 struct plat_stmmacenet_data *plat)
0639 {
0640 clk_disable_unprepare(plat->stmmac_clk);
0641 clk_disable_unprepare(plat->pclk);
0642 of_node_put(plat->phy_node);
0643 of_node_put(plat->mdio_node);
0644 }
0645 #else
0646 struct plat_stmmacenet_data *
0647 stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
0648 {
0649 return ERR_PTR(-EINVAL);
0650 }
0651
0652 void stmmac_remove_config_dt(struct platform_device *pdev,
0653 struct plat_stmmacenet_data *plat)
0654 {
0655 }
0656 #endif
0657 EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
0658 EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
0659
0660 int stmmac_get_platform_resources(struct platform_device *pdev,
0661 struct stmmac_resources *stmmac_res)
0662 {
0663 memset(stmmac_res, 0, sizeof(*stmmac_res));
0664
0665
0666
0667
0668 stmmac_res->irq = platform_get_irq_byname(pdev, "macirq");
0669 if (stmmac_res->irq < 0)
0670 return stmmac_res->irq;
0671
0672
0673
0674
0675
0676
0677
0678
0679 stmmac_res->wol_irq =
0680 platform_get_irq_byname_optional(pdev, "eth_wake_irq");
0681 if (stmmac_res->wol_irq < 0) {
0682 if (stmmac_res->wol_irq == -EPROBE_DEFER)
0683 return -EPROBE_DEFER;
0684 dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n");
0685 stmmac_res->wol_irq = stmmac_res->irq;
0686 }
0687
0688 stmmac_res->lpi_irq =
0689 platform_get_irq_byname_optional(pdev, "eth_lpi");
0690 if (stmmac_res->lpi_irq < 0) {
0691 if (stmmac_res->lpi_irq == -EPROBE_DEFER)
0692 return -EPROBE_DEFER;
0693 dev_info(&pdev->dev, "IRQ eth_lpi not found\n");
0694 }
0695
0696 stmmac_res->addr = devm_platform_ioremap_resource(pdev, 0);
0697
0698 return PTR_ERR_OR_ZERO(stmmac_res->addr);
0699 }
0700 EXPORT_SYMBOL_GPL(stmmac_get_platform_resources);
0701
0702
0703
0704
0705
0706
0707
0708 int stmmac_pltfr_remove(struct platform_device *pdev)
0709 {
0710 struct net_device *ndev = platform_get_drvdata(pdev);
0711 struct stmmac_priv *priv = netdev_priv(ndev);
0712 struct plat_stmmacenet_data *plat = priv->plat;
0713 int ret = stmmac_dvr_remove(&pdev->dev);
0714
0715 if (plat->exit)
0716 plat->exit(pdev, plat->bsp_priv);
0717
0718 stmmac_remove_config_dt(pdev, plat);
0719
0720 return ret;
0721 }
0722 EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
0723
0724
0725
0726
0727
0728
0729
0730
0731 static int __maybe_unused stmmac_pltfr_suspend(struct device *dev)
0732 {
0733 int ret;
0734 struct net_device *ndev = dev_get_drvdata(dev);
0735 struct stmmac_priv *priv = netdev_priv(ndev);
0736 struct platform_device *pdev = to_platform_device(dev);
0737
0738 ret = stmmac_suspend(dev);
0739 if (priv->plat->exit)
0740 priv->plat->exit(pdev, priv->plat->bsp_priv);
0741
0742 return ret;
0743 }
0744
0745
0746
0747
0748
0749
0750
0751
0752 static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
0753 {
0754 struct net_device *ndev = dev_get_drvdata(dev);
0755 struct stmmac_priv *priv = netdev_priv(ndev);
0756 struct platform_device *pdev = to_platform_device(dev);
0757
0758 if (priv->plat->init)
0759 priv->plat->init(pdev, priv->plat->bsp_priv);
0760
0761 return stmmac_resume(dev);
0762 }
0763
0764 static int __maybe_unused stmmac_runtime_suspend(struct device *dev)
0765 {
0766 struct net_device *ndev = dev_get_drvdata(dev);
0767 struct stmmac_priv *priv = netdev_priv(ndev);
0768
0769 stmmac_bus_clks_config(priv, false);
0770
0771 return 0;
0772 }
0773
0774 static int __maybe_unused stmmac_runtime_resume(struct device *dev)
0775 {
0776 struct net_device *ndev = dev_get_drvdata(dev);
0777 struct stmmac_priv *priv = netdev_priv(ndev);
0778
0779 return stmmac_bus_clks_config(priv, true);
0780 }
0781
0782 static int __maybe_unused stmmac_pltfr_noirq_suspend(struct device *dev)
0783 {
0784 struct net_device *ndev = dev_get_drvdata(dev);
0785 struct stmmac_priv *priv = netdev_priv(ndev);
0786 int ret;
0787
0788 if (!netif_running(ndev))
0789 return 0;
0790
0791 if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
0792
0793 clk_disable_unprepare(priv->plat->clk_ptp_ref);
0794
0795 ret = pm_runtime_force_suspend(dev);
0796 if (ret)
0797 return ret;
0798 }
0799
0800 return 0;
0801 }
0802
0803 static int __maybe_unused stmmac_pltfr_noirq_resume(struct device *dev)
0804 {
0805 struct net_device *ndev = dev_get_drvdata(dev);
0806 struct stmmac_priv *priv = netdev_priv(ndev);
0807 int ret;
0808
0809 if (!netif_running(ndev))
0810 return 0;
0811
0812 if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
0813
0814 ret = pm_runtime_force_resume(dev);
0815 if (ret)
0816 return ret;
0817
0818 ret = clk_prepare_enable(priv->plat->clk_ptp_ref);
0819 if (ret < 0) {
0820 netdev_warn(priv->dev,
0821 "failed to enable PTP reference clock: %pe\n",
0822 ERR_PTR(ret));
0823 return ret;
0824 }
0825 }
0826
0827 return 0;
0828 }
0829
0830 const struct dev_pm_ops stmmac_pltfr_pm_ops = {
0831 SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
0832 SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
0833 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_noirq_suspend, stmmac_pltfr_noirq_resume)
0834 };
0835 EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
0836
0837 MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
0838 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
0839 MODULE_LICENSE("GPL");