diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-01-07 11:57:51 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-01-07 11:57:51 +0100 |
commit | c56fdbbc37cf676b42bbbf8d0efd0b78df4aed22 (patch) | |
tree | 6677350dc844c6fdb88c64401a1f965feb722557 /drivers/net | |
parent | 9d8c0841d2a893625c2eb5d7055cdf1615af5b8f (diff) | |
parent | 9bc898059000da9882f2f0561bfcff6d709e52ac (diff) | |
download | barebox-c56fdbbc37cf676b42bbbf8d0efd0b78df4aed22.tar.gz barebox-c56fdbbc37cf676b42bbbf8d0efd0b78df4aed22.tar.xz |
Merge branch 'for-next/miiphy'
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/phy/Kconfig | 5 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/lxt.c | 31 | ||||
-rw-r--r-- | drivers/net/phy/mdio_bus.c | 41 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 108 |
5 files changed, 128 insertions, 58 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 83966f997f..7ebdaa0c01 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -13,6 +13,11 @@ config AT803X_PHY ---help--- Currently supports the AT8030, AT8031 and AT8035 PHYs. +config LXT_PHY + bool "Driver for the Intel LXT PHYs" + ---help--- + Currently supports the lxt971 PHY. + config MICREL_PHY bool "Driver for Micrel PHYs" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 47e2b42331..451573ed83 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -1,4 +1,5 @@ obj-y += phy.o mdio_bus.o obj-$(CONFIG_AT803X_PHY) += at803x.o +obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_SMSC_PHY) += smsc.o diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c new file mode 100644 index 0000000000..9e5ddbb426 --- /dev/null +++ b/drivers/net/phy/lxt.c @@ -0,0 +1,31 @@ +/* + * drivers/net/phy/lxt.c + * + * Driver for Intel LXT PHYs + * + * base on Andy Fleming's linux lxt.c driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <common.h> +#include <init.h> +#include <linux/phy.h> + +static struct phy_driver lxt97x_driver[] = { +{ + .phy_id = 0x001378e0, + .phy_id_mask = 0xfffffff0, + .drv.name = "LXT971", + .features = PHY_BASIC_FEATURES, +} }; + +static int lxt97x_phy_init(void) +{ + return phy_drivers_register(lxt97x_driver, + ARRAY_SIZE(lxt97x_driver)); +} +fs_initcall(lxt97x_phy_init); diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 87072be289..895ead0a5c 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -25,6 +25,30 @@ #include <linux/phy.h> #include <linux/err.h> +LIST_HEAD(mii_bus_list); + +int mdiobus_detect(struct device_d *dev) +{ + struct mii_bus *mii = to_mii_bus(dev); + int i, ret; + + for (i = 0; i < PHY_MAX_ADDR; i++) { + struct phy_device *phydev; + + phydev = mdiobus_scan(mii, i); + if (IS_ERR(phydev)) + continue; + if (phydev->registered) + continue; + ret = phy_register_device(phydev); + if (ret) + dev_err(dev, "failed to register phy: %s\n", strerror(-ret)); + dev_info(dev, "registered phy as /dev/%s\n", phydev->cdev.name); + } + + return 0; +} + /** * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus * @bus: target mii_bus @@ -47,6 +71,7 @@ int mdiobus_register(struct mii_bus *bus) bus->dev.id = DEVICE_ID_DYNAMIC; strcpy(bus->dev.name, "miibus"); bus->dev.parent = bus->parent; + bus->dev.detect = mdiobus_detect; err = register_device(&bus->dev); if (err) { @@ -57,6 +82,8 @@ int mdiobus_register(struct mii_bus *bus) if (bus->reset) bus->reset(bus); + list_add_tail(&bus->list, &mii_bus_list); + pr_info("%s: probed\n", dev_name(&bus->dev)); return 0; } @@ -71,6 +98,8 @@ void mdiobus_unregister(struct mii_bus *bus) unregister_device(&bus->phy_map[i]->dev); bus->phy_map[i] = NULL; } + + list_del(&bus->list); } EXPORT_SYMBOL(mdiobus_unregister); @@ -153,8 +182,6 @@ static int mdio_bus_probe(struct device_d *_dev) int ret; - dev->attached_dev->phydev = dev; - if (drv->probe) { ret = drv->probe(dev); if (ret) @@ -183,14 +210,6 @@ static int mdio_bus_probe(struct device_d *_dev) dev->supported = drv->features; dev->advertising = drv->features; - ret = phy_init_hw(dev); - if (ret) - goto err; - - /* Sanitize settings based on PHY capabilities */ - if ((dev->supported & SUPPORTED_Autoneg) == 0) - dev->autoneg = AUTONEG_DISABLE; - dev_add_param_int_ro(&dev->dev, "phy_addr", dev->addr, "%d"); dev_add_param_int_ro(&dev->dev, "phy_id", dev->phy_id, "0x%08x"); @@ -204,8 +223,6 @@ static int mdio_bus_probe(struct device_d *_dev) return 0; err: - dev->attached_dev->phydev = NULL; - dev->attached_dev = NULL; return ret; } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 2a33054589..6ca1bb2573 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -224,21 +224,40 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr) return dev; } -static int phy_register_device(struct phy_device* dev) +static void phy_config_aneg(struct phy_device *phydev) +{ + struct phy_driver *drv; + + drv = to_phy_driver(phydev->dev.driver); + drv->config_aneg(phydev); +} + +int phy_register_device(struct phy_device* dev) { int ret; - dev->dev.parent = &dev->attached_dev->dev; + if (dev->registered) + return -EBUSY; + + dev->dev.parent = &dev->bus->dev; ret = register_device(&dev->dev); if (ret) return ret; + dev->registered = 1; + if (dev->dev.driver) return 0; dev->dev.driver = &genphy_driver.drv; - return device_probe(&dev->dev); + ret = device_probe(&dev->dev); + if (ret) { + unregister_device(&dev->dev); + dev->registered = 0; + } + + return ret; } /* Automatically gets and returns the PHY device */ @@ -246,66 +265,63 @@ int phy_device_connect(struct eth_device *edev, struct mii_bus *bus, int addr, void (*adjust_link) (struct eth_device *edev), u32 flags, phy_interface_t interface) { - struct phy_driver* drv; struct phy_device* dev = NULL; unsigned int i; int ret = -EINVAL; - if (!edev->phydev) { - if (addr >= 0) { - dev = mdiobus_scan(bus, addr); - if (IS_ERR(dev)) { - ret = -EIO; - goto fail; - } - - dev->attached_dev = edev; - dev->interface = interface; - dev->dev_flags = flags; - - ret = phy_register_device(dev); - if (ret) - goto fail; - } else { - for (i = 0; i < PHY_MAX_ADDR && !edev->phydev; i++) { - /* skip masked out PHY addresses */ - if (bus->phy_mask & (1 << i)) - continue; - - dev = mdiobus_scan(bus, i); - if (IS_ERR(dev) || dev->attached_dev) - continue; + if (edev->phydev) { + phy_config_aneg(edev->phydev); + return 0; + } - dev->attached_dev = edev; - dev->interface = interface; - dev->dev_flags = flags; + if (addr >= 0) { + dev = mdiobus_scan(bus, addr); + if (IS_ERR(dev)) { + ret = -EIO; + goto fail; + } + } else { + for (i = 0; i < PHY_MAX_ADDR && !edev->phydev; i++) { + /* skip masked out PHY addresses */ + if (bus->phy_mask & (1 << i)) + continue; + + dev = mdiobus_scan(bus, i); + if (!IS_ERR(dev) && !dev->attached_dev) + break; + } + } - ret = phy_register_device(dev); - if (ret) - goto fail; + if (dev->attached_dev) + return -EBUSY; - break; - } - } + dev->interface = interface; + dev->dev_flags = flags; - if (!edev->phydev) { - ret = -EIO; + if (!dev->registered) { + ret = phy_register_device(dev); + if (ret) goto fail; - } } - dev = edev->phydev; - drv = to_phy_driver(dev->dev.driver); + edev->phydev = dev; + dev->attached_dev = edev; - drv->config_aneg(dev); + ret = phy_init_hw(dev); + if (ret) + goto fail; + + /* Sanitize settings based on PHY capabilities */ + if ((dev->supported & SUPPORTED_Autoneg) == 0) + dev->autoneg = AUTONEG_DISABLE; + + phy_config_aneg(edev->phydev); dev->adjust_link = adjust_link; return 0; fail: - if (!IS_ERR(dev)) - dev->attached_dev = NULL; puts("Unable to find a PHY (unknown ID?)\n"); return ret; } @@ -757,7 +773,7 @@ int phy_driver_register(struct phy_driver *phydrv) return register_driver(&phydrv->drv); } - + int phy_drivers_register(struct phy_driver *new_driver, int n) { int i, ret = 0; |