19f35a734STimur Tabi /* 29f35a734STimur Tabi * QorIQ 10G MDIO Controller 39f35a734STimur Tabi * 49f35a734STimur Tabi * Copyright 2012 Freescale Semiconductor, Inc. 515e7064eSCalvin Johnson * Copyright 2021 NXP 69f35a734STimur Tabi * 79f35a734STimur Tabi * Authors: Andy Fleming <afleming@freescale.com> 89f35a734STimur Tabi * Timur Tabi <timur@freescale.com> 99f35a734STimur Tabi * 109f35a734STimur Tabi * This file is licensed under the terms of the GNU General Public License 119f35a734STimur Tabi * version 2. This program is licensed "as is" without any warranty of any 129f35a734STimur Tabi * kind, whether express or implied. 139f35a734STimur Tabi */ 149f35a734STimur Tabi 1515e7064eSCalvin Johnson #include <linux/acpi.h> 16ac53c264SMarcin Wojtas #include <linux/acpi_mdio.h> 17*dd8f467eSTobias Waldekranz #include <linux/clk.h> 189f35a734STimur Tabi #include <linux/interrupt.h> 1915e7064eSCalvin Johnson #include <linux/kernel.h> 209f35a734STimur Tabi #include <linux/mdio.h> 2115e7064eSCalvin Johnson #include <linux/module.h> 225af50730SRob Herring #include <linux/of_address.h> 239f35a734STimur Tabi #include <linux/of_mdio.h> 2415e7064eSCalvin Johnson #include <linux/of_platform.h> 2515e7064eSCalvin Johnson #include <linux/phy.h> 2615e7064eSCalvin Johnson #include <linux/slab.h> 279f35a734STimur Tabi 289f35a734STimur Tabi /* Number of microseconds to wait for a register to respond */ 299f35a734STimur Tabi #define TIMEOUT 1000 309f35a734STimur Tabi 319f35a734STimur Tabi struct tgec_mdio_controller { 329f35a734STimur Tabi __be32 reserved[12]; 339f35a734STimur Tabi __be32 mdio_stat; /* MDIO configuration and status */ 349f35a734STimur Tabi __be32 mdio_ctl; /* MDIO control */ 359f35a734STimur Tabi __be32 mdio_data; /* MDIO data */ 369f35a734STimur Tabi __be32 mdio_addr; /* MDIO address */ 379f35a734STimur Tabi } __packed; 389f35a734STimur Tabi 391fcf77c8SAndy Fleming #define MDIO_STAT_ENC BIT(6) 40*dd8f467eSTobias Waldekranz #define MDIO_STAT_CLKDIV(x) (((x) & 0x1ff) << 7) 4149ff2d3fSShaohui Xie #define MDIO_STAT_BSY BIT(0) 4249ff2d3fSShaohui Xie #define MDIO_STAT_RD_ER BIT(1) 43909bea73STobias Waldekranz #define MDIO_STAT_PRE_DIS BIT(5) 449f35a734STimur Tabi #define MDIO_CTL_DEV_ADDR(x) (x & 0x1f) 459f35a734STimur Tabi #define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5) 4649ff2d3fSShaohui Xie #define MDIO_CTL_PRE_DIS BIT(10) 4749ff2d3fSShaohui Xie #define MDIO_CTL_SCAN_EN BIT(11) 4849ff2d3fSShaohui Xie #define MDIO_CTL_POST_INC BIT(14) 4949ff2d3fSShaohui Xie #define MDIO_CTL_READ BIT(15) 509f35a734STimur Tabi 519f35a734STimur Tabi #define MDIO_DATA(x) (x & 0xffff) 529f35a734STimur Tabi 5373ee5442SShaohui Xie struct mdio_fsl_priv { 5473ee5442SShaohui Xie struct tgec_mdio_controller __iomem *mdio_base; 55*dd8f467eSTobias Waldekranz struct clk *enet_clk; 56*dd8f467eSTobias Waldekranz u32 mdc_freq; 5773ee5442SShaohui Xie bool is_little_endian; 586198c722STobias Waldekranz bool has_a009885; 591d3ca681SMadalin Bucur bool has_a011043; 6073ee5442SShaohui Xie }; 6173ee5442SShaohui Xie 6273ee5442SShaohui Xie static u32 xgmac_read32(void __iomem *regs, 6373ee5442SShaohui Xie bool is_little_endian) 6473ee5442SShaohui Xie { 6573ee5442SShaohui Xie if (is_little_endian) 6673ee5442SShaohui Xie return ioread32(regs); 6773ee5442SShaohui Xie else 6873ee5442SShaohui Xie return ioread32be(regs); 6973ee5442SShaohui Xie } 7073ee5442SShaohui Xie 7173ee5442SShaohui Xie static void xgmac_write32(u32 value, 7273ee5442SShaohui Xie void __iomem *regs, 7373ee5442SShaohui Xie bool is_little_endian) 7473ee5442SShaohui Xie { 7573ee5442SShaohui Xie if (is_little_endian) 7673ee5442SShaohui Xie iowrite32(value, regs); 7773ee5442SShaohui Xie else 7873ee5442SShaohui Xie iowrite32be(value, regs); 7973ee5442SShaohui Xie } 8073ee5442SShaohui Xie 819f35a734STimur Tabi /* 82c1543d37SMadalin Bucur * Wait until the MDIO bus is free 839f35a734STimur Tabi */ 849f35a734STimur Tabi static int xgmac_wait_until_free(struct device *dev, 8573ee5442SShaohui Xie struct tgec_mdio_controller __iomem *regs, 8673ee5442SShaohui Xie bool is_little_endian) 879f35a734STimur Tabi { 8822f6bba7SShaohui Xie unsigned int timeout; 899f35a734STimur Tabi 909f35a734STimur Tabi /* Wait till the bus is free */ 9122f6bba7SShaohui Xie timeout = TIMEOUT; 9273ee5442SShaohui Xie while ((xgmac_read32(®s->mdio_stat, is_little_endian) & 9373ee5442SShaohui Xie MDIO_STAT_BSY) && timeout) { 9422f6bba7SShaohui Xie cpu_relax(); 9522f6bba7SShaohui Xie timeout--; 9622f6bba7SShaohui Xie } 9722f6bba7SShaohui Xie 9822f6bba7SShaohui Xie if (!timeout) { 999f35a734STimur Tabi dev_err(dev, "timeout waiting for bus to be free\n"); 1009f35a734STimur Tabi return -ETIMEDOUT; 1019f35a734STimur Tabi } 1029f35a734STimur Tabi 1039f35a734STimur Tabi return 0; 1049f35a734STimur Tabi } 1059f35a734STimur Tabi 1069f35a734STimur Tabi /* 1079f35a734STimur Tabi * Wait till the MDIO read or write operation is complete 1089f35a734STimur Tabi */ 1099f35a734STimur Tabi static int xgmac_wait_until_done(struct device *dev, 11073ee5442SShaohui Xie struct tgec_mdio_controller __iomem *regs, 11173ee5442SShaohui Xie bool is_little_endian) 1129f35a734STimur Tabi { 11322f6bba7SShaohui Xie unsigned int timeout; 1149f35a734STimur Tabi 1159f35a734STimur Tabi /* Wait till the MDIO write is complete */ 11622f6bba7SShaohui Xie timeout = TIMEOUT; 11773ee5442SShaohui Xie while ((xgmac_read32(®s->mdio_stat, is_little_endian) & 11873ee5442SShaohui Xie MDIO_STAT_BSY) && timeout) { 11922f6bba7SShaohui Xie cpu_relax(); 12022f6bba7SShaohui Xie timeout--; 12122f6bba7SShaohui Xie } 12222f6bba7SShaohui Xie 12322f6bba7SShaohui Xie if (!timeout) { 1249f35a734STimur Tabi dev_err(dev, "timeout waiting for operation to complete\n"); 1259f35a734STimur Tabi return -ETIMEDOUT; 1269f35a734STimur Tabi } 1279f35a734STimur Tabi 1289f35a734STimur Tabi return 0; 1299f35a734STimur Tabi } 1309f35a734STimur Tabi 1319f35a734STimur Tabi /* 1329f35a734STimur Tabi * Write value to the PHY for this device to the register at regnum,waiting 1339f35a734STimur Tabi * until the write is done before it returns. All PHY configuration has to be 1349f35a734STimur Tabi * done through the TSEC1 MIIM regs. 1359f35a734STimur Tabi */ 1369f35a734STimur Tabi static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value) 1379f35a734STimur Tabi { 13873ee5442SShaohui Xie struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; 13973ee5442SShaohui Xie struct tgec_mdio_controller __iomem *regs = priv->mdio_base; 1401fcf77c8SAndy Fleming uint16_t dev_addr; 1411fcf77c8SAndy Fleming u32 mdio_ctl, mdio_stat; 1429f35a734STimur Tabi int ret; 14373ee5442SShaohui Xie bool endian = priv->is_little_endian; 1449f35a734STimur Tabi 14573ee5442SShaohui Xie mdio_stat = xgmac_read32(®s->mdio_stat, endian); 1461fcf77c8SAndy Fleming if (regnum & MII_ADDR_C45) { 1471fcf77c8SAndy Fleming /* Clause 45 (ie 10G) */ 1481fcf77c8SAndy Fleming dev_addr = (regnum >> 16) & 0x1f; 1491fcf77c8SAndy Fleming mdio_stat |= MDIO_STAT_ENC; 1501fcf77c8SAndy Fleming } else { 1511fcf77c8SAndy Fleming /* Clause 22 (ie 1G) */ 1521fcf77c8SAndy Fleming dev_addr = regnum & 0x1f; 1531fcf77c8SAndy Fleming mdio_stat &= ~MDIO_STAT_ENC; 1541fcf77c8SAndy Fleming } 1551fcf77c8SAndy Fleming 15673ee5442SShaohui Xie xgmac_write32(mdio_stat, ®s->mdio_stat, endian); 1571fcf77c8SAndy Fleming 15873ee5442SShaohui Xie ret = xgmac_wait_until_free(&bus->dev, regs, endian); 1591fcf77c8SAndy Fleming if (ret) 1601fcf77c8SAndy Fleming return ret; 1611fcf77c8SAndy Fleming 1629f35a734STimur Tabi /* Set the port and dev addr */ 1631fcf77c8SAndy Fleming mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 16473ee5442SShaohui Xie xgmac_write32(mdio_ctl, ®s->mdio_ctl, endian); 1659f35a734STimur Tabi 1669f35a734STimur Tabi /* Set the register address */ 1671fcf77c8SAndy Fleming if (regnum & MII_ADDR_C45) { 16873ee5442SShaohui Xie xgmac_write32(regnum & 0xffff, ®s->mdio_addr, endian); 1699f35a734STimur Tabi 17073ee5442SShaohui Xie ret = xgmac_wait_until_free(&bus->dev, regs, endian); 1719f35a734STimur Tabi if (ret) 1729f35a734STimur Tabi return ret; 1731fcf77c8SAndy Fleming } 1749f35a734STimur Tabi 1759f35a734STimur Tabi /* Write the value to the register */ 17673ee5442SShaohui Xie xgmac_write32(MDIO_DATA(value), ®s->mdio_data, endian); 1779f35a734STimur Tabi 17873ee5442SShaohui Xie ret = xgmac_wait_until_done(&bus->dev, regs, endian); 1799f35a734STimur Tabi if (ret) 1809f35a734STimur Tabi return ret; 1819f35a734STimur Tabi 1829f35a734STimur Tabi return 0; 1839f35a734STimur Tabi } 1849f35a734STimur Tabi 1859f35a734STimur Tabi /* 1869f35a734STimur Tabi * Reads from register regnum in the PHY for device dev, returning the value. 1879f35a734STimur Tabi * Clears miimcom first. All PHY configuration has to be done through the 1889f35a734STimur Tabi * TSEC1 MIIM regs. 1899f35a734STimur Tabi */ 1909f35a734STimur Tabi static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum) 1919f35a734STimur Tabi { 19273ee5442SShaohui Xie struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; 19373ee5442SShaohui Xie struct tgec_mdio_controller __iomem *regs = priv->mdio_base; 1946198c722STobias Waldekranz unsigned long flags; 1951fcf77c8SAndy Fleming uint16_t dev_addr; 1961fcf77c8SAndy Fleming uint32_t mdio_stat; 1979f35a734STimur Tabi uint32_t mdio_ctl; 1989f35a734STimur Tabi int ret; 19973ee5442SShaohui Xie bool endian = priv->is_little_endian; 2009f35a734STimur Tabi 20173ee5442SShaohui Xie mdio_stat = xgmac_read32(®s->mdio_stat, endian); 2021fcf77c8SAndy Fleming if (regnum & MII_ADDR_C45) { 2031fcf77c8SAndy Fleming dev_addr = (regnum >> 16) & 0x1f; 2041fcf77c8SAndy Fleming mdio_stat |= MDIO_STAT_ENC; 2051fcf77c8SAndy Fleming } else { 2061fcf77c8SAndy Fleming dev_addr = regnum & 0x1f; 207e54bfe9dSShaohui Xie mdio_stat &= ~MDIO_STAT_ENC; 2081fcf77c8SAndy Fleming } 2091fcf77c8SAndy Fleming 21073ee5442SShaohui Xie xgmac_write32(mdio_stat, ®s->mdio_stat, endian); 2111fcf77c8SAndy Fleming 21273ee5442SShaohui Xie ret = xgmac_wait_until_free(&bus->dev, regs, endian); 2131fcf77c8SAndy Fleming if (ret) 2141fcf77c8SAndy Fleming return ret; 2151fcf77c8SAndy Fleming 2169f35a734STimur Tabi /* Set the Port and Device Addrs */ 2179f35a734STimur Tabi mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); 21873ee5442SShaohui Xie xgmac_write32(mdio_ctl, ®s->mdio_ctl, endian); 2199f35a734STimur Tabi 2209f35a734STimur Tabi /* Set the register address */ 2211fcf77c8SAndy Fleming if (regnum & MII_ADDR_C45) { 22273ee5442SShaohui Xie xgmac_write32(regnum & 0xffff, ®s->mdio_addr, endian); 2239f35a734STimur Tabi 22473ee5442SShaohui Xie ret = xgmac_wait_until_free(&bus->dev, regs, endian); 2259f35a734STimur Tabi if (ret) 2269f35a734STimur Tabi return ret; 2271fcf77c8SAndy Fleming } 2289f35a734STimur Tabi 2296198c722STobias Waldekranz if (priv->has_a009885) 2306198c722STobias Waldekranz /* Once the operation completes, i.e. MDIO_STAT_BSY clears, we 2316198c722STobias Waldekranz * must read back the data register within 16 MDC cycles. 2326198c722STobias Waldekranz */ 2336198c722STobias Waldekranz local_irq_save(flags); 2346198c722STobias Waldekranz 2359f35a734STimur Tabi /* Initiate the read */ 23673ee5442SShaohui Xie xgmac_write32(mdio_ctl | MDIO_CTL_READ, ®s->mdio_ctl, endian); 2379f35a734STimur Tabi 23873ee5442SShaohui Xie ret = xgmac_wait_until_done(&bus->dev, regs, endian); 2399f35a734STimur Tabi if (ret) 2406198c722STobias Waldekranz goto irq_restore; 2419f35a734STimur Tabi 2429f35a734STimur Tabi /* Return all Fs if nothing was there */ 2431d3ca681SMadalin Bucur if ((xgmac_read32(®s->mdio_stat, endian) & MDIO_STAT_RD_ER) && 2441d3ca681SMadalin Bucur !priv->has_a011043) { 2451ec8e748SJamie Iles dev_dbg(&bus->dev, 2469e6492ecSShruti Kanetkar "Error while reading PHY%d reg at %d.%hhu\n", 24755fd3641SShruti Kanetkar phy_id, dev_addr, regnum); 2486198c722STobias Waldekranz ret = 0xffff; 2496198c722STobias Waldekranz } else { 2506198c722STobias Waldekranz ret = xgmac_read32(®s->mdio_data, endian) & 0xffff; 2516198c722STobias Waldekranz dev_dbg(&bus->dev, "read %04x\n", ret); 2529f35a734STimur Tabi } 2539f35a734STimur Tabi 2546198c722STobias Waldekranz irq_restore: 2556198c722STobias Waldekranz if (priv->has_a009885) 2566198c722STobias Waldekranz local_irq_restore(flags); 2579f35a734STimur Tabi 2586198c722STobias Waldekranz return ret; 2599f35a734STimur Tabi } 2609f35a734STimur Tabi 261*dd8f467eSTobias Waldekranz static int xgmac_mdio_set_mdc_freq(struct mii_bus *bus) 262*dd8f467eSTobias Waldekranz { 263*dd8f467eSTobias Waldekranz struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; 264*dd8f467eSTobias Waldekranz struct tgec_mdio_controller __iomem *regs = priv->mdio_base; 265*dd8f467eSTobias Waldekranz struct device *dev = bus->parent; 266*dd8f467eSTobias Waldekranz u32 mdio_stat, div; 267*dd8f467eSTobias Waldekranz 268*dd8f467eSTobias Waldekranz if (device_property_read_u32(dev, "clock-frequency", &priv->mdc_freq)) 269*dd8f467eSTobias Waldekranz return 0; 270*dd8f467eSTobias Waldekranz 271*dd8f467eSTobias Waldekranz priv->enet_clk = devm_clk_get(dev, NULL); 272*dd8f467eSTobias Waldekranz if (IS_ERR(priv->enet_clk)) { 273*dd8f467eSTobias Waldekranz dev_err(dev, "Input clock unknown, not changing MDC frequency"); 274*dd8f467eSTobias Waldekranz return PTR_ERR(priv->enet_clk); 275*dd8f467eSTobias Waldekranz } 276*dd8f467eSTobias Waldekranz 277*dd8f467eSTobias Waldekranz div = ((clk_get_rate(priv->enet_clk) / priv->mdc_freq) - 1) / 2; 278*dd8f467eSTobias Waldekranz if (div < 5 || div > 0x1ff) { 279*dd8f467eSTobias Waldekranz dev_err(dev, "Requested MDC frequecy is out of range, ignoring"); 280*dd8f467eSTobias Waldekranz return -EINVAL; 281*dd8f467eSTobias Waldekranz } 282*dd8f467eSTobias Waldekranz 283*dd8f467eSTobias Waldekranz mdio_stat = xgmac_read32(®s->mdio_stat, priv->is_little_endian); 284*dd8f467eSTobias Waldekranz mdio_stat &= ~MDIO_STAT_CLKDIV(0x1ff); 285*dd8f467eSTobias Waldekranz mdio_stat |= MDIO_STAT_CLKDIV(div); 286*dd8f467eSTobias Waldekranz xgmac_write32(mdio_stat, ®s->mdio_stat, priv->is_little_endian); 287*dd8f467eSTobias Waldekranz return 0; 288*dd8f467eSTobias Waldekranz } 289*dd8f467eSTobias Waldekranz 290909bea73STobias Waldekranz static void xgmac_mdio_set_suppress_preamble(struct mii_bus *bus) 291909bea73STobias Waldekranz { 292909bea73STobias Waldekranz struct mdio_fsl_priv *priv = (struct mdio_fsl_priv *)bus->priv; 293909bea73STobias Waldekranz struct tgec_mdio_controller __iomem *regs = priv->mdio_base; 294909bea73STobias Waldekranz struct device *dev = bus->parent; 295909bea73STobias Waldekranz u32 mdio_stat; 296909bea73STobias Waldekranz 297909bea73STobias Waldekranz if (!device_property_read_bool(dev, "suppress-preamble")) 298909bea73STobias Waldekranz return; 299909bea73STobias Waldekranz 300909bea73STobias Waldekranz mdio_stat = xgmac_read32(®s->mdio_stat, priv->is_little_endian); 301909bea73STobias Waldekranz mdio_stat |= MDIO_STAT_PRE_DIS; 302909bea73STobias Waldekranz xgmac_write32(mdio_stat, ®s->mdio_stat, priv->is_little_endian); 303909bea73STobias Waldekranz } 304909bea73STobias Waldekranz 30533897cc8SBill Pemberton static int xgmac_mdio_probe(struct platform_device *pdev) 3069f35a734STimur Tabi { 307ac53c264SMarcin Wojtas struct fwnode_handle *fwnode; 30873ee5442SShaohui Xie struct mdio_fsl_priv *priv; 30915e7064eSCalvin Johnson struct resource *res; 31015e7064eSCalvin Johnson struct mii_bus *bus; 3119f35a734STimur Tabi int ret; 3129f35a734STimur Tabi 313229f4bb4SCalvin Johnson /* In DPAA-1, MDIO is one of the many FMan sub-devices. The FMan 314229f4bb4SCalvin Johnson * defines a register space that spans a large area, covering all the 315229f4bb4SCalvin Johnson * subdevice areas. Therefore, MDIO cannot claim exclusive access to 316229f4bb4SCalvin Johnson * this register area. 317229f4bb4SCalvin Johnson */ 318229f4bb4SCalvin Johnson res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 319229f4bb4SCalvin Johnson if (!res) { 3209f35a734STimur Tabi dev_err(&pdev->dev, "could not obtain address\n"); 321229f4bb4SCalvin Johnson return -EINVAL; 3229f35a734STimur Tabi } 3239f35a734STimur Tabi 3241d14eb15STobias Waldekranz bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(struct mdio_fsl_priv)); 3259f35a734STimur Tabi if (!bus) 3269f35a734STimur Tabi return -ENOMEM; 3279f35a734STimur Tabi 3289f35a734STimur Tabi bus->name = "Freescale XGMAC MDIO Bus"; 3299f35a734STimur Tabi bus->read = xgmac_mdio_read; 3309f35a734STimur Tabi bus->write = xgmac_mdio_write; 3319f35a734STimur Tabi bus->parent = &pdev->dev; 3320f183fd1SJeremy Linton bus->probe_capabilities = MDIOBUS_C22_C45; 333229f4bb4SCalvin Johnson snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res->start); 3349f35a734STimur Tabi 33573ee5442SShaohui Xie priv = bus->priv; 3361d14eb15STobias Waldekranz priv->mdio_base = devm_ioremap(&pdev->dev, res->start, 3371d14eb15STobias Waldekranz resource_size(res)); 3381d14eb15STobias Waldekranz if (IS_ERR(priv->mdio_base)) 3391d14eb15STobias Waldekranz return PTR_ERR(priv->mdio_base); 3409f35a734STimur Tabi 34115e7064eSCalvin Johnson /* For both ACPI and DT cases, endianness of MDIO controller 34215e7064eSCalvin Johnson * needs to be specified using "little-endian" property. 34315e7064eSCalvin Johnson */ 344229f4bb4SCalvin Johnson priv->is_little_endian = device_property_read_bool(&pdev->dev, 34507bf2e11SJulia Lawall "little-endian"); 34673ee5442SShaohui Xie 3476198c722STobias Waldekranz priv->has_a009885 = device_property_read_bool(&pdev->dev, 3486198c722STobias Waldekranz "fsl,erratum-a009885"); 349229f4bb4SCalvin Johnson priv->has_a011043 = device_property_read_bool(&pdev->dev, 3501d3ca681SMadalin Bucur "fsl,erratum-a011043"); 3511d3ca681SMadalin Bucur 352909bea73STobias Waldekranz xgmac_mdio_set_suppress_preamble(bus); 353909bea73STobias Waldekranz 354*dd8f467eSTobias Waldekranz ret = xgmac_mdio_set_mdc_freq(bus); 355*dd8f467eSTobias Waldekranz if (ret) 356*dd8f467eSTobias Waldekranz return ret; 357*dd8f467eSTobias Waldekranz 358ac53c264SMarcin Wojtas fwnode = pdev->dev.fwnode; 359ac53c264SMarcin Wojtas if (is_of_node(fwnode)) 360ac53c264SMarcin Wojtas ret = of_mdiobus_register(bus, to_of_node(fwnode)); 361ac53c264SMarcin Wojtas else if (is_acpi_node(fwnode)) 362ac53c264SMarcin Wojtas ret = acpi_mdiobus_register(bus, fwnode); 363ac53c264SMarcin Wojtas else 364ac53c264SMarcin Wojtas ret = -EINVAL; 3659f35a734STimur Tabi if (ret) { 3669f35a734STimur Tabi dev_err(&pdev->dev, "cannot register MDIO bus\n"); 3679f35a734STimur Tabi return ret; 3689f35a734STimur Tabi } 3699f35a734STimur Tabi 3701d14eb15STobias Waldekranz platform_set_drvdata(pdev, bus); 3719f35a734STimur Tabi 3729f35a734STimur Tabi return 0; 3739f35a734STimur Tabi } 3749f35a734STimur Tabi 37594e5a2a8SFabian Frederick static const struct of_device_id xgmac_mdio_match[] = { 3769f35a734STimur Tabi { 3779f35a734STimur Tabi .compatible = "fsl,fman-xmdio", 3789f35a734STimur Tabi }, 3791fcf77c8SAndy Fleming { 3801fcf77c8SAndy Fleming .compatible = "fsl,fman-memac-mdio", 3811fcf77c8SAndy Fleming }, 3829f35a734STimur Tabi {}, 3839f35a734STimur Tabi }; 3849f35a734STimur Tabi MODULE_DEVICE_TABLE(of, xgmac_mdio_match); 3859f35a734STimur Tabi 386229f4bb4SCalvin Johnson static const struct acpi_device_id xgmac_acpi_match[] = { 387229f4bb4SCalvin Johnson { "NXP0006" }, 388229f4bb4SCalvin Johnson { } 389229f4bb4SCalvin Johnson }; 390229f4bb4SCalvin Johnson MODULE_DEVICE_TABLE(acpi, xgmac_acpi_match); 391229f4bb4SCalvin Johnson 3929f35a734STimur Tabi static struct platform_driver xgmac_mdio_driver = { 3939f35a734STimur Tabi .driver = { 3949f35a734STimur Tabi .name = "fsl-fman_xmdio", 3959f35a734STimur Tabi .of_match_table = xgmac_mdio_match, 396229f4bb4SCalvin Johnson .acpi_match_table = xgmac_acpi_match, 3979f35a734STimur Tabi }, 3989f35a734STimur Tabi .probe = xgmac_mdio_probe, 3999f35a734STimur Tabi }; 4009f35a734STimur Tabi 4019f35a734STimur Tabi module_platform_driver(xgmac_mdio_driver); 4029f35a734STimur Tabi 4039f35a734STimur Tabi MODULE_DESCRIPTION("Freescale QorIQ 10G MDIO Controller"); 4049f35a734STimur Tabi MODULE_LICENSE("GPL v2"); 405