18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * QorIQ 10G MDIO Controller 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2012 Freescale Semiconductor, Inc. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Authors: Andy Fleming <afleming@freescale.com> 78c2ecf20Sopenharmony_ci * Timur Tabi <timur@freescale.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public License 108c2ecf20Sopenharmony_ci * version 2. This program is licensed "as is" without any warranty of any 118c2ecf20Sopenharmony_ci * kind, whether express or implied. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/phy.h> 198c2ecf20Sopenharmony_ci#include <linux/mdio.h> 208c2ecf20Sopenharmony_ci#include <linux/of_address.h> 218c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 228c2ecf20Sopenharmony_ci#include <linux/of_mdio.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* Number of microseconds to wait for a register to respond */ 258c2ecf20Sopenharmony_ci#define TIMEOUT 1000 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct tgec_mdio_controller { 288c2ecf20Sopenharmony_ci __be32 reserved[12]; 298c2ecf20Sopenharmony_ci __be32 mdio_stat; /* MDIO configuration and status */ 308c2ecf20Sopenharmony_ci __be32 mdio_ctl; /* MDIO control */ 318c2ecf20Sopenharmony_ci __be32 mdio_data; /* MDIO data */ 328c2ecf20Sopenharmony_ci __be32 mdio_addr; /* MDIO address */ 338c2ecf20Sopenharmony_ci} __packed; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define MDIO_STAT_ENC BIT(6) 368c2ecf20Sopenharmony_ci#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8) 378c2ecf20Sopenharmony_ci#define MDIO_STAT_BSY BIT(0) 388c2ecf20Sopenharmony_ci#define MDIO_STAT_RD_ER BIT(1) 398c2ecf20Sopenharmony_ci#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f) 408c2ecf20Sopenharmony_ci#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5) 418c2ecf20Sopenharmony_ci#define MDIO_CTL_PRE_DIS BIT(10) 428c2ecf20Sopenharmony_ci#define MDIO_CTL_SCAN_EN BIT(11) 438c2ecf20Sopenharmony_ci#define MDIO_CTL_POST_INC BIT(14) 448c2ecf20Sopenharmony_ci#define MDIO_CTL_READ BIT(15) 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define MDIO_DATA(x) (x & 0xffff) 478c2ecf20Sopenharmony_ci#define MDIO_DATA_BSY BIT(31) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistruct mdio_fsl_priv { 508c2ecf20Sopenharmony_ci struct tgec_mdio_controller __iomem *mdio_base; 518c2ecf20Sopenharmony_ci bool is_little_endian; 528c2ecf20Sopenharmony_ci bool has_a009885; 538c2ecf20Sopenharmony_ci bool has_a011043; 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic u32 xgmac_read32(void __iomem *regs, 578c2ecf20Sopenharmony_ci bool is_little_endian) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci if (is_little_endian) 608c2ecf20Sopenharmony_ci return ioread32(regs); 618c2ecf20Sopenharmony_ci else 628c2ecf20Sopenharmony_ci return ioread32be(regs); 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic void xgmac_write32(u32 value, 668c2ecf20Sopenharmony_ci void __iomem *regs, 678c2ecf20Sopenharmony_ci bool is_little_endian) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci if (is_little_endian) 708c2ecf20Sopenharmony_ci iowrite32(value, regs); 718c2ecf20Sopenharmony_ci else 728c2ecf20Sopenharmony_ci iowrite32be(value, regs); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* 768c2ecf20Sopenharmony_ci * Wait until the MDIO bus is free 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_cistatic int xgmac_wait_until_free(struct device *dev, 798c2ecf20Sopenharmony_ci struct tgec_mdio_controller __iomem *regs, 808c2ecf20Sopenharmony_ci bool is_little_endian) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci unsigned int timeout; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* Wait till the bus is free */ 858c2ecf20Sopenharmony_ci timeout = TIMEOUT; 868c2ecf20Sopenharmony_ci while ((xgmac_read32(®s->mdio_stat, is_little_endian) & 878c2ecf20Sopenharmony_ci MDIO_STAT_BSY) && timeout) { 888c2ecf20Sopenharmony_ci cpu_relax(); 898c2ecf20Sopenharmony_ci timeout--; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (!timeout) { 938c2ecf20Sopenharmony_ci dev_err(dev, "timeout waiting for bus to be free\n"); 948c2ecf20Sopenharmony_ci return -ETIMEDOUT; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci return 0; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * Wait till the MDIO read or write operation is complete 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_cistatic int xgmac_wait_until_done(struct device *dev, 1048c2ecf20Sopenharmony_ci struct tgec_mdio_controller __iomem *regs, 1058c2ecf20Sopenharmony_ci bool is_little_endian) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci unsigned int timeout; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* Wait till the MDIO write is complete */ 1108c2ecf20Sopenharmony_ci timeout = TIMEOUT; 1118c2ecf20Sopenharmony_ci while ((xgmac_read32(®s->mdio_stat, is_little_endian) & 1128c2ecf20Sopenharmony_ci MDIO_STAT_BSY) && timeout) { 1138c2ecf20Sopenharmony_ci cpu_relax(); 1148c2ecf20Sopenharmony_ci timeout--; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if (!timeout) { 1188c2ecf20Sopenharmony_ci dev_err(dev, "timeout waiting for operation to complete\n"); 1198c2ecf20Sopenharmony_ci return -ETIMEDOUT; 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return 0; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* 1268c2ecf20Sopenharmony_ci * Write value to the PHY for this device to the register at regnum,waiting 1278c2ecf20Sopenharmony_ci * until the write is done before it returns. All PHY configuration has to be 1288c2ecf20Sopenharmony_ci * done through the TSEC1 MIIM regs. 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_cistatic int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; 1338c2ecf20Sopenharmony_ci struct tgec_mdio_controller __iomem *regs = priv->mdio_base; 1348c2ecf20Sopenharmony_ci uint16_t dev_addr; 1358c2ecf20Sopenharmony_ci u32 mdio_ctl, mdio_stat; 1368c2ecf20Sopenharmony_ci int ret; 1378c2ecf20Sopenharmony_ci bool endian = priv->is_little_endian; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci mdio_stat = xgmac_read32(®s->mdio_stat, endian); 1408c2ecf20Sopenharmony_ci if (regnum & MII_ADDR_C45) { 1418c2ecf20Sopenharmony_ci /* Clause 45 (ie 10G) */ 1428c2ecf20Sopenharmony_ci dev_addr = (regnum >> 16) & 0x1f; 1438c2ecf20Sopenharmony_ci mdio_stat |= MDIO_STAT_ENC; 1448c2ecf20Sopenharmony_ci } else { 1458c2ecf20Sopenharmony_ci /* Clause 22 (ie 1G) */ 1468c2ecf20Sopenharmony_ci dev_addr = regnum & 0x1f; 1478c2ecf20Sopenharmony_ci mdio_stat &= ~MDIO_STAT_ENC; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci xgmac_write32(mdio_stat, ®s->mdio_stat, endian); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci ret = xgmac_wait_until_free(&bus->dev, regs, endian); 1538c2ecf20Sopenharmony_ci if (ret) 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Set the port and dev addr */ 1578c2ecf20Sopenharmony_ci mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 1588c2ecf20Sopenharmony_ci xgmac_write32(mdio_ctl, ®s->mdio_ctl, endian); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Set the register address */ 1618c2ecf20Sopenharmony_ci if (regnum & MII_ADDR_C45) { 1628c2ecf20Sopenharmony_ci xgmac_write32(regnum & 0xffff, ®s->mdio_addr, endian); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci ret = xgmac_wait_until_free(&bus->dev, regs, endian); 1658c2ecf20Sopenharmony_ci if (ret) 1668c2ecf20Sopenharmony_ci return ret; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Write the value to the register */ 1708c2ecf20Sopenharmony_ci xgmac_write32(MDIO_DATA(value), ®s->mdio_data, endian); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci ret = xgmac_wait_until_done(&bus->dev, regs, endian); 1738c2ecf20Sopenharmony_ci if (ret) 1748c2ecf20Sopenharmony_ci return ret; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci return 0; 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci/* 1808c2ecf20Sopenharmony_ci * Reads from register regnum in the PHY for device dev, returning the value. 1818c2ecf20Sopenharmony_ci * Clears miimcom first. All PHY configuration has to be done through the 1828c2ecf20Sopenharmony_ci * TSEC1 MIIM regs. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_cistatic int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; 1878c2ecf20Sopenharmony_ci struct tgec_mdio_controller __iomem *regs = priv->mdio_base; 1888c2ecf20Sopenharmony_ci unsigned long flags; 1898c2ecf20Sopenharmony_ci uint16_t dev_addr; 1908c2ecf20Sopenharmony_ci uint32_t mdio_stat; 1918c2ecf20Sopenharmony_ci uint32_t mdio_ctl; 1928c2ecf20Sopenharmony_ci int ret; 1938c2ecf20Sopenharmony_ci bool endian = priv->is_little_endian; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci mdio_stat = xgmac_read32(®s->mdio_stat, endian); 1968c2ecf20Sopenharmony_ci if (regnum & MII_ADDR_C45) { 1978c2ecf20Sopenharmony_ci dev_addr = (regnum >> 16) & 0x1f; 1988c2ecf20Sopenharmony_ci mdio_stat |= MDIO_STAT_ENC; 1998c2ecf20Sopenharmony_ci } else { 2008c2ecf20Sopenharmony_ci dev_addr = regnum & 0x1f; 2018c2ecf20Sopenharmony_ci mdio_stat &= ~MDIO_STAT_ENC; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci xgmac_write32(mdio_stat, ®s->mdio_stat, endian); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci ret = xgmac_wait_until_free(&bus->dev, regs, endian); 2078c2ecf20Sopenharmony_ci if (ret) 2088c2ecf20Sopenharmony_ci return ret; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Set the Port and Device Addrs */ 2118c2ecf20Sopenharmony_ci mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 2128c2ecf20Sopenharmony_ci xgmac_write32(mdio_ctl, ®s->mdio_ctl, endian); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci /* Set the register address */ 2158c2ecf20Sopenharmony_ci if (regnum & MII_ADDR_C45) { 2168c2ecf20Sopenharmony_ci xgmac_write32(regnum & 0xffff, ®s->mdio_addr, endian); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci ret = xgmac_wait_until_free(&bus->dev, regs, endian); 2198c2ecf20Sopenharmony_ci if (ret) 2208c2ecf20Sopenharmony_ci return ret; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (priv->has_a009885) 2248c2ecf20Sopenharmony_ci /* Once the operation completes, i.e. MDIO_STAT_BSY clears, we 2258c2ecf20Sopenharmony_ci * must read back the data register within 16 MDC cycles. 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ci local_irq_save(flags); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* Initiate the read */ 2308c2ecf20Sopenharmony_ci xgmac_write32(mdio_ctl | MDIO_CTL_READ, ®s->mdio_ctl, endian); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci ret = xgmac_wait_until_done(&bus->dev, regs, endian); 2338c2ecf20Sopenharmony_ci if (ret) 2348c2ecf20Sopenharmony_ci goto irq_restore; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* Return all Fs if nothing was there */ 2378c2ecf20Sopenharmony_ci if ((xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) && 2388c2ecf20Sopenharmony_ci !priv->has_a011043) { 2398c2ecf20Sopenharmony_ci dev_dbg(&bus->dev, 2408c2ecf20Sopenharmony_ci "Error while reading PHY%d reg at %d.%hhu\n", 2418c2ecf20Sopenharmony_ci phy_id, dev_addr, regnum); 2428c2ecf20Sopenharmony_ci ret = 0xffff; 2438c2ecf20Sopenharmony_ci } else { 2448c2ecf20Sopenharmony_ci ret = xgmac_read32(®s->mdio_data, endian) & 0xffff; 2458c2ecf20Sopenharmony_ci dev_dbg(&bus->dev, "read %04x\n", ret); 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciirq_restore: 2498c2ecf20Sopenharmony_ci if (priv->has_a009885) 2508c2ecf20Sopenharmony_ci local_irq_restore(flags); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci return ret; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic int xgmac_mdio_probe(struct platform_device *pdev) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 2588c2ecf20Sopenharmony_ci struct mii_bus *bus; 2598c2ecf20Sopenharmony_ci struct resource *res; 2608c2ecf20Sopenharmony_ci struct mdio_fsl_priv *priv; 2618c2ecf20Sopenharmony_ci int ret; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* In DPAA-1, MDIO is one of the many FMan sub-devices. The FMan 2648c2ecf20Sopenharmony_ci * defines a register space that spans a large area, covering all the 2658c2ecf20Sopenharmony_ci * subdevice areas. Therefore, MDIO cannot claim exclusive access to 2668c2ecf20Sopenharmony_ci * this register area. 2678c2ecf20Sopenharmony_ci */ 2688c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2698c2ecf20Sopenharmony_ci if (!res) { 2708c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "could not obtain address\n"); 2718c2ecf20Sopenharmony_ci return -EINVAL; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci bus = mdiobus_alloc_size(sizeof(struct mdio_fsl_priv)); 2758c2ecf20Sopenharmony_ci if (!bus) 2768c2ecf20Sopenharmony_ci return -ENOMEM; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci bus->name = "Freescale XGMAC MDIO Bus"; 2798c2ecf20Sopenharmony_ci bus->read = xgmac_mdio_read; 2808c2ecf20Sopenharmony_ci bus->write = xgmac_mdio_write; 2818c2ecf20Sopenharmony_ci bus->parent = &pdev->dev; 2828c2ecf20Sopenharmony_ci bus->probe_capabilities = MDIOBUS_C22_C45; 2838c2ecf20Sopenharmony_ci snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res->start); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* Set the PHY base address */ 2868c2ecf20Sopenharmony_ci priv = bus->priv; 2878c2ecf20Sopenharmony_ci priv->mdio_base = ioremap(res->start, resource_size(res)); 2888c2ecf20Sopenharmony_ci if (!priv->mdio_base) { 2898c2ecf20Sopenharmony_ci ret = -ENOMEM; 2908c2ecf20Sopenharmony_ci goto err_ioremap; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci priv->is_little_endian = device_property_read_bool(&pdev->dev, 2948c2ecf20Sopenharmony_ci "little-endian"); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci priv->has_a009885 = device_property_read_bool(&pdev->dev, 2978c2ecf20Sopenharmony_ci "fsl,erratum-a009885"); 2988c2ecf20Sopenharmony_ci priv->has_a011043 = device_property_read_bool(&pdev->dev, 2998c2ecf20Sopenharmony_ci "fsl,erratum-a011043"); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci ret = of_mdiobus_register(bus, np); 3028c2ecf20Sopenharmony_ci if (ret) { 3038c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "cannot register MDIO bus\n"); 3048c2ecf20Sopenharmony_ci goto err_registration; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, bus); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return 0; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cierr_registration: 3128c2ecf20Sopenharmony_ci iounmap(priv->mdio_base); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cierr_ioremap: 3158c2ecf20Sopenharmony_ci mdiobus_free(bus); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci return ret; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int xgmac_mdio_remove(struct platform_device *pdev) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct mii_bus *bus = platform_get_drvdata(pdev); 3238c2ecf20Sopenharmony_ci struct mdio_fsl_priv *priv = bus->priv; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci mdiobus_unregister(bus); 3268c2ecf20Sopenharmony_ci iounmap(priv->mdio_base); 3278c2ecf20Sopenharmony_ci mdiobus_free(bus); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci return 0; 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic const struct of_device_id xgmac_mdio_match[] = { 3338c2ecf20Sopenharmony_ci { 3348c2ecf20Sopenharmony_ci .compatible = "fsl,fman-xmdio", 3358c2ecf20Sopenharmony_ci }, 3368c2ecf20Sopenharmony_ci { 3378c2ecf20Sopenharmony_ci .compatible = "fsl,fman-memac-mdio", 3388c2ecf20Sopenharmony_ci }, 3398c2ecf20Sopenharmony_ci {}, 3408c2ecf20Sopenharmony_ci}; 3418c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, xgmac_mdio_match); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic const struct acpi_device_id xgmac_acpi_match[] = { 3448c2ecf20Sopenharmony_ci { "NXP0006" }, 3458c2ecf20Sopenharmony_ci { } 3468c2ecf20Sopenharmony_ci}; 3478c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, xgmac_acpi_match); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic struct platform_driver xgmac_mdio_driver = { 3508c2ecf20Sopenharmony_ci .driver = { 3518c2ecf20Sopenharmony_ci .name = "fsl-fman_xmdio", 3528c2ecf20Sopenharmony_ci .of_match_table = xgmac_mdio_match, 3538c2ecf20Sopenharmony_ci .acpi_match_table = xgmac_acpi_match, 3548c2ecf20Sopenharmony_ci }, 3558c2ecf20Sopenharmony_ci .probe = xgmac_mdio_probe, 3568c2ecf20Sopenharmony_ci .remove = xgmac_mdio_remove, 3578c2ecf20Sopenharmony_ci}; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cimodule_platform_driver(xgmac_mdio_driver); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Freescale QorIQ 10G MDIO Controller"); 3628c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 363