1 // SPDX-License-Identifier: GPL-2.0-only 2 /******************************************************************************* 3 This contains the functions to handle the platform driver. 4 5 Copyright (C) 2007-2011 STMicroelectronics Ltd 6 7 8 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 9 *******************************************************************************/ 10 11 #include <linux/platform_device.h> 12 #include <linux/module.h> 13 #include <linux/io.h> 14 #include <linux/of.h> 15 #include <linux/of_net.h> 16 #include <linux/of_device.h> 17 #include <linux/of_mdio.h> 18 19 #include "stmmac.h" 20 #include "stmmac_platform.h" 21 22 #ifdef CONFIG_OF 23 24 /** 25 * dwmac1000_validate_mcast_bins - validates the number of Multicast filter bins 26 * @mcast_bins: Multicast filtering bins 27 * Description: 28 * this function validates the number of Multicast filtering bins specified 29 * by the configuration through the device tree. The Synopsys GMAC supports 30 * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC 31 * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds 32 * to 7 bits, and 256 refers to 8 bits of the CRC. Any other setting is 33 * invalid and will cause the filtering algorithm to use Multicast 34 * promiscuous mode. 35 */ 36 static int dwmac1000_validate_mcast_bins(int mcast_bins) 37 { 38 int x = mcast_bins; 39 40 switch (x) { 41 case HASH_TABLE_SIZE: 42 case 128: 43 case 256: 44 break; 45 default: 46 x = 0; 47 pr_info("Hash table entries set to unexpected value %d", 48 mcast_bins); 49 break; 50 } 51 return x; 52 } 53 54 /** 55 * dwmac1000_validate_ucast_entries - validate the Unicast address entries 56 * @ucast_entries: number of Unicast address entries 57 * Description: 58 * This function validates the number of Unicast address entries supported 59 * by a particular Synopsys 10/100/1000 controller. The Synopsys controller 60 * supports 1..32, 64, or 128 Unicast filter entries for it's Unicast filter 61 * logic. This function validates a valid, supported configuration is 62 * selected, and defaults to 1 Unicast address if an unsupported 63 * configuration is selected. 64 */ 65 static int dwmac1000_validate_ucast_entries(int ucast_entries) 66 { 67 int x = ucast_entries; 68 69 switch (x) { 70 case 1 ... 32: 71 case 64: 72 case 128: 73 break; 74 default: 75 x = 1; 76 pr_info("Unicast table entries set to unexpected value %d\n", 77 ucast_entries); 78 break; 79 } 80 return x; 81 } 82 83 /** 84 * stmmac_axi_setup - parse DT parameters for programming the AXI register 85 * @pdev: platform device 86 * Description: 87 * if required, from device-tree the AXI internal register can be tuned 88 * by using platform parameters. 89 */ 90 static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev) 91 { 92 struct device_node *np; 93 struct stmmac_axi *axi; 94 95 np = of_parse_phandle(pdev->dev.of_node, "snps,axi-config", 0); 96 if (!np) 97 return NULL; 98 99 axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL); 100 if (!axi) { 101 of_node_put(np); 102 return ERR_PTR(-ENOMEM); 103 } 104 105 axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en"); 106 axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm"); 107 axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe"); 108 axi->axi_fb = of_property_read_bool(np, "snps,axi_fb"); 109 axi->axi_mb = of_property_read_bool(np, "snps,axi_mb"); 110 axi->axi_rb = of_property_read_bool(np, "snps,axi_rb"); 111 112 if (of_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt)) 113 axi->axi_wr_osr_lmt = 1; 114 if (of_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt)) 115 axi->axi_rd_osr_lmt = 1; 116 of_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN); 117 of_node_put(np); 118 119 return axi; 120 } 121 122 /** 123 * stmmac_mtl_setup - parse DT parameters for multiple queues configuration 124 * @pdev: platform device 125 */ 126 static int stmmac_mtl_setup(struct platform_device *pdev, 127 struct plat_stmmacenet_data *plat) 128 { 129 struct device_node *q_node; 130 struct device_node *rx_node; 131 struct device_node *tx_node; 132 u8 queue = 0; 133 int ret = 0; 134 135 /* For backwards-compatibility with device trees that don't have any 136 * snps,mtl-rx-config or snps,mtl-tx-config properties, we fall back 137 * to one RX and TX queues each. 138 */ 139 plat->rx_queues_to_use = 1; 140 plat->tx_queues_to_use = 1; 141 142 /* First Queue must always be in DCB mode. As MTL_QUEUE_DCB = 1 we need 143 * to always set this, otherwise Queue will be classified as AVB 144 * (because MTL_QUEUE_AVB = 0). 145 */ 146 plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB; 147 plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB; 148 149 rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0); 150 if (!rx_node) 151 return ret; 152 153 tx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-tx-config", 0); 154 if (!tx_node) { 155 of_node_put(rx_node); 156 return ret; 157 } 158 159 /* Processing RX queues common config */ 160 if (of_property_read_u32(rx_node, "snps,rx-queues-to-use", 161 &plat->rx_queues_to_use)) 162 plat->rx_queues_to_use = 1; 163 164 if (of_property_read_bool(rx_node, "snps,rx-sched-sp")) 165 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; 166 else if (of_property_read_bool(rx_node, "snps,rx-sched-wsp")) 167 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_WSP; 168 else 169 plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; 170 171 /* Processing individual RX queue config */ 172 for_each_child_of_node(rx_node, q_node) { 173 if (queue >= plat->rx_queues_to_use) 174 break; 175 176 if (of_property_read_bool(q_node, "snps,dcb-algorithm")) 177 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; 178 else if (of_property_read_bool(q_node, "snps,avb-algorithm")) 179 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB; 180 else 181 plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; 182 183 if (of_property_read_u32(q_node, "snps,map-to-dma-channel", 184 &plat->rx_queues_cfg[queue].chan)) 185 plat->rx_queues_cfg[queue].chan = queue; 186 /* TODO: Dynamic mapping to be included in the future */ 187 188 if (of_property_read_u32(q_node, "snps,priority", 189 &plat->rx_queues_cfg[queue].prio)) { 190 plat->rx_queues_cfg[queue].prio = 0; 191 plat->rx_queues_cfg[queue].use_prio = false; 192 } else { 193 plat->rx_queues_cfg[queue].use_prio = true; 194 } 195 196 /* RX queue specific packet type routing */ 197 if (of_property_read_bool(q_node, "snps,route-avcp")) 198 plat->rx_queues_cfg[queue].pkt_route = PACKET_AVCPQ; 199 else if (of_property_read_bool(q_node, "snps,route-ptp")) 200 plat->rx_queues_cfg[queue].pkt_route = PACKET_PTPQ; 201 else if (of_property_read_bool(q_node, "snps,route-dcbcp")) 202 plat->rx_queues_cfg[queue].pkt_route = PACKET_DCBCPQ; 203 else if (of_property_read_bool(q_node, "snps,route-up")) 204 plat->rx_queues_cfg[queue].pkt_route = PACKET_UPQ; 205 else if (of_property_read_bool(q_node, "snps,route-multi-broad")) 206 plat->rx_queues_cfg[queue].pkt_route = PACKET_MCBCQ; 207 else 208 plat->rx_queues_cfg[queue].pkt_route = 0x0; 209 210 queue++; 211 } 212 if (queue != plat->rx_queues_to_use) { 213 ret = -EINVAL; 214 dev_err(&pdev->dev, "Not all RX queues were configured\n"); 215 goto out; 216 } 217 218 /* Processing TX queues common config */ 219 if (of_property_read_u32(tx_node, "snps,tx-queues-to-use", 220 &plat->tx_queues_to_use)) 221 plat->tx_queues_to_use = 1; 222 223 if (of_property_read_bool(tx_node, "snps,tx-sched-wrr")) 224 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR; 225 else if (of_property_read_bool(tx_node, "snps,tx-sched-wfq")) 226 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WFQ; 227 else if (of_property_read_bool(tx_node, "snps,tx-sched-dwrr")) 228 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_DWRR; 229 else if (of_property_read_bool(tx_node, "snps,tx-sched-sp")) 230 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP; 231 else 232 plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP; 233 234 queue = 0; 235 236 /* Processing individual TX queue config */ 237 for_each_child_of_node(tx_node, q_node) { 238 if (queue >= plat->tx_queues_to_use) 239 break; 240 241 if (of_property_read_u32(q_node, "snps,weight", 242 &plat->tx_queues_cfg[queue].weight)) 243 plat->tx_queues_cfg[queue].weight = 0x10 + queue; 244 245 if (of_property_read_bool(q_node, "snps,dcb-algorithm")) { 246 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; 247 } else if (of_property_read_bool(q_node, 248 "snps,avb-algorithm")) { 249 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB; 250 251 /* Credit Base Shaper parameters used by AVB */ 252 if (of_property_read_u32(q_node, "snps,send_slope", 253 &plat->tx_queues_cfg[queue].send_slope)) 254 plat->tx_queues_cfg[queue].send_slope = 0x0; 255 if (of_property_read_u32(q_node, "snps,idle_slope", 256 &plat->tx_queues_cfg[queue].idle_slope)) 257 plat->tx_queues_cfg[queue].idle_slope = 0x0; 258 if (of_property_read_u32(q_node, "snps,high_credit", 259 &plat->tx_queues_cfg[queue].high_credit)) 260 plat->tx_queues_cfg[queue].high_credit = 0x0; 261 if (of_property_read_u32(q_node, "snps,low_credit", 262 &plat->tx_queues_cfg[queue].low_credit)) 263 plat->tx_queues_cfg[queue].low_credit = 0x0; 264 } else { 265 plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; 266 } 267 268 if (of_property_read_u32(q_node, "snps,priority", 269 &plat->tx_queues_cfg[queue].prio)) { 270 plat->tx_queues_cfg[queue].prio = 0; 271 plat->tx_queues_cfg[queue].use_prio = false; 272 } else { 273 plat->tx_queues_cfg[queue].use_prio = true; 274 } 275 276 queue++; 277 } 278 if (queue != plat->tx_queues_to_use) { 279 ret = -EINVAL; 280 dev_err(&pdev->dev, "Not all TX queues were configured\n"); 281 goto out; 282 } 283 284 out: 285 of_node_put(rx_node); 286 of_node_put(tx_node); 287 of_node_put(q_node); 288 289 return ret; 290 } 291 292 /** 293 * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources 294 * @plat: driver data platform structure 295 * @np: device tree node 296 * @dev: device pointer 297 * Description: 298 * The mdio bus will be allocated in case of a phy transceiver is on board; 299 * it will be NULL if the fixed-link is configured. 300 * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated 301 * in any case (for DSA, mdio must be registered even if fixed-link). 302 * The table below sums the supported configurations: 303 * ------------------------------- 304 * snps,phy-addr | Y 305 * ------------------------------- 306 * phy-handle | Y 307 * ------------------------------- 308 * fixed-link | N 309 * ------------------------------- 310 * snps,dwmac-mdio | 311 * even if | Y 312 * fixed-link | 313 * ------------------------------- 314 * 315 * It returns 0 in case of success otherwise -ENODEV. 316 */ 317 static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, 318 struct device_node *np, struct device *dev) 319 { 320 bool mdio = true; 321 static const struct of_device_id need_mdio_ids[] = { 322 { .compatible = "snps,dwc-qos-ethernet-4.10" }, 323 {}, 324 }; 325 326 if (of_match_node(need_mdio_ids, np)) { 327 plat->mdio_node = of_get_child_by_name(np, "mdio"); 328 } else { 329 /** 330 * If snps,dwmac-mdio is passed from DT, always register 331 * the MDIO 332 */ 333 for_each_child_of_node(np, plat->mdio_node) { 334 if (of_device_is_compatible(plat->mdio_node, 335 "snps,dwmac-mdio")) 336 break; 337 } 338 } 339 340 if (plat->mdio_node) { 341 dev_dbg(dev, "Found MDIO subnode\n"); 342 mdio = true; 343 } 344 345 if (mdio) 346 plat->mdio_bus_data = 347 devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), 348 GFP_KERNEL); 349 return 0; 350 } 351 352 /** 353 * stmmac_probe_config_dt - parse device-tree driver parameters 354 * @pdev: platform_device structure 355 * @mac: MAC address to use 356 * Description: 357 * this function is to read the driver parameters from device-tree and 358 * set some private fields that will be used by the main at runtime. 359 */ 360 struct plat_stmmacenet_data * 361 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) 362 { 363 struct device_node *np = pdev->dev.of_node; 364 struct plat_stmmacenet_data *plat; 365 struct stmmac_dma_cfg *dma_cfg; 366 int rc; 367 368 plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); 369 if (!plat) 370 return ERR_PTR(-ENOMEM); 371 372 *mac = of_get_mac_address(np); 373 if (IS_ERR(*mac)) { 374 if (PTR_ERR(*mac) == -EPROBE_DEFER) 375 return ERR_CAST(*mac); 376 377 *mac = NULL; 378 } 379 380 plat->interface = of_get_phy_mode(np); 381 382 /* Some wrapper drivers still rely on phy_node. Let's save it while 383 * they are not converted to phylink. */ 384 plat->phy_node = of_parse_phandle(np, "phy-handle", 0); 385 386 /* PHYLINK automatically parses the phy-handle property */ 387 plat->phylink_node = np; 388 389 /* Get max speed of operation from device tree */ 390 if (of_property_read_u32(np, "max-speed", &plat->max_speed)) 391 plat->max_speed = -1; 392 393 plat->bus_id = of_alias_get_id(np, "ethernet"); 394 if (plat->bus_id < 0) 395 plat->bus_id = 0; 396 397 /* Default to phy auto-detection */ 398 plat->phy_addr = -1; 399 400 /* Default to get clk_csr from stmmac_clk_crs_set(), 401 * or get clk_csr from device tree. 402 */ 403 plat->clk_csr = -1; 404 of_property_read_u32(np, "clk_csr", &plat->clk_csr); 405 406 /* "snps,phy-addr" is not a standard property. Mark it as deprecated 407 * and warn of its use. Remove this when phy node support is added. 408 */ 409 if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) 410 dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); 411 412 /* To Configure PHY by using all device-tree supported properties */ 413 rc = stmmac_dt_phy(plat, np, &pdev->dev); 414 if (rc) 415 return ERR_PTR(rc); 416 417 of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); 418 419 of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size); 420 421 plat->force_sf_dma_mode = 422 of_property_read_bool(np, "snps,force_sf_dma_mode"); 423 424 plat->en_tx_lpi_clockgating = 425 of_property_read_bool(np, "snps,en-tx-lpi-clockgating"); 426 427 /* Set the maxmtu to a default of JUMBO_LEN in case the 428 * parameter is not present in the device tree. 429 */ 430 plat->maxmtu = JUMBO_LEN; 431 432 /* Set default value for multicast hash bins */ 433 plat->multicast_filter_bins = HASH_TABLE_SIZE; 434 435 /* Set default value for unicast filter entries */ 436 plat->unicast_filter_entries = 1; 437 438 /* 439 * Currently only the properties needed on SPEAr600 440 * are provided. All other properties should be added 441 * once needed on other platforms. 442 */ 443 if (of_device_is_compatible(np, "st,spear600-gmac") || 444 of_device_is_compatible(np, "snps,dwmac-3.50a") || 445 of_device_is_compatible(np, "snps,dwmac-3.70a") || 446 of_device_is_compatible(np, "snps,dwmac")) { 447 /* Note that the max-frame-size parameter as defined in the 448 * ePAPR v1.1 spec is defined as max-frame-size, it's 449 * actually used as the IEEE definition of MAC Client 450 * data, or MTU. The ePAPR specification is confusing as 451 * the definition is max-frame-size, but usage examples 452 * are clearly MTUs 453 */ 454 of_property_read_u32(np, "max-frame-size", &plat->maxmtu); 455 of_property_read_u32(np, "snps,multicast-filter-bins", 456 &plat->multicast_filter_bins); 457 of_property_read_u32(np, "snps,perfect-filter-entries", 458 &plat->unicast_filter_entries); 459 plat->unicast_filter_entries = dwmac1000_validate_ucast_entries( 460 plat->unicast_filter_entries); 461 plat->multicast_filter_bins = dwmac1000_validate_mcast_bins( 462 plat->multicast_filter_bins); 463 plat->has_gmac = 1; 464 plat->pmt = 1; 465 } 466 467 if (of_device_is_compatible(np, "snps,dwmac-4.00") || 468 of_device_is_compatible(np, "snps,dwmac-4.10a") || 469 of_device_is_compatible(np, "snps,dwmac-4.20a")) { 470 plat->has_gmac4 = 1; 471 plat->has_gmac = 0; 472 plat->pmt = 1; 473 plat->tso_en = of_property_read_bool(np, "snps,tso"); 474 } 475 476 if (of_device_is_compatible(np, "snps,dwmac-3.610") || 477 of_device_is_compatible(np, "snps,dwmac-3.710")) { 478 plat->enh_desc = 1; 479 plat->bugged_jumbo = 1; 480 plat->force_sf_dma_mode = 1; 481 } 482 483 if (of_device_is_compatible(np, "snps,dwxgmac")) { 484 plat->has_xgmac = 1; 485 plat->pmt = 1; 486 plat->tso_en = of_property_read_bool(np, "snps,tso"); 487 } 488 489 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), 490 GFP_KERNEL); 491 if (!dma_cfg) { 492 stmmac_remove_config_dt(pdev, plat); 493 return ERR_PTR(-ENOMEM); 494 } 495 plat->dma_cfg = dma_cfg; 496 497 of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); 498 if (!dma_cfg->pbl) 499 dma_cfg->pbl = DEFAULT_DMA_PBL; 500 of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl); 501 of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl); 502 dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8"); 503 504 dma_cfg->aal = of_property_read_bool(np, "snps,aal"); 505 dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst"); 506 dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst"); 507 508 plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode"); 509 if (plat->force_thresh_dma_mode) { 510 plat->force_sf_dma_mode = 0; 511 pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); 512 } 513 514 of_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed); 515 516 plat->axi = stmmac_axi_setup(pdev); 517 518 rc = stmmac_mtl_setup(pdev, plat); 519 if (rc) { 520 stmmac_remove_config_dt(pdev, plat); 521 return ERR_PTR(rc); 522 } 523 524 /* clock setup */ 525 plat->stmmac_clk = devm_clk_get(&pdev->dev, 526 STMMAC_RESOURCE_NAME); 527 if (IS_ERR(plat->stmmac_clk)) { 528 dev_warn(&pdev->dev, "Cannot get CSR clock\n"); 529 plat->stmmac_clk = NULL; 530 } 531 clk_prepare_enable(plat->stmmac_clk); 532 533 plat->pclk = devm_clk_get(&pdev->dev, "pclk"); 534 if (IS_ERR(plat->pclk)) { 535 if (PTR_ERR(plat->pclk) == -EPROBE_DEFER) 536 goto error_pclk_get; 537 538 plat->pclk = NULL; 539 } 540 clk_prepare_enable(plat->pclk); 541 542 /* Fall-back to main clock in case of no PTP ref is passed */ 543 plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "ptp_ref"); 544 if (IS_ERR(plat->clk_ptp_ref)) { 545 plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk); 546 plat->clk_ptp_ref = NULL; 547 dev_warn(&pdev->dev, "PTP uses main clock\n"); 548 } else { 549 plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref); 550 dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate); 551 } 552 553 plat->stmmac_rst = devm_reset_control_get(&pdev->dev, 554 STMMAC_RESOURCE_NAME); 555 if (IS_ERR(plat->stmmac_rst)) { 556 if (PTR_ERR(plat->stmmac_rst) == -EPROBE_DEFER) 557 goto error_hw_init; 558 559 dev_info(&pdev->dev, "no reset control found\n"); 560 plat->stmmac_rst = NULL; 561 } 562 563 return plat; 564 565 error_hw_init: 566 clk_disable_unprepare(plat->pclk); 567 error_pclk_get: 568 clk_disable_unprepare(plat->stmmac_clk); 569 570 return ERR_PTR(-EPROBE_DEFER); 571 } 572 573 /** 574 * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt() 575 * @pdev: platform_device structure 576 * @plat: driver data platform structure 577 * 578 * Release resources claimed by stmmac_probe_config_dt(). 579 */ 580 void stmmac_remove_config_dt(struct platform_device *pdev, 581 struct plat_stmmacenet_data *plat) 582 { 583 of_node_put(plat->phy_node); 584 of_node_put(plat->mdio_node); 585 } 586 #else 587 struct plat_stmmacenet_data * 588 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) 589 { 590 return ERR_PTR(-EINVAL); 591 } 592 593 void stmmac_remove_config_dt(struct platform_device *pdev, 594 struct plat_stmmacenet_data *plat) 595 { 596 } 597 #endif /* CONFIG_OF */ 598 EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); 599 EXPORT_SYMBOL_GPL(stmmac_remove_config_dt); 600 601 int stmmac_get_platform_resources(struct platform_device *pdev, 602 struct stmmac_resources *stmmac_res) 603 { 604 struct resource *res; 605 606 memset(stmmac_res, 0, sizeof(*stmmac_res)); 607 608 /* Get IRQ information early to have an ability to ask for deferred 609 * probe if needed before we went too far with resource allocation. 610 */ 611 stmmac_res->irq = platform_get_irq_byname(pdev, "macirq"); 612 if (stmmac_res->irq < 0) { 613 if (stmmac_res->irq != -EPROBE_DEFER) { 614 dev_err(&pdev->dev, 615 "MAC IRQ configuration information not found\n"); 616 } 617 return stmmac_res->irq; 618 } 619 620 /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq 621 * The external wake up irq can be passed through the platform code 622 * named as "eth_wake_irq" 623 * 624 * In case the wake up interrupt is not passed from the platform 625 * so the driver will continue to use the mac irq (ndev->irq) 626 */ 627 stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); 628 if (stmmac_res->wol_irq < 0) { 629 if (stmmac_res->wol_irq == -EPROBE_DEFER) 630 return -EPROBE_DEFER; 631 stmmac_res->wol_irq = stmmac_res->irq; 632 } 633 634 stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); 635 if (stmmac_res->lpi_irq == -EPROBE_DEFER) 636 return -EPROBE_DEFER; 637 638 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 639 stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res); 640 641 return PTR_ERR_OR_ZERO(stmmac_res->addr); 642 } 643 EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); 644 645 /** 646 * stmmac_pltfr_remove 647 * @pdev: platform device pointer 648 * Description: this function calls the main to free the net resources 649 * and calls the platforms hook and release the resources (e.g. mem). 650 */ 651 int stmmac_pltfr_remove(struct platform_device *pdev) 652 { 653 struct net_device *ndev = platform_get_drvdata(pdev); 654 struct stmmac_priv *priv = netdev_priv(ndev); 655 struct plat_stmmacenet_data *plat = priv->plat; 656 int ret = stmmac_dvr_remove(&pdev->dev); 657 658 if (plat->exit) 659 plat->exit(pdev, plat->bsp_priv); 660 661 stmmac_remove_config_dt(pdev, plat); 662 663 return ret; 664 } 665 EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); 666 667 #ifdef CONFIG_PM_SLEEP 668 /** 669 * stmmac_pltfr_suspend 670 * @dev: device pointer 671 * Description: this function is invoked when suspend the driver and it direcly 672 * call the main suspend function and then, if required, on some platform, it 673 * can call an exit helper. 674 */ 675 static int stmmac_pltfr_suspend(struct device *dev) 676 { 677 int ret; 678 struct net_device *ndev = dev_get_drvdata(dev); 679 struct stmmac_priv *priv = netdev_priv(ndev); 680 struct platform_device *pdev = to_platform_device(dev); 681 682 ret = stmmac_suspend(dev); 683 if (priv->plat->exit) 684 priv->plat->exit(pdev, priv->plat->bsp_priv); 685 686 return ret; 687 } 688 689 /** 690 * stmmac_pltfr_resume 691 * @dev: device pointer 692 * Description: this function is invoked when resume the driver before calling 693 * the main resume function, on some platforms, it can call own init helper 694 * if required. 695 */ 696 static int stmmac_pltfr_resume(struct device *dev) 697 { 698 struct net_device *ndev = dev_get_drvdata(dev); 699 struct stmmac_priv *priv = netdev_priv(ndev); 700 struct platform_device *pdev = to_platform_device(dev); 701 702 if (priv->plat->init) 703 priv->plat->init(pdev, priv->plat->bsp_priv); 704 705 return stmmac_resume(dev); 706 } 707 #endif /* CONFIG_PM_SLEEP */ 708 709 SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, 710 stmmac_pltfr_resume); 711 EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); 712 713 MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); 714 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 715 MODULE_LICENSE("GPL"); 716