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 phy-handle property is passed from DT, use it as the PHY */ 327 plat->phy_node = of_parse_phandle(np, "phy-handle", 0); 328 if (plat->phy_node) 329 dev_dbg(dev, "Found phy-handle subnode\n"); 330 331 /* If phy-handle is not specified, check if we have a fixed-phy */ 332 if (!plat->phy_node && of_phy_is_fixed_link(np)) { 333 if ((of_phy_register_fixed_link(np) < 0)) 334 return -ENODEV; 335 336 dev_dbg(dev, "Found fixed-link subnode\n"); 337 plat->phy_node = of_node_get(np); 338 mdio = false; 339 } 340 341 if (of_match_node(need_mdio_ids, np)) { 342 plat->mdio_node = of_get_child_by_name(np, "mdio"); 343 } else { 344 /** 345 * If snps,dwmac-mdio is passed from DT, always register 346 * the MDIO 347 */ 348 for_each_child_of_node(np, plat->mdio_node) { 349 if (of_device_is_compatible(plat->mdio_node, 350 "snps,dwmac-mdio")) 351 break; 352 } 353 } 354 355 if (plat->mdio_node) { 356 dev_dbg(dev, "Found MDIO subnode\n"); 357 mdio = true; 358 } 359 360 if (mdio) 361 plat->mdio_bus_data = 362 devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), 363 GFP_KERNEL); 364 return 0; 365 } 366 367 /** 368 * stmmac_probe_config_dt - parse device-tree driver parameters 369 * @pdev: platform_device structure 370 * @mac: MAC address to use 371 * Description: 372 * this function is to read the driver parameters from device-tree and 373 * set some private fields that will be used by the main at runtime. 374 */ 375 struct plat_stmmacenet_data * 376 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) 377 { 378 struct device_node *np = pdev->dev.of_node; 379 struct plat_stmmacenet_data *plat; 380 struct stmmac_dma_cfg *dma_cfg; 381 int rc; 382 383 plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); 384 if (!plat) 385 return ERR_PTR(-ENOMEM); 386 387 *mac = of_get_mac_address(np); 388 plat->interface = of_get_phy_mode(np); 389 390 /* Get max speed of operation from device tree */ 391 if (of_property_read_u32(np, "max-speed", &plat->max_speed)) 392 plat->max_speed = -1; 393 394 plat->bus_id = of_alias_get_id(np, "ethernet"); 395 if (plat->bus_id < 0) 396 plat->bus_id = 0; 397 398 /* Default to phy auto-detection */ 399 plat->phy_addr = -1; 400 401 /* Default to get clk_csr from stmmac_clk_crs_set(), 402 * or get clk_csr from device tree. 403 */ 404 plat->clk_csr = -1; 405 of_property_read_u32(np, "clk_csr", &plat->clk_csr); 406 407 /* "snps,phy-addr" is not a standard property. Mark it as deprecated 408 * and warn of its use. Remove this when phy node support is added. 409 */ 410 if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) 411 dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); 412 413 /* To Configure PHY by using all device-tree supported properties */ 414 rc = stmmac_dt_phy(plat, np, &pdev->dev); 415 if (rc) 416 return ERR_PTR(rc); 417 418 of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); 419 420 of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size); 421 422 plat->force_sf_dma_mode = 423 of_property_read_bool(np, "snps,force_sf_dma_mode"); 424 425 plat->en_tx_lpi_clockgating = 426 of_property_read_bool(np, "snps,en-tx-lpi-clockgating"); 427 428 /* Set the maxmtu to a default of JUMBO_LEN in case the 429 * parameter is not present in the device tree. 430 */ 431 plat->maxmtu = JUMBO_LEN; 432 433 /* Set default value for multicast hash bins */ 434 plat->multicast_filter_bins = HASH_TABLE_SIZE; 435 436 /* Set default value for unicast filter entries */ 437 plat->unicast_filter_entries = 1; 438 439 /* 440 * Currently only the properties needed on SPEAr600 441 * are provided. All other properties should be added 442 * once needed on other platforms. 443 */ 444 if (of_device_is_compatible(np, "st,spear600-gmac") || 445 of_device_is_compatible(np, "snps,dwmac-3.50a") || 446 of_device_is_compatible(np, "snps,dwmac-3.70a") || 447 of_device_is_compatible(np, "snps,dwmac")) { 448 /* Note that the max-frame-size parameter as defined in the 449 * ePAPR v1.1 spec is defined as max-frame-size, it's 450 * actually used as the IEEE definition of MAC Client 451 * data, or MTU. The ePAPR specification is confusing as 452 * the definition is max-frame-size, but usage examples 453 * are clearly MTUs 454 */ 455 of_property_read_u32(np, "max-frame-size", &plat->maxmtu); 456 of_property_read_u32(np, "snps,multicast-filter-bins", 457 &plat->multicast_filter_bins); 458 of_property_read_u32(np, "snps,perfect-filter-entries", 459 &plat->unicast_filter_entries); 460 plat->unicast_filter_entries = dwmac1000_validate_ucast_entries( 461 plat->unicast_filter_entries); 462 plat->multicast_filter_bins = dwmac1000_validate_mcast_bins( 463 plat->multicast_filter_bins); 464 plat->has_gmac = 1; 465 plat->pmt = 1; 466 } 467 468 if (of_device_is_compatible(np, "snps,dwmac-4.00") || 469 of_device_is_compatible(np, "snps,dwmac-4.10a") || 470 of_device_is_compatible(np, "snps,dwmac-4.20a")) { 471 plat->has_gmac4 = 1; 472 plat->has_gmac = 0; 473 plat->pmt = 1; 474 plat->tso_en = of_property_read_bool(np, "snps,tso"); 475 } 476 477 if (of_device_is_compatible(np, "snps,dwmac-3.610") || 478 of_device_is_compatible(np, "snps,dwmac-3.710")) { 479 plat->enh_desc = 1; 480 plat->bugged_jumbo = 1; 481 plat->force_sf_dma_mode = 1; 482 } 483 484 if (of_device_is_compatible(np, "snps,dwxgmac")) { 485 plat->has_xgmac = 1; 486 plat->pmt = 1; 487 plat->tso_en = of_property_read_bool(np, "snps,tso"); 488 } 489 490 dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), 491 GFP_KERNEL); 492 if (!dma_cfg) { 493 stmmac_remove_config_dt(pdev, plat); 494 return ERR_PTR(-ENOMEM); 495 } 496 plat->dma_cfg = dma_cfg; 497 498 of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); 499 if (!dma_cfg->pbl) 500 dma_cfg->pbl = DEFAULT_DMA_PBL; 501 of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl); 502 of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl); 503 dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8"); 504 505 dma_cfg->aal = of_property_read_bool(np, "snps,aal"); 506 dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst"); 507 dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst"); 508 509 plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode"); 510 if (plat->force_thresh_dma_mode) { 511 plat->force_sf_dma_mode = 0; 512 pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); 513 } 514 515 of_property_read_u32(np, "snps,ps-speed", &plat->mac_port_sel_speed); 516 517 plat->axi = stmmac_axi_setup(pdev); 518 519 rc = stmmac_mtl_setup(pdev, plat); 520 if (rc) { 521 stmmac_remove_config_dt(pdev, plat); 522 return ERR_PTR(rc); 523 } 524 525 /* clock setup */ 526 plat->stmmac_clk = devm_clk_get(&pdev->dev, 527 STMMAC_RESOURCE_NAME); 528 if (IS_ERR(plat->stmmac_clk)) { 529 dev_warn(&pdev->dev, "Cannot get CSR clock\n"); 530 plat->stmmac_clk = NULL; 531 } 532 clk_prepare_enable(plat->stmmac_clk); 533 534 plat->pclk = devm_clk_get(&pdev->dev, "pclk"); 535 if (IS_ERR(plat->pclk)) { 536 if (PTR_ERR(plat->pclk) == -EPROBE_DEFER) 537 goto error_pclk_get; 538 539 plat->pclk = NULL; 540 } 541 clk_prepare_enable(plat->pclk); 542 543 /* Fall-back to main clock in case of no PTP ref is passed */ 544 plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "ptp_ref"); 545 if (IS_ERR(plat->clk_ptp_ref)) { 546 plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk); 547 plat->clk_ptp_ref = NULL; 548 dev_warn(&pdev->dev, "PTP uses main clock\n"); 549 } else { 550 plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref); 551 dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate); 552 } 553 554 plat->stmmac_rst = devm_reset_control_get(&pdev->dev, 555 STMMAC_RESOURCE_NAME); 556 if (IS_ERR(plat->stmmac_rst)) { 557 if (PTR_ERR(plat->stmmac_rst) == -EPROBE_DEFER) 558 goto error_hw_init; 559 560 dev_info(&pdev->dev, "no reset control found\n"); 561 plat->stmmac_rst = NULL; 562 } 563 564 return plat; 565 566 error_hw_init: 567 clk_disable_unprepare(plat->pclk); 568 error_pclk_get: 569 clk_disable_unprepare(plat->stmmac_clk); 570 571 return ERR_PTR(-EPROBE_DEFER); 572 } 573 574 /** 575 * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt() 576 * @pdev: platform_device structure 577 * @plat: driver data platform structure 578 * 579 * Release resources claimed by stmmac_probe_config_dt(). 580 */ 581 void stmmac_remove_config_dt(struct platform_device *pdev, 582 struct plat_stmmacenet_data *plat) 583 { 584 struct device_node *np = pdev->dev.of_node; 585 586 if (of_phy_is_fixed_link(np)) 587 of_phy_deregister_fixed_link(np); 588 of_node_put(plat->phy_node); 589 of_node_put(plat->mdio_node); 590 } 591 #else 592 struct plat_stmmacenet_data * 593 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) 594 { 595 return ERR_PTR(-EINVAL); 596 } 597 598 void stmmac_remove_config_dt(struct platform_device *pdev, 599 struct plat_stmmacenet_data *plat) 600 { 601 } 602 #endif /* CONFIG_OF */ 603 EXPORT_SYMBOL_GPL(stmmac_probe_config_dt); 604 EXPORT_SYMBOL_GPL(stmmac_remove_config_dt); 605 606 int stmmac_get_platform_resources(struct platform_device *pdev, 607 struct stmmac_resources *stmmac_res) 608 { 609 struct resource *res; 610 611 memset(stmmac_res, 0, sizeof(*stmmac_res)); 612 613 /* Get IRQ information early to have an ability to ask for deferred 614 * probe if needed before we went too far with resource allocation. 615 */ 616 stmmac_res->irq = platform_get_irq_byname(pdev, "macirq"); 617 if (stmmac_res->irq < 0) { 618 if (stmmac_res->irq != -EPROBE_DEFER) { 619 dev_err(&pdev->dev, 620 "MAC IRQ configuration information not found\n"); 621 } 622 return stmmac_res->irq; 623 } 624 625 /* On some platforms e.g. SPEAr the wake up irq differs from the mac irq 626 * The external wake up irq can be passed through the platform code 627 * named as "eth_wake_irq" 628 * 629 * In case the wake up interrupt is not passed from the platform 630 * so the driver will continue to use the mac irq (ndev->irq) 631 */ 632 stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq"); 633 if (stmmac_res->wol_irq < 0) { 634 if (stmmac_res->wol_irq == -EPROBE_DEFER) 635 return -EPROBE_DEFER; 636 stmmac_res->wol_irq = stmmac_res->irq; 637 } 638 639 stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi"); 640 if (stmmac_res->lpi_irq == -EPROBE_DEFER) 641 return -EPROBE_DEFER; 642 643 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 644 stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res); 645 646 return PTR_ERR_OR_ZERO(stmmac_res->addr); 647 } 648 EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); 649 650 /** 651 * stmmac_pltfr_remove 652 * @pdev: platform device pointer 653 * Description: this function calls the main to free the net resources 654 * and calls the platforms hook and release the resources (e.g. mem). 655 */ 656 int stmmac_pltfr_remove(struct platform_device *pdev) 657 { 658 struct net_device *ndev = platform_get_drvdata(pdev); 659 struct stmmac_priv *priv = netdev_priv(ndev); 660 struct plat_stmmacenet_data *plat = priv->plat; 661 int ret = stmmac_dvr_remove(&pdev->dev); 662 663 if (plat->exit) 664 plat->exit(pdev, plat->bsp_priv); 665 666 stmmac_remove_config_dt(pdev, plat); 667 668 return ret; 669 } 670 EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); 671 672 #ifdef CONFIG_PM_SLEEP 673 /** 674 * stmmac_pltfr_suspend 675 * @dev: device pointer 676 * Description: this function is invoked when suspend the driver and it direcly 677 * call the main suspend function and then, if required, on some platform, it 678 * can call an exit helper. 679 */ 680 static int stmmac_pltfr_suspend(struct device *dev) 681 { 682 int ret; 683 struct net_device *ndev = dev_get_drvdata(dev); 684 struct stmmac_priv *priv = netdev_priv(ndev); 685 struct platform_device *pdev = to_platform_device(dev); 686 687 ret = stmmac_suspend(dev); 688 if (priv->plat->exit) 689 priv->plat->exit(pdev, priv->plat->bsp_priv); 690 691 return ret; 692 } 693 694 /** 695 * stmmac_pltfr_resume 696 * @dev: device pointer 697 * Description: this function is invoked when resume the driver before calling 698 * the main resume function, on some platforms, it can call own init helper 699 * if required. 700 */ 701 static int stmmac_pltfr_resume(struct device *dev) 702 { 703 struct net_device *ndev = dev_get_drvdata(dev); 704 struct stmmac_priv *priv = netdev_priv(ndev); 705 struct platform_device *pdev = to_platform_device(dev); 706 707 if (priv->plat->init) 708 priv->plat->init(pdev, priv->plat->bsp_priv); 709 710 return stmmac_resume(dev); 711 } 712 #endif /* CONFIG_PM_SLEEP */ 713 714 SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, 715 stmmac_pltfr_resume); 716 EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); 717 718 MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); 719 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 720 MODULE_LICENSE("GPL"); 721