static int sun4i_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mii_bus *bus; struct sun4i_mdio_data *data; struct resource *res; int ret; bus = mdiobus_alloc_size(sizeof(*data)); if (!bus) return -ENOMEM; bus->name = "sun4i_mii_bus"; bus->read = &sun4i_mdio_read; bus->write = &sun4i_mdio_write; snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); bus->parent = &pdev->dev; data = bus->priv; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->membase)) { ret = PTR_ERR(data->membase); goto err_out_free_mdiobus; } data->regulator = devm_regulator_get(&pdev->dev, "phy"); if (IS_ERR(data->regulator)) { if (PTR_ERR(data->regulator) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_info(&pdev->dev, "no regulator found\n"); data->regulator = NULL; } else { ret = regulator_enable(data->regulator); if (ret) goto err_out_free_mdiobus; } ret = of_mdiobus_register(bus, np); if (ret < 0) goto err_out_disable_regulator; platform_set_drvdata(pdev, bus); return 0; err_out_disable_regulator: if (data->regulator) regulator_disable(data->regulator); err_out_free_mdiobus: mdiobus_free(bus); return ret; }
static int xgmac_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mii_bus *bus; struct resource res; int ret; ret = of_address_to_resource(np, 0, &res); if (ret) { dev_err(&pdev->dev, "could not obtain address\n"); return ret; } bus = mdiobus_alloc_size(PHY_MAX_ADDR * sizeof(int)); if (!bus) return -ENOMEM; bus->name = "Freescale XGMAC MDIO Bus"; bus->read = xgmac_mdio_read; bus->write = xgmac_mdio_write; bus->reset = xgmac_mdio_reset; bus->irq = bus->priv; bus->parent = &pdev->dev; snprintf(bus->id, MII_BUS_ID_SIZE, "%llx", (unsigned long long)res.start); /* Set the PHY base address */ bus->priv = of_iomap(np, 0); if (!bus->priv) { ret = -ENOMEM; goto err_ioremap; } ret = of_mdiobus_register(bus, np); if (ret) { dev_err(&pdev->dev, "cannot register MDIO bus\n"); goto err_registration; } platform_set_drvdata(pdev, bus); return 0; err_registration: iounmap(bus->priv); err_ioremap: mdiobus_free(bus); return ret; }
static int moxart_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mii_bus *bus; struct moxart_mdio_data *data; struct resource *res; int ret, i; bus = mdiobus_alloc_size(sizeof(*data)); if (!bus) return -ENOMEM; bus->name = "MOXA ART Ethernet MII"; bus->read = &moxart_mdio_read; bus->write = &moxart_mdio_write; bus->reset = &moxart_mdio_reset; snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d-mii", pdev->name, pdev->id); bus->parent = &pdev->dev; /* Setting PHY_IGNORE_INTERRUPT here even if it has no effect, * of_mdiobus_register() sets these PHY_POLL. * Ideally, the interrupt from MAC controller could be used to * detect link state changes, not polling, i.e. if there was * a way phy_driver could set PHY_HAS_INTERRUPT but have that * interrupt handled in ethernet drivercode. */ for (i = 0; i < PHY_MAX_ADDR; i++) bus->irq[i] = PHY_IGNORE_INTERRUPT; data = bus->priv; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->base)) { ret = PTR_ERR(data->base); goto err_out_free_mdiobus; } ret = of_mdiobus_register(bus, np); if (ret < 0) goto err_out_free_mdiobus; platform_set_drvdata(pdev, bus); return 0; err_out_free_mdiobus: mdiobus_free(bus); return ret; }
static int hip04_mdio_probe(struct platform_device *pdev) { struct resource *r; struct mii_bus *bus; struct hip04_mdio_priv *priv; int ret; bus = mdiobus_alloc_size(sizeof(struct hip04_mdio_priv)); if (!bus) { dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); return -ENOMEM; } bus->name = "hip04_mdio_bus"; bus->read = hip04_mdio_read; bus->write = hip04_mdio_write; bus->reset = hip04_mdio_reset; snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); bus->parent = &pdev->dev; priv = bus->priv; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto out_mdio; } ret = of_mdiobus_register(bus, pdev->dev.of_node); if (ret < 0) { dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); goto out_mdio; } platform_set_drvdata(pdev, bus); return 0; out_mdio: mdiobus_free(bus); return ret; }
static int sun4i_mdio_probe(struct vmm_device *pdev, const struct vmm_devtree_nodeid *devid) { struct device_node *np = pdev->node; struct mii_bus *bus; struct sun4i_mdio_data *data; int ret, i; virtual_addr_t reg_addr; bus = mdiobus_alloc_size(sizeof(*data)); if (!bus) return -ENOMEM; bus->name = "sun4i_mii_bus"; bus->read = &sun4i_mdio_read; bus->write = &sun4i_mdio_write; bus->reset = &sun4i_mdio_reset; snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(pdev)); bus->parent = pdev; #if 0 bus->irq = devm_kzalloc(&pdev->dev, sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); #endif bus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!bus->irq) { ret = -ENOMEM; goto err_out_free_mdiobus; } for (i = 0; i < PHY_MAX_ADDR; i++) bus->irq[i] = PHY_POLL; data = bus->priv; #if 0 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->membase)) { ret = PTR_ERR(data->membase); goto err_out_free_mdiobus; } #endif if ((ret = vmm_devtree_request_regmap(np, ®_addr, 0, "Sun4i MDIO"))) { vmm_printf("%s: Failed to ioremap\n", __func__); return -ENOMEM; } data->membase = (void *) reg_addr; #if 0 data->regulator = devm_regulator_get(&pdev->dev, "phy"); #endif data->regulator = devm_regulator_get(pdev, "phy"); if (IS_ERR(data->regulator)) { if (PTR_ERR(data->regulator) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_info(pdev, "no regulator found\n"); } else { ret = regulator_enable(data->regulator); if (ret) goto err_out_free_mdiobus; } ret = of_mdiobus_register(bus, np); if (ret < 0) goto err_out_disable_regulator; platform_set_drvdata(pdev, bus); return 0; err_out_disable_regulator: regulator_disable(data->regulator); err_out_free_mdiobus: mdiobus_free(bus); return ret; }
static int orion_mdio_probe(struct platform_device *pdev) { struct resource *r; struct mii_bus *bus; struct orion_mdio_dev *dev; int i, ret; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "No SMI register address given\n"); return -ENODEV; } bus = mdiobus_alloc_size(sizeof(struct orion_mdio_dev)); if (!bus) { dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); return -ENOMEM; } bus->name = "orion_mdio_bus"; bus->read = orion_mdio_read; bus->write = orion_mdio_write; snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); bus->parent = &pdev->dev; bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); if (!bus->irq) { mdiobus_free(bus); return -ENOMEM; } for (i = 0; i < PHY_MAX_ADDR; i++) bus->irq[i] = PHY_POLL; dev = bus->priv; dev->regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!dev->regs) { dev_err(&pdev->dev, "Unable to remap SMI register\n"); ret = -ENODEV; goto out_mdio; } init_waitqueue_head(&dev->smi_busy_wait); dev->clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(dev->clk)) clk_prepare_enable(dev->clk); dev->err_interrupt = platform_get_irq(pdev, 0); if (dev->err_interrupt > 0) { ret = devm_request_irq(&pdev->dev, dev->err_interrupt, orion_mdio_err_irq, IRQF_SHARED, pdev->name, dev); if (ret) goto out_mdio; writel(MVMDIO_ERR_INT_SMI_DONE, dev->regs + MVMDIO_ERR_INT_MASK); } else if (dev->err_interrupt == -EPROBE_DEFER) { return -EPROBE_DEFER; } mutex_init(&dev->lock); if (pdev->dev.of_node) ret = of_mdiobus_register(bus, pdev->dev.of_node); else ret = mdiobus_register(bus); if (ret < 0) { dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); goto out_mdio; } platform_set_drvdata(pdev, bus); return 0; out_mdio: if (!IS_ERR(dev->clk)) clk_disable_unprepare(dev->clk); kfree(bus->irq); mdiobus_free(bus); return ret; }