Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * AMD 10Gb Ethernet driver
0003  *
0004  * This file is available to you under your choice of the following two
0005  * licenses:
0006  *
0007  * License 1: GPLv2
0008  *
0009  * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
0010  *
0011  * This file is free software; you may copy, redistribute and/or modify
0012  * it under the terms of the GNU General Public License as published by
0013  * the Free Software Foundation, either version 2 of the License, or (at
0014  * your option) any later version.
0015  *
0016  * This file is distributed in the hope that it will be useful, but
0017  * WITHOUT ANY WARRANTY; without even the implied warranty of
0018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0019  * General Public License for more details.
0020  *
0021  * You should have received a copy of the GNU General Public License
0022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0023  *
0024  * This file incorporates work covered by the following copyright and
0025  * permission notice:
0026  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
0027  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
0028  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
0029  *     and you.
0030  *
0031  *     The Software IS NOT an item of Licensed Software or Licensed Product
0032  *     under any End User Software License Agreement or Agreement for Licensed
0033  *     Product with Synopsys or any supplement thereto.  Permission is hereby
0034  *     granted, free of charge, to any person obtaining a copy of this software
0035  *     annotated with this license and the Software, to deal in the Software
0036  *     without restriction, including without limitation the rights to use,
0037  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
0038  *     of the Software, and to permit persons to whom the Software is furnished
0039  *     to do so, subject to the following conditions:
0040  *
0041  *     The above copyright notice and this permission notice shall be included
0042  *     in all copies or substantial portions of the Software.
0043  *
0044  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
0045  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
0046  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0047  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
0048  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0049  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0050  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0051  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0052  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0053  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0054  *     THE POSSIBILITY OF SUCH DAMAGE.
0055  *
0056  *
0057  * License 2: Modified BSD
0058  *
0059  * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
0060  * All rights reserved.
0061  *
0062  * Redistribution and use in source and binary forms, with or without
0063  * modification, are permitted provided that the following conditions are met:
0064  *     * Redistributions of source code must retain the above copyright
0065  *       notice, this list of conditions and the following disclaimer.
0066  *     * Redistributions in binary form must reproduce the above copyright
0067  *       notice, this list of conditions and the following disclaimer in the
0068  *       documentation and/or other materials provided with the distribution.
0069  *     * Neither the name of Advanced Micro Devices, Inc. nor the
0070  *       names of its contributors may be used to endorse or promote products
0071  *       derived from this software without specific prior written permission.
0072  *
0073  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0074  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0075  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0076  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
0077  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0078  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0079  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0080  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0081  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0082  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0083  *
0084  * This file incorporates work covered by the following copyright and
0085  * permission notice:
0086  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
0087  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
0088  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
0089  *     and you.
0090  *
0091  *     The Software IS NOT an item of Licensed Software or Licensed Product
0092  *     under any End User Software License Agreement or Agreement for Licensed
0093  *     Product with Synopsys or any supplement thereto.  Permission is hereby
0094  *     granted, free of charge, to any person obtaining a copy of this software
0095  *     annotated with this license and the Software, to deal in the Software
0096  *     without restriction, including without limitation the rights to use,
0097  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
0098  *     of the Software, and to permit persons to whom the Software is furnished
0099  *     to do so, subject to the following conditions:
0100  *
0101  *     The above copyright notice and this permission notice shall be included
0102  *     in all copies or substantial portions of the Software.
0103  *
0104  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
0105  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
0106  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0107  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
0108  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0109  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0110  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0111  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0112  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0113  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0114  *     THE POSSIBILITY OF SUCH DAMAGE.
0115  */
0116 
0117 #include <linux/module.h>
0118 #include <linux/device.h>
0119 #include <linux/platform_device.h>
0120 #include <linux/spinlock.h>
0121 #include <linux/netdevice.h>
0122 #include <linux/etherdevice.h>
0123 #include <linux/io.h>
0124 #include <linux/of.h>
0125 #include <linux/of_net.h>
0126 #include <linux/of_address.h>
0127 #include <linux/of_platform.h>
0128 #include <linux/of_device.h>
0129 #include <linux/clk.h>
0130 #include <linux/property.h>
0131 #include <linux/acpi.h>
0132 #include <linux/mdio.h>
0133 
0134 #include "xgbe.h"
0135 #include "xgbe-common.h"
0136 
0137 #ifdef CONFIG_ACPI
0138 static const struct acpi_device_id xgbe_acpi_match[];
0139 
0140 static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
0141 {
0142     const struct acpi_device_id *id;
0143 
0144     id = acpi_match_device(xgbe_acpi_match, pdata->dev);
0145 
0146     return id ? (struct xgbe_version_data *)id->driver_data : NULL;
0147 }
0148 
0149 static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
0150 {
0151     struct device *dev = pdata->dev;
0152     u32 property;
0153     int ret;
0154 
0155     /* Obtain the system clock setting */
0156     ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property);
0157     if (ret) {
0158         dev_err(dev, "unable to obtain %s property\n",
0159             XGBE_ACPI_DMA_FREQ);
0160         return ret;
0161     }
0162     pdata->sysclk_rate = property;
0163 
0164     /* Obtain the PTP clock setting */
0165     ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property);
0166     if (ret) {
0167         dev_err(dev, "unable to obtain %s property\n",
0168             XGBE_ACPI_PTP_FREQ);
0169         return ret;
0170     }
0171     pdata->ptpclk_rate = property;
0172 
0173     return 0;
0174 }
0175 #else   /* CONFIG_ACPI */
0176 static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
0177 {
0178     return NULL;
0179 }
0180 
0181 static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
0182 {
0183     return -EINVAL;
0184 }
0185 #endif  /* CONFIG_ACPI */
0186 
0187 #ifdef CONFIG_OF
0188 static const struct of_device_id xgbe_of_match[];
0189 
0190 static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
0191 {
0192     const struct of_device_id *id;
0193 
0194     id = of_match_device(xgbe_of_match, pdata->dev);
0195 
0196     return id ? (struct xgbe_version_data *)id->data : NULL;
0197 }
0198 
0199 static int xgbe_of_support(struct xgbe_prv_data *pdata)
0200 {
0201     struct device *dev = pdata->dev;
0202 
0203     /* Obtain the system clock setting */
0204     pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
0205     if (IS_ERR(pdata->sysclk)) {
0206         dev_err(dev, "dma devm_clk_get failed\n");
0207         return PTR_ERR(pdata->sysclk);
0208     }
0209     pdata->sysclk_rate = clk_get_rate(pdata->sysclk);
0210 
0211     /* Obtain the PTP clock setting */
0212     pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
0213     if (IS_ERR(pdata->ptpclk)) {
0214         dev_err(dev, "ptp devm_clk_get failed\n");
0215         return PTR_ERR(pdata->ptpclk);
0216     }
0217     pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
0218 
0219     return 0;
0220 }
0221 
0222 static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
0223 {
0224     struct device *dev = pdata->dev;
0225     struct device_node *phy_node;
0226     struct platform_device *phy_pdev;
0227 
0228     phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);
0229     if (phy_node) {
0230         /* Old style device tree:
0231          *   The XGBE and PHY resources are separate
0232          */
0233         phy_pdev = of_find_device_by_node(phy_node);
0234         of_node_put(phy_node);
0235     } else {
0236         /* New style device tree:
0237          *   The XGBE and PHY resources are grouped together with
0238          *   the PHY resources listed last
0239          */
0240         get_device(dev);
0241         phy_pdev = pdata->platdev;
0242     }
0243 
0244     return phy_pdev;
0245 }
0246 #else   /* CONFIG_OF */
0247 static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
0248 {
0249     return NULL;
0250 }
0251 
0252 static int xgbe_of_support(struct xgbe_prv_data *pdata)
0253 {
0254     return -EINVAL;
0255 }
0256 
0257 static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
0258 {
0259     return NULL;
0260 }
0261 #endif  /* CONFIG_OF */
0262 
0263 static unsigned int xgbe_resource_count(struct platform_device *pdev,
0264                     unsigned int type)
0265 {
0266     unsigned int count;
0267     int i;
0268 
0269     for (i = 0, count = 0; i < pdev->num_resources; i++) {
0270         struct resource *res = &pdev->resource[i];
0271 
0272         if (type == resource_type(res))
0273             count++;
0274     }
0275 
0276     return count;
0277 }
0278 
0279 static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata)
0280 {
0281     struct platform_device *phy_pdev;
0282 
0283     if (pdata->use_acpi) {
0284         get_device(pdata->dev);
0285         phy_pdev = pdata->platdev;
0286     } else {
0287         phy_pdev = xgbe_of_get_phy_pdev(pdata);
0288     }
0289 
0290     return phy_pdev;
0291 }
0292 
0293 static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata)
0294 {
0295     return pdata->use_acpi ? xgbe_acpi_vdata(pdata)
0296                    : xgbe_of_vdata(pdata);
0297 }
0298 
0299 static int xgbe_platform_probe(struct platform_device *pdev)
0300 {
0301     struct xgbe_prv_data *pdata;
0302     struct device *dev = &pdev->dev;
0303     struct platform_device *phy_pdev;
0304     const char *phy_mode;
0305     unsigned int phy_memnum, phy_irqnum;
0306     unsigned int dma_irqnum, dma_irqend;
0307     enum dev_dma_attr attr;
0308     int ret;
0309 
0310     pdata = xgbe_alloc_pdata(dev);
0311     if (IS_ERR(pdata)) {
0312         ret = PTR_ERR(pdata);
0313         goto err_alloc;
0314     }
0315 
0316     pdata->platdev = pdev;
0317     pdata->adev = ACPI_COMPANION(dev);
0318     platform_set_drvdata(pdev, pdata);
0319 
0320     /* Check if we should use ACPI or DT */
0321     pdata->use_acpi = dev->of_node ? 0 : 1;
0322 
0323     /* Get the version data */
0324     pdata->vdata = xgbe_get_vdata(pdata);
0325 
0326     phy_pdev = xgbe_get_phy_pdev(pdata);
0327     if (!phy_pdev) {
0328         dev_err(dev, "unable to obtain phy device\n");
0329         ret = -EINVAL;
0330         goto err_phydev;
0331     }
0332     pdata->phy_platdev = phy_pdev;
0333     pdata->phy_dev = &phy_pdev->dev;
0334 
0335     if (pdev == phy_pdev) {
0336         /* New style device tree or ACPI:
0337          *   The XGBE and PHY resources are grouped together with
0338          *   the PHY resources listed last
0339          */
0340         phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
0341         phy_irqnum = platform_irq_count(pdev) - 1;
0342         dma_irqnum = 1;
0343         dma_irqend = phy_irqnum;
0344     } else {
0345         /* Old style device tree:
0346          *   The XGBE and PHY resources are separate
0347          */
0348         phy_memnum = 0;
0349         phy_irqnum = 0;
0350         dma_irqnum = 1;
0351         dma_irqend = platform_irq_count(pdev);
0352     }
0353 
0354     /* Obtain the mmio areas for the device */
0355     pdata->xgmac_regs = devm_platform_ioremap_resource(pdev, 0);
0356     if (IS_ERR(pdata->xgmac_regs)) {
0357         dev_err(dev, "xgmac ioremap failed\n");
0358         ret = PTR_ERR(pdata->xgmac_regs);
0359         goto err_io;
0360     }
0361     if (netif_msg_probe(pdata))
0362         dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
0363 
0364     pdata->xpcs_regs = devm_platform_ioremap_resource(pdev, 1);
0365     if (IS_ERR(pdata->xpcs_regs)) {
0366         dev_err(dev, "xpcs ioremap failed\n");
0367         ret = PTR_ERR(pdata->xpcs_regs);
0368         goto err_io;
0369     }
0370     if (netif_msg_probe(pdata))
0371         dev_dbg(dev, "xpcs_regs  = %p\n", pdata->xpcs_regs);
0372 
0373     pdata->rxtx_regs = devm_platform_ioremap_resource(phy_pdev,
0374                               phy_memnum++);
0375     if (IS_ERR(pdata->rxtx_regs)) {
0376         dev_err(dev, "rxtx ioremap failed\n");
0377         ret = PTR_ERR(pdata->rxtx_regs);
0378         goto err_io;
0379     }
0380     if (netif_msg_probe(pdata))
0381         dev_dbg(dev, "rxtx_regs  = %p\n", pdata->rxtx_regs);
0382 
0383     pdata->sir0_regs = devm_platform_ioremap_resource(phy_pdev,
0384                               phy_memnum++);
0385     if (IS_ERR(pdata->sir0_regs)) {
0386         dev_err(dev, "sir0 ioremap failed\n");
0387         ret = PTR_ERR(pdata->sir0_regs);
0388         goto err_io;
0389     }
0390     if (netif_msg_probe(pdata))
0391         dev_dbg(dev, "sir0_regs  = %p\n", pdata->sir0_regs);
0392 
0393     pdata->sir1_regs = devm_platform_ioremap_resource(phy_pdev,
0394                               phy_memnum++);
0395     if (IS_ERR(pdata->sir1_regs)) {
0396         dev_err(dev, "sir1 ioremap failed\n");
0397         ret = PTR_ERR(pdata->sir1_regs);
0398         goto err_io;
0399     }
0400     if (netif_msg_probe(pdata))
0401         dev_dbg(dev, "sir1_regs  = %p\n", pdata->sir1_regs);
0402 
0403     /* Retrieve the MAC address */
0404     ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY,
0405                         pdata->mac_addr,
0406                         sizeof(pdata->mac_addr));
0407     if (ret || !is_valid_ether_addr(pdata->mac_addr)) {
0408         dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY);
0409         if (!ret)
0410             ret = -EINVAL;
0411         goto err_io;
0412     }
0413 
0414     /* Retrieve the PHY mode - it must be "xgmii" */
0415     ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY,
0416                       &phy_mode);
0417     if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) {
0418         dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY);
0419         if (!ret)
0420             ret = -EINVAL;
0421         goto err_io;
0422     }
0423     pdata->phy_mode = PHY_INTERFACE_MODE_XGMII;
0424 
0425     /* Check for per channel interrupt support */
0426     if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) {
0427         pdata->per_channel_irq = 1;
0428         pdata->channel_irq_mode = XGBE_IRQ_MODE_EDGE;
0429     }
0430 
0431     /* Obtain device settings unique to ACPI/OF */
0432     if (pdata->use_acpi)
0433         ret = xgbe_acpi_support(pdata);
0434     else
0435         ret = xgbe_of_support(pdata);
0436     if (ret)
0437         goto err_io;
0438 
0439     /* Set the DMA coherency values */
0440     attr = device_get_dma_attr(dev);
0441     if (attr == DEV_DMA_NOT_SUPPORTED) {
0442         dev_err(dev, "DMA is not supported");
0443         ret = -ENODEV;
0444         goto err_io;
0445     }
0446     pdata->coherent = (attr == DEV_DMA_COHERENT);
0447     if (pdata->coherent) {
0448         pdata->arcr = XGBE_DMA_OS_ARCR;
0449         pdata->awcr = XGBE_DMA_OS_AWCR;
0450     } else {
0451         pdata->arcr = XGBE_DMA_SYS_ARCR;
0452         pdata->awcr = XGBE_DMA_SYS_AWCR;
0453     }
0454 
0455     /* Set the maximum fifo amounts */
0456     pdata->tx_max_fifo_size = pdata->vdata->tx_max_fifo_size;
0457     pdata->rx_max_fifo_size = pdata->vdata->rx_max_fifo_size;
0458 
0459     /* Set the hardware channel and queue counts */
0460     xgbe_set_counts(pdata);
0461 
0462     /* Always have XGMAC and XPCS (auto-negotiation) interrupts */
0463     pdata->irq_count = 2;
0464 
0465     /* Get the device interrupt */
0466     ret = platform_get_irq(pdev, 0);
0467     if (ret < 0)
0468         goto err_io;
0469     pdata->dev_irq = ret;
0470 
0471     /* Get the per channel DMA interrupts */
0472     if (pdata->per_channel_irq) {
0473         unsigned int i, max = ARRAY_SIZE(pdata->channel_irq);
0474 
0475         for (i = 0; (i < max) && (dma_irqnum < dma_irqend); i++) {
0476             ret = platform_get_irq(pdata->platdev, dma_irqnum++);
0477             if (ret < 0)
0478                 goto err_io;
0479 
0480             pdata->channel_irq[i] = ret;
0481         }
0482 
0483         pdata->channel_irq_count = max;
0484 
0485         pdata->irq_count += max;
0486     }
0487 
0488     /* Get the auto-negotiation interrupt */
0489     ret = platform_get_irq(phy_pdev, phy_irqnum++);
0490     if (ret < 0)
0491         goto err_io;
0492     pdata->an_irq = ret;
0493 
0494     /* Configure the netdev resource */
0495     ret = xgbe_config_netdev(pdata);
0496     if (ret)
0497         goto err_io;
0498 
0499     netdev_notice(pdata->netdev, "net device enabled\n");
0500 
0501     return 0;
0502 
0503 err_io:
0504     platform_device_put(phy_pdev);
0505 
0506 err_phydev:
0507     xgbe_free_pdata(pdata);
0508 
0509 err_alloc:
0510     dev_notice(dev, "net device not enabled\n");
0511 
0512     return ret;
0513 }
0514 
0515 static int xgbe_platform_remove(struct platform_device *pdev)
0516 {
0517     struct xgbe_prv_data *pdata = platform_get_drvdata(pdev);
0518 
0519     xgbe_deconfig_netdev(pdata);
0520 
0521     platform_device_put(pdata->phy_platdev);
0522 
0523     xgbe_free_pdata(pdata);
0524 
0525     return 0;
0526 }
0527 
0528 #ifdef CONFIG_PM_SLEEP
0529 static int xgbe_platform_suspend(struct device *dev)
0530 {
0531     struct xgbe_prv_data *pdata = dev_get_drvdata(dev);
0532     struct net_device *netdev = pdata->netdev;
0533     int ret = 0;
0534 
0535     DBGPR("-->xgbe_suspend\n");
0536 
0537     if (netif_running(netdev))
0538         ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
0539 
0540     pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
0541     pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
0542     XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
0543 
0544     DBGPR("<--xgbe_suspend\n");
0545 
0546     return ret;
0547 }
0548 
0549 static int xgbe_platform_resume(struct device *dev)
0550 {
0551     struct xgbe_prv_data *pdata = dev_get_drvdata(dev);
0552     struct net_device *netdev = pdata->netdev;
0553     int ret = 0;
0554 
0555     DBGPR("-->xgbe_resume\n");
0556 
0557     pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
0558     XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
0559 
0560     if (netif_running(netdev)) {
0561         ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
0562 
0563         /* Schedule a restart in case the link or phy state changed
0564          * while we were powered down.
0565          */
0566         schedule_work(&pdata->restart_work);
0567     }
0568 
0569     DBGPR("<--xgbe_resume\n");
0570 
0571     return ret;
0572 }
0573 #endif /* CONFIG_PM_SLEEP */
0574 
0575 static const struct xgbe_version_data xgbe_v1 = {
0576     .init_function_ptrs_phy_impl    = xgbe_init_function_ptrs_phy_v1,
0577     .xpcs_access            = XGBE_XPCS_ACCESS_V1,
0578     .tx_max_fifo_size       = 81920,
0579     .rx_max_fifo_size       = 81920,
0580     .tx_tstamp_workaround       = 1,
0581 };
0582 
0583 #ifdef CONFIG_ACPI
0584 static const struct acpi_device_id xgbe_acpi_match[] = {
0585     { .id = "AMDI8001",
0586       .driver_data = (kernel_ulong_t)&xgbe_v1 },
0587     {},
0588 };
0589 
0590 MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
0591 #endif
0592 
0593 #ifdef CONFIG_OF
0594 static const struct of_device_id xgbe_of_match[] = {
0595     { .compatible = "amd,xgbe-seattle-v1a",
0596       .data = &xgbe_v1 },
0597     {},
0598 };
0599 
0600 MODULE_DEVICE_TABLE(of, xgbe_of_match);
0601 #endif
0602 
0603 static SIMPLE_DEV_PM_OPS(xgbe_platform_pm_ops,
0604              xgbe_platform_suspend, xgbe_platform_resume);
0605 
0606 static struct platform_driver xgbe_driver = {
0607     .driver = {
0608         .name = XGBE_DRV_NAME,
0609 #ifdef CONFIG_ACPI
0610         .acpi_match_table = xgbe_acpi_match,
0611 #endif
0612 #ifdef CONFIG_OF
0613         .of_match_table = xgbe_of_match,
0614 #endif
0615         .pm = &xgbe_platform_pm_ops,
0616     },
0617     .probe = xgbe_platform_probe,
0618     .remove = xgbe_platform_remove,
0619 };
0620 
0621 int xgbe_platform_init(void)
0622 {
0623     return platform_driver_register(&xgbe_driver);
0624 }
0625 
0626 void xgbe_platform_exit(void)
0627 {
0628     platform_driver_unregister(&xgbe_driver);
0629 }