linux/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
<<
>>
Prefs
   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 */
  36static 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 */
  65static 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 */
  90static 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 */
 126static 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
 284out:
 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 */
 317static 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 */
 360struct plat_stmmacenet_data *
 361stmmac_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
 565error_hw_init:
 566        clk_disable_unprepare(plat->pclk);
 567error_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 */
 580void 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
 587struct plat_stmmacenet_data *
 588stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 589{
 590        return ERR_PTR(-EINVAL);
 591}
 592
 593void stmmac_remove_config_dt(struct platform_device *pdev,
 594                             struct plat_stmmacenet_data *plat)
 595{
 596}
 597#endif /* CONFIG_OF */
 598EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
 599EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
 600
 601int 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}
 643EXPORT_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 */
 651int 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}
 665EXPORT_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 */
 675static 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 */
 696static 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
 709SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend,
 710                                       stmmac_pltfr_resume);
 711EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
 712
 713MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
 714MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
 715MODULE_LICENSE("GPL");
 716