if (up)
netif_carrier_on(netdev); else
netif_carrier_off(netdev);
phydev->adjust_link(netdev); if (phydev->mii_ts && phydev->mii_ts->link_state)
phydev->mii_ts->link_state(phydev->mii_ts, phydev);
}
/** * phy_uses_state_machine - test whether consumer driver uses PAL state machine * @phydev: the target PHY device structure * * Ultimately, this aims to indirectly determine whether the PHY is attached * to a consumer which uses the state machine by calling phy_start() and * phy_stop(). * * When the PHY driver consumer uses phylib, it must have previously called * phy_connect_direct() or one of its derivatives, so that phy_prepare_link() * has set up a hook for monitoring state changes. * * When the PHY driver is used by the MAC driver consumer through phylink (the * only other provider of a phy_link_change() method), using the PHY state * machine is not optional. * * Return: true if consumer calls phy_start() and phy_stop(), false otherwise.
*/ staticbool phy_uses_state_machine(struct phy_device *phydev)
{ if (phydev->phy_link_change == phy_link_change) return phydev->attached_dev && phydev->adjust_link;
/* If the PHY on the mido bus is not attached but has WOL enabled * we cannot suspend the PHY.
*/ if (!netdev && phy_drv_wol_enabled(phydev)) returnfalse;
/* PHY not attached? May suspend if the PHY has not already been * suspended as part of a prior call to phy_disconnect() -> * phy_detach() -> phy_suspend() because the parent netdev might be the * MDIO bus driver and clock gated at this point.
*/ if (!netdev) goto out;
if (netdev->ethtool->wol_enabled) returnfalse;
/* As long as not all affected network drivers support the * wol_enabled flag, let's check for hints that WoL is enabled. * Don't suspend PHY if the attached netdev parent may wake up. * The parent may point to a PCI device, as in tg3 driver.
*/ if (netdev->dev.parent && device_may_wakeup(netdev->dev.parent)) returnfalse;
/* Also don't suspend PHY if the netdev itself may wakeup. This * is the case for devices w/o underlaying pwr. mgmt. aware bus, * e.g. SoC devices.
*/ if (device_may_wakeup(&netdev->dev)) returnfalse;
/* Wakeup interrupts may occur during the system sleep transition when * the PHY is inaccessible. Set flag to postpone handling until the PHY * has resumed. Wait for concurrent interrupt handler to complete.
*/ if (phy_interrupt_is_valid(phydev)) {
phydev->irq_suspended = 1;
synchronize_irq(phydev->irq);
}
/* We must stop the state machine manually, otherwise it stops out of * control, possibly with the phydev->lock held. Upon resume, netdev * may call phy routines that try to grab the same lock, and that may * lead to a deadlock.
*/ if (phy_uses_state_machine(phydev))
phy_stop_machine(phydev);
if (!mdio_bus_phy_may_suspend(phydev)) return 0;
phydev->suspended_by_mdio_bus = 1;
return phy_suspend(phydev);
}
static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
{ struct phy_device *phydev = to_phy_device(dev); int ret;
if (phydev->mac_managed_pm) return 0;
if (!phydev->suspended_by_mdio_bus) goto no_resume;
phydev->suspended_by_mdio_bus = 0;
/* If we managed to get here with the PHY state machine in a state * neither PHY_HALTED, PHY_READY nor PHY_UP, this is an indication * that something went wrong and we should most likely be using * MAC managed PM, but we are not.
*/
WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY &&
phydev->state != PHY_UP);
ret = phy_init_hw(phydev); if (ret < 0) return ret;
ret = phy_resume(phydev); if (ret < 0) return ret;
no_resume: if (phy_interrupt_is_valid(phydev)) {
phydev->irq_suspended = 0;
synchronize_irq(phydev->irq);
/* Rerun interrupts which were postponed by phy_interrupt() * because they occurred during the system sleep transition.
*/ if (phydev->irq_rerun) {
phydev->irq_rerun = 0;
enable_irq(phydev->irq);
irq_wake_thread(phydev->irq, phydev);
}
}
if (phy_uses_state_machine(phydev))
phy_start_machine(phydev);
/** * phy_register_fixup - creates a new phy_fixup and adds it to the list * @bus_id: A string which matches phydev->mdio.dev.bus_id (or PHY_ANY_ID) * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY) * It can also be PHY_ANY_UID * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before * comparison * @run: The actual code to be run when a matching PHY is found
*/ staticint phy_register_fixup(constchar *bus_id, u32 phy_uid, u32 phy_uid_mask, int (*run)(struct phy_device *))
{ struct phy_fixup *fixup = kzalloc(sizeof(*fixup), GFP_KERNEL);
/* Registers a fixup to be run on any PHY with the UID in phy_uid */ int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, int (*run)(struct phy_device *))
{ return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
}
EXPORT_SYMBOL(phy_register_fixup_for_uid);
/* Registers a fixup to be run on the PHY with id string bus_id */ int phy_register_fixup_for_id(constchar *bus_id, int (*run)(struct phy_device *))
{ return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run);
}
EXPORT_SYMBOL(phy_register_fixup_for_id);
/** * phy_unregister_fixup - remove a phy_fixup from the list * @bus_id: A string matches fixup->bus_id (or PHY_ANY_ID) in phy_fixup_list * @phy_uid: A phy id matches fixup->phy_id (or PHY_ANY_UID) in phy_fixup_list * @phy_uid_mask: Applied to phy_uid and fixup->phy_uid before comparison
*/ int phy_unregister_fixup(constchar *bus_id, u32 phy_uid, u32 phy_uid_mask)
{ struct list_head *pos, *n; struct phy_fixup *fixup; int ret;
/* Unregisters a fixup of any PHY with the UID in phy_uid */ int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask)
{ return phy_unregister_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask);
}
EXPORT_SYMBOL(phy_unregister_fixup_for_uid);
/* Unregisters a fixup of the PHY with id string bus_id */ int phy_unregister_fixup_for_id(constchar *bus_id)
{ return phy_unregister_fixup(bus_id, PHY_ANY_UID, 0xffffffff);
}
EXPORT_SYMBOL(phy_unregister_fixup_for_id);
/* Returns 1 if fixup matches phydev in bus_id and phy_uid. * Fixups can be set to match any in one or more fields.
*/ staticint phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
{ if (strcmp(fixup->bus_id, phydev_name(phydev)) != 0) if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) return 0;
if (!phy_id_compare(phydev->phy_id, fixup->phy_uid,
fixup->phy_uid_mask)) if (fixup->phy_uid != PHY_ANY_UID) return 0;
return 1;
}
/* Runs any matching fixups for this phydev */ staticint phy_scan_fixups(struct phy_device *phydev)
{ struct phy_fixup *fixup;
mutex_lock(&phy_fixup_lock);
list_for_each_entry(fixup, &phy_fixup_list, list) { if (phy_needs_fixup(phydev, fixup)) { int err = fixup->run(phydev);
/** * genphy_match_phy_device - match a PHY device with a PHY driver * @phydev: target phy_device struct * @phydrv: target phy_driver struct * * Description: Checks whether the given PHY device matches the specified * PHY driver. For Clause 45 PHYs, iterates over the available device * identifiers and compares them against the driver's expected PHY ID, * applying the provided mask. For Clause 22 PHYs, a direct ID comparison * is performed. * * Return: 1 if the PHY device matches the driver, 0 otherwise.
*/ int genphy_match_phy_device(struct phy_device *phydev, conststruct phy_driver *phydrv)
{ if (phydev->is_c45) { constint num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); int i;
for (i = 1; i < num_ids; i++) { if (phydev->c45_ids.device_ids[i] == 0xffffffff) continue;
if (phy_id_compare(phydev->c45_ids.device_ids[i],
phydrv->phy_id, phydrv->phy_id_mask)) return 1;
}
staticint phy_request_driver_module(struct phy_device *dev, u32 phy_id)
{ int ret;
ret = request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT,
MDIO_ID_ARGS(phy_id)); /* We only check for failures in executing the usermode binary, * not whether a PHY driver module exists for the PHY ID. * Accept -ENOENT because this may occur in case no initramfs exists, * then modprobe isn't available.
*/ if (IS_ENABLED(CONFIG_MODULES) && ret < 0 && ret != -ENOENT) {
phydev_err(dev, "error %d loading PHY driver module for ID 0x%08lx\n",
ret, (unsignedlong)phy_id); return ret;
}
return 0;
}
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id, bool is_c45, struct phy_c45_device_ids *c45_ids)
{ struct phy_device *dev; struct mdio_device *mdiodev; int ret = 0;
/* We allocate the device, and initialize the default values */
dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM);
/* Request the appropriate module unconditionally; don't * bother trying to do so only if it isn't already loaded, * because that gets complicated. A hotplug event would have * done an unconditional modprobe anyway. * We don't do normal hotplug because it won't work for MDIO * -- because it relies on the device staying around for long * enough for the driver to get loaded. With MDIO, the NIC * driver will get bored and give up as soon as it finds that * there's no driver _already_ loaded.
*/ if (is_c45 && c45_ids) { constint num_ids = ARRAY_SIZE(c45_ids->device_ids); int i;
for (i = 1; i < num_ids; i++) { if (c45_ids->device_ids[i] == 0xffffffff) continue;
ret = phy_request_driver_module(dev,
c45_ids->device_ids[i]); if (ret) break;
}
} else {
ret = phy_request_driver_module(dev, phy_id);
}
if (ret) {
put_device(&mdiodev->dev);
dev = ERR_PTR(ret);
}
return dev;
}
EXPORT_SYMBOL(phy_device_create);
/* phy_c45_probe_present - checks to see if a MMD is present in the package * @bus: the target MII bus * @prtad: PHY package address on the MII bus * @devad: PHY device (MMD) address * * Read the MDIO_STAT2 register, and check whether a device is responding * at this address. * * Returns: negative error number on bus access error, zero if no device * is responding, or positive if a device is present.
*/ staticint phy_c45_probe_present(struct mii_bus *bus, int prtad, int devad)
{ int stat2;
/* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers. * @bus: the target MII bus * @addr: PHY address on the MII bus * @dev_addr: MMD address in the PHY. * @devices_in_package: where to store the devices in package information. * * Description: reads devices in package registers of a MMD at @dev_addr * from PHY at @addr on @bus. * * Returns: 0 on success, -EIO on failure.
*/ staticint get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr,
u32 *devices_in_package)
{ int phy_reg;
/** * get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs. * @bus: the target MII bus * @addr: PHY address on the MII bus * @c45_ids: where to store the c45 ID information. * * Read the PHY "devices in package". If this appears to be valid, read * the PHY identifiers for each device. Return the "devices in package" * and identifiers in @c45_ids. * * Returns zero on success, %-EIO on bus access error, or %-ENODEV if * the "devices in package" is invalid or no device responds.
*/ staticint get_phy_c45_ids(struct mii_bus *bus, int addr, struct phy_c45_device_ids *c45_ids)
{ constint num_ids = ARRAY_SIZE(c45_ids->device_ids);
u32 devs_in_pkg = 0; int i, ret, phy_reg;
/* Find first non-zero Devices In package. Device zero is reserved * for 802.3 c45 complied PHYs, so don't probe it at first.
*/ for (i = 1; i < MDIO_MMD_NUM && (devs_in_pkg == 0 ||
(devs_in_pkg & 0x1fffffff) == 0x1fffffff); i++) { if (i == MDIO_MMD_VEND1 || i == MDIO_MMD_VEND2) { /* Check that there is a device present at this * address before reading the devices-in-package * register to avoid reading garbage from the PHY. * Some PHYs (88x3310) vendor space is not IEEE802.3 * compliant.
*/
ret = phy_c45_probe_present(bus, addr, i); if (ret < 0) /* returning -ENODEV doesn't stop bus * scanning
*/ return (phy_reg == -EIO ||
phy_reg == -ENODEV) ? -ENODEV : -EIO;
if (!ret) continue;
}
phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, &devs_in_pkg); if (phy_reg < 0) return -EIO;
}
if ((devs_in_pkg & 0x1fffffff) == 0x1fffffff) { /* If mostly Fs, there is no device there, then let's probe * MMD 0, as some 10G PHYs have zero Devices In package, * e.g. Cortina CS4315/CS4340 PHY.
*/
phy_reg = get_phy_c45_devs_in_pkg(bus, addr, 0, &devs_in_pkg); if (phy_reg < 0) return -EIO;
/* no device there, let's get out of here */ if ((devs_in_pkg & 0x1fffffff) == 0x1fffffff) return -ENODEV;
}
/* Now probe Device Identifiers for each device present. */ for (i = 1; i < num_ids; i++) { if (!(devs_in_pkg & (1 << i))) continue;
if (i == MDIO_MMD_VEND1 || i == MDIO_MMD_VEND2) { /* Probe the "Device Present" bits for the vendor MMDs * to ignore these if they do not contain IEEE 802.3 * registers.
*/
ret = phy_c45_probe_present(bus, addr, i); if (ret < 0) return ret;
if (!ret) continue;
}
phy_reg = mdiobus_c45_read(bus, addr, i, MII_PHYSID1); if (phy_reg < 0) return -EIO;
c45_ids->device_ids[i] = phy_reg << 16;
phy_reg = mdiobus_c45_read(bus, addr, i, MII_PHYSID2); if (phy_reg < 0) return -EIO;
c45_ids->device_ids[i] |= phy_reg;
}
c45_ids->devices_in_package = devs_in_pkg; /* Bit 0 doesn't represent a device, it indicates c22 regs presence */
c45_ids->mmds_present = devs_in_pkg & ~BIT(0);
return 0;
}
/** * get_phy_c22_id - reads the specified addr for its clause 22 ID. * @bus: the target MII bus * @addr: PHY address on the MII bus * @phy_id: where to store the ID retrieved. * * Read the 802.3 clause 22 PHY ID from the PHY at @addr on the @bus, * placing it in @phy_id. Return zero on successful read and the ID is * valid, %-EIO on bus access error, or %-ENODEV if no device responds * or invalid ID.
*/ staticint get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id)
{ int phy_reg;
/* Grab the bits from PHYIR1, and put them in the upper half */
phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); if (phy_reg < 0) { /* returning -ENODEV doesn't stop bus scanning */ return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
}
*phy_id = phy_reg << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
phy_reg = mdiobus_read(bus, addr, MII_PHYSID2); if (phy_reg < 0) { /* returning -ENODEV doesn't stop bus scanning */ return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
}
*phy_id |= phy_reg;
/* If the phy_id is mostly Fs, there is no device there */ if ((*phy_id & 0x1fffffff) == 0x1fffffff) return -ENODEV;
return 0;
}
/* Extract the phy ID from the compatible string of the form * ethernet-phy-idAAAA.BBBB.
*/ int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id)
{ unsignedint upper, lower; constchar *cp; int ret;
ret = fwnode_property_read_string(fwnode, "compatible", &cp); if (ret) return ret;
if (sscanf(cp, "ethernet-phy-id%4x.%4x", &upper, &lower) != 2) return -EINVAL;
/** * get_phy_device - reads the specified PHY device and returns its @phy_device * struct * @bus: the target MII bus * @addr: PHY address on the MII bus * @is_c45: If true the PHY uses the 802.3 clause 45 protocol * * Probe for a PHY at @addr on @bus. * * When probing for a clause 22 PHY, then read the ID registers. If we find * a valid ID, allocate and return a &struct phy_device. * * When probing for a clause 45 PHY, read the "devices in package" registers. * If the "devices in package" appears valid, read the ID registers for each * MMD, allocate and return a &struct phy_device. * * Returns an allocated &struct phy_device on success, %-ENODEV if there is * no PHY present, or %-EIO on bus access error.
*/ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
{ struct phy_c45_device_ids c45_ids;
u32 phy_id = 0; int r;
if (is_c45)
r = get_phy_c45_ids(bus, addr, &c45_ids); else
r = get_phy_c22_id(bus, addr, &phy_id);
if (r) return ERR_PTR(r);
/* PHY device such as the Marvell Alaska 88E2110 will return a PHY ID * of 0 when probed using get_phy_c22_id() with no error. Proceed to * probe with C45 to see if we're able to get a valid PHY ID in the C45 * space, if successful, create the C45 PHY device.
*/ if (!is_c45 && phy_id == 0 && bus->read_c45) {
r = get_phy_c45_ids(bus, addr, &c45_ids); if (!r) return phy_device_create(bus, addr, phy_id, true, &c45_ids);
}
/** * phy_device_register - Register the phy device on the MDIO bus * @phydev: phy_device structure to be added to the MDIO bus
*/ int phy_device_register(struct phy_device *phydev)
{ int err;
err = mdiobus_register_device(&phydev->mdio); if (err) return err;
/* Deassert the reset signal */
phy_device_reset(phydev, 0);
/* Run all of the fixups for this PHY */
err = phy_scan_fixups(phydev); if (err) {
phydev_err(phydev, "failed to initialize\n"); goto out;
}
err = device_add(&phydev->mdio.dev); if (err) {
phydev_err(phydev, "failed to add\n"); goto out;
}
return 0;
out: /* Assert the reset signal */
phy_device_reset(phydev, 1);
/** * phy_device_remove - Remove a previously registered phy device from the MDIO bus * @phydev: phy_device structure to remove * * This doesn't free the phy_device itself, it merely reverses the effects * of phy_device_register(). Use phy_device_free() to free the device * after calling this function.
*/ void phy_device_remove(struct phy_device *phydev)
{
unregister_mii_timestamper(phydev->mii_ts);
pse_control_put(phydev->psec);
device_del(&phydev->mdio.dev);
/* Assert the reset signal */
phy_device_reset(phydev, 1);
/** * phy_get_c45_ids - Read 802.3-c45 IDs for phy device. * @phydev: phy_device structure to read 802.3-c45 IDs * * Returns zero on success, %-EIO on bus access error, or %-ENODEV if * the "devices in package" is invalid.
*/ int phy_get_c45_ids(struct phy_device *phydev)
{ return get_phy_c45_ids(phydev->mdio.bus, phydev->mdio.addr,
&phydev->c45_ids);
}
EXPORT_SYMBOL(phy_get_c45_ids);
/** * phy_find_first - finds the first PHY device on the bus * @bus: the target MII bus
*/ struct phy_device *phy_find_first(struct mii_bus *bus)
{ struct phy_device *phydev; int addr;
/** * phy_prepare_link - prepares the PHY layer to monitor link status * @phydev: target phy_device struct * @handler: callback function for link status change notifications * * Description: Tells the PHY infrastructure to handle the * gory details on monitoring link status (whether through * polling or an interrupt), and to call back to the * connected device driver when the link status changes. * If you want to monitor your own link state, don't call * this function.
*/ staticvoid phy_prepare_link(struct phy_device *phydev, void (*handler)(struct net_device *))
{
phydev->adjust_link = handler;
}
/** * phy_connect_direct - connect an ethernet device to a specific phy_device * @dev: the network device to connect * @phydev: the pointer to the phy device * @handler: callback function for state change notifications * @interface: PHY device's interface
*/ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, void (*handler)(struct net_device *),
phy_interface_t interface)
{ int rc;
if (!dev) return -EINVAL;
rc = phy_attach_direct(dev, phydev, phydev->dev_flags, interface); if (rc) return rc;
phy_prepare_link(phydev, handler); if (phy_interrupt_is_valid(phydev))
phy_request_interrupt(phydev);
return 0;
}
EXPORT_SYMBOL(phy_connect_direct);
/** * phy_connect - connect an ethernet device to a PHY device * @dev: the network device to connect * @bus_id: the id string of the PHY device to connect * @handler: callback function for state change notifications * @interface: PHY device's interface * * Description: Convenience function for connecting ethernet * devices to PHY devices. The default behavior is for * the PHY infrastructure to handle everything, and only notify * the connected driver when the link status changes. If you * don't want, or can't use the provided functionality, you may * choose to call only the subset of functions which provide * the desired functionality.
*/ struct phy_device *phy_connect(struct net_device *dev, constchar *bus_id, void (*handler)(struct net_device *),
phy_interface_t interface)
{ struct phy_device *phydev; struct device *d; int rc;
/* Search the list of PHY devices on the mdio bus for the * PHY with the requested name
*/
d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); if (!d) {
pr_err("PHY %s not found\n", bus_id); return ERR_PTR(-ENODEV);
}
phydev = to_phy_device(d);
/** * phy_poll_reset - Safely wait until a PHY reset has properly completed * @phydev: The PHY device to poll * * Description: According to IEEE 802.3, Section 2, Subsection 22.2.4.1.1, as * published in 2008, a PHY reset may take up to 0.5 seconds. The MII BMCR * register must be polled until the BMCR_RESET bit clears. * * Furthermore, any attempts to write to PHY registers may have no effect * or even generate MDIO bus errors until this is complete. * * Some PHYs (such as the Marvell 88E1111) don't entirely conform to the * standard and do not fully reset after the BMCR_RESET bit is set, and may * even *REQUIRE* a soft-reset to properly restart autonegotiation. In an * effort to support such broken PHYs, this function is separate from the * standard phy_init_hw() which will zero all the other bits in the BMCR * and reapply all driver-specific and board-specific fixups.
*/ staticint phy_poll_reset(struct phy_device *phydev)
{ /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ int ret, val;
ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
50000, 600000, true); if (ret) return ret; /* Some chips (smsc911x) may still need up to another 1ms after the * BMCR_RESET bit is cleared before they are usable.
*/
msleep(1); return 0;
}
int phy_init_hw(struct phy_device *phydev)
{ int ret = 0;
/* Deassert the reset signal */
phy_device_reset(phydev, 0);
if (!phydev->drv) return 0;
if (phydev->drv->soft_reset) {
ret = phydev->drv->soft_reset(phydev); if (ret < 0) return ret;
/* see comment in genphy_soft_reset for an explanation */
phydev->suspended = 0;
}
ret = phy_scan_fixups(phydev); if (ret < 0) return ret;
phy_interface_zero(phydev->possible_interfaces);
if (phydev->drv->config_init) {
ret = phydev->drv->config_init(phydev); if (ret < 0) return ret;
}
if (phydev->drv->config_intr) {
ret = phydev->drv->config_intr(phydev); if (ret < 0) return ret;
}
err = sysfs_create_link(&phydev->mdio.dev.kobj, &dev->dev.kobj, "attached_dev"); if (err) return;
err = sysfs_create_link_nowarn(&dev->dev.kobj,
&phydev->mdio.dev.kobj, "phydev"); if (err) {
dev_err(&dev->dev, "could not add device link to %s err %d\n",
kobject_name(&phydev->mdio.dev.kobj),
err); /* non-fatal - some net drivers can use one netdevice * with more then one phy
*/
}
/** * phy_sfp_connect_phy - Connect the SFP module's PHY to the upstream PHY * @upstream: pointer to the upstream phy device * @phy: pointer to the SFP module's phy device * * This helper allows keeping track of PHY devices on the link. It adds the * SFP module's phy to the phy namespace of the upstream phy * * Return: 0 on success, otherwise a negative error code.
*/ int phy_sfp_connect_phy(void *upstream, struct phy_device *phy)
{ struct phy_device *phydev = upstream; struct net_device *dev = phydev->attached_dev;
if (dev) return phy_link_topo_add_phy(dev, phy, PHY_UPSTREAM_PHY, phydev);
return 0;
}
EXPORT_SYMBOL(phy_sfp_connect_phy);
/** * phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstream PHY * @upstream: pointer to the upstream phy device * @phy: pointer to the SFP module's phy device * * This helper allows keeping track of PHY devices on the link. It removes the * SFP module's phy to the phy namespace of the upstream phy. As the module phy * will be destroyed, re-inserting the same module will add a new phy with a * new index.
*/ void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy)
{ struct phy_device *phydev = upstream; struct net_device *dev = phydev->attached_dev;
if (dev)
phy_link_topo_del_phy(dev, phy);
}
EXPORT_SYMBOL(phy_sfp_disconnect_phy);
/** * phy_sfp_attach - attach the SFP bus to the PHY upstream network device * @upstream: pointer to the phy device * @bus: sfp bus representing cage being attached * * This is used to fill in the sfp_upstream_ops .attach member.
*/ void phy_sfp_attach(void *upstream, struct sfp_bus *bus)
{ struct phy_device *phydev = upstream;
if (phydev->attached_dev)
phydev->attached_dev->sfp_bus = bus;
phydev->sfp_bus_attached = true;
}
EXPORT_SYMBOL(phy_sfp_attach);
/** * phy_sfp_detach - detach the SFP bus from the PHY upstream network device * @upstream: pointer to the phy device * @bus: sfp bus representing cage being attached * * This is used to fill in the sfp_upstream_ops .detach member.
*/ void phy_sfp_detach(void *upstream, struct sfp_bus *bus)
{ struct phy_device *phydev = upstream;
if (phydev->attached_dev)
phydev->attached_dev->sfp_bus = NULL;
phydev->sfp_bus_attached = false;
}
EXPORT_SYMBOL(phy_sfp_detach);
/** * phy_sfp_probe - probe for a SFP cage attached to this PHY device * @phydev: Pointer to phy_device * @ops: SFP's upstream operations
*/ int phy_sfp_probe(struct phy_device *phydev, conststruct sfp_upstream_ops *ops)
{ struct sfp_bus *bus; int ret = 0;
if (phydev->mdio.dev.fwnode) {
bus = sfp_bus_find_fwnode(phydev->mdio.dev.fwnode); if (IS_ERR(bus)) return PTR_ERR(bus);
/** * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach * @phydev: Pointer to phy_device to attach * @flags: PHY device's dev_flags * @interface: PHY device's interface * * Description: Called by drivers to attach to a particular PHY * device. The phy_device is found, and properly hooked up * to the phy_driver. If no driver is attached, then a * generic driver is used. The phy_device is given a ptr to * the attaching device, and given a callback for link status * change. The phy_device is returned to the attaching driver. * This function takes a reference on the phy device.
*/ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
u32 flags, phy_interface_t interface)
{ struct mii_bus *bus = phydev->mdio.bus; struct device *d = &phydev->mdio.dev; struct module *ndev_owner = NULL; int err;
/* For Ethernet device drivers that register their own MDIO bus, we * will have bus->owner match ndev_mod, so we do not want to increment * our own module->refcnt here, otherwise we would not be able to * unload later on.
*/ if (dev)
ndev_owner = dev->dev.parent->driver->owner; if (ndev_owner != bus->owner && !try_module_get(bus->owner)) {
phydev_err(phydev, "failed to get the bus module\n"); return -EIO;
}
get_device(d);
/* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver.
*/ if (!d->driver) { if (phydev->is_c45)
d->driver = &genphy_c45_driver.mdiodrv.driver; else
d->driver = &genphy_driver.mdiodrv.driver;
phydev->is_genphy_driven = 1;
}
if (!try_module_get(d->driver->owner)) {
phydev_err(phydev, "failed to get the device driver module\n");
err = -EIO; goto error_put_device;
}
if (phydev->is_genphy_driven) {
err = d->driver->probe(d); if (err >= 0)
err = device_bind_driver(d);
/* Some Ethernet drivers try to connect to a PHY device before * calling register_netdevice() -> netdev_register_kobject() and * does the dev->dev.kobj initialization. Here we only check for * success which indicates that the network device kobject is * ready. Once we do that we still need to keep track of whether * links were successfully set up or not for phy_detach() to * remove them accordingly.
*/
phydev->sysfs_links = false;
phy_sysfs_create_links(phydev);
if (!phydev->attached_dev) {
err = sysfs_create_file(&phydev->mdio.dev.kobj,
&dev_attr_phy_standalone.attr); if (err)
phydev_err(phydev, "error creating 'phy_standalone' sysfs entry\n");
}
phydev->dev_flags |= flags;
phydev->interface = interface;
phydev->state = PHY_READY;
phydev->interrupts = PHY_INTERRUPT_DISABLED;
/* PHYs can request to use poll mode even though they have an * associated interrupt line. This could be the case if they * detect a broken interrupt handling.
*/ if (phydev->dev_flags & PHY_F_NO_IRQ)
phydev->irq = PHY_POLL;
if (!phy_drv_supports_irq(phydev->drv) && phy_interrupt_is_valid(phydev))
phydev->irq = PHY_POLL;
/* Port is set to PORT_TP by default and the actual PHY driver will set * it to different value depending on the PHY configuration. If we have * the generic PHY driver we can't figure it out, thus set the old * legacy PORT_MII value.
*/ if (phydev->is_genphy_driven)
phydev->port = PORT_MII;
/* Initial carrier state is off as the phy is about to be * (re)initialized.
*/ if (dev)
netif_carrier_off(phydev->attached_dev);
/* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface)
*/
err = phy_init_hw(phydev); if (err) goto error;
phy_resume(phydev); if (!phydev->is_on_sfp_module)
phy_led_triggers_register(phydev);
/** * If the external phy used by current mac interface is managed by * another mac interface, so we should create a device link between * phy dev and mac dev.
*/ if (dev && phydev->mdio.bus->parent && dev->dev.parent != phydev->mdio.bus->parent)
phydev->devlink = device_link_add(dev->dev.parent, &phydev->mdio.dev,
DL_FLAG_PM_RUNTIME | DL_FLAG_STATELESS);
return err;
error: /* phy_detach() does all of the cleanup below */
phy_detach(phydev); return err;
/** * phy_attach - attach a network device to a particular PHY device * @dev: network device to attach * @bus_id: Bus ID of PHY device to attach * @interface: PHY device's interface * * Description: Same as phy_attach_direct() except that a PHY bus_id * string is passed instead of a pointer to a struct phy_device.
*/ struct phy_device *phy_attach(struct net_device *dev, constchar *bus_id,
phy_interface_t interface)
{ struct phy_device *phydev; struct device *d; int rc;
if (!dev) return ERR_PTR(-EINVAL);
/* Search the list of PHY devices on the mdio bus for the * PHY with the requested name
*/
d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); if (!d) {
pr_err("PHY %s not found\n", bus_id); return ERR_PTR(-ENODEV);
}
phydev = to_phy_device(d);
/** * phy_detach - detach a PHY device from its network device * @phydev: target phy_device struct * * This detaches the phy device from its network device and the phy * driver, and drops the reference count taken in phy_attach_direct().
*/ void phy_detach(struct phy_device *phydev)
{ struct net_device *dev = phydev->attached_dev; struct module *ndev_owner = NULL; struct mii_bus *bus;
if (phydev->devlink) {
device_link_del(phydev->devlink);
phydev->devlink = NULL;
}
if (phydev->sysfs_links) { if (dev)
sysfs_remove_link(&dev->dev.kobj, "phydev");
sysfs_remove_link(&phydev->mdio.dev.kobj, "attached_dev");
}
if (!phydev->attached_dev)
sysfs_remove_file(&phydev->mdio.dev.kobj,
&dev_attr_phy_standalone.attr);
phy_suspend(phydev); if (dev) { struct hwtstamp_provider *hwprov;
hwprov = rtnl_dereference(dev->hwprov); /* Disable timestamp if it is the one selected */ if (hwprov && hwprov->phydev == phydev) {
rcu_assign_pointer(dev->hwprov, NULL);
kfree_rcu(hwprov, rcu_head);
}
if (!phydev->is_on_sfp_module)
phy_led_triggers_unregister(phydev);
if (phydev->mdio.dev.driver)
module_put(phydev->mdio.dev.driver->owner);
/* If the device had no specific driver before (i.e. - it * was using the generic driver), we unbind the device * from the generic driver so that there's a chance a * real driver could be loaded
*/ if (phydev->is_genphy_driven) {
device_release_driver(&phydev->mdio.dev);
phydev->is_genphy_driven = 0;
}
/* Assert the reset signal */
phy_device_reset(phydev, 1);
/* * The phydev might go away on the put_device() below, so avoid * a use-after-free bug by reading the underlying bus first.
*/
bus = phydev->mdio.bus;
put_device(&phydev->mdio.dev); if (dev)
ndev_owner = dev->dev.parent->driver->owner; if (ndev_owner != bus->owner)
module_put(bus->owner);
}
EXPORT_SYMBOL(phy_detach);
int phy_suspend(struct phy_device *phydev)
{ struct net_device *netdev = phydev->attached_dev; conststruct phy_driver *phydrv = phydev->drv; int ret;
if (phydev->suspended || !phydrv) return 0;
phydev->wol_enabled = phy_drv_wol_enabled(phydev) ||
(netdev && netdev->ethtool->wol_enabled); /* If the device has WOL enabled, we cannot suspend the PHY */ if (phydev->wol_enabled && !(phydrv->flags & PHY_ALWAYS_CALL_SUSPEND)) return -EBUSY;
if (!phydrv->suspend) return 0;
ret = phydrv->suspend(phydev); if (!ret)
phydev->suspended = true;
return ret;
}
EXPORT_SYMBOL(phy_suspend);
int __phy_resume(struct phy_device *phydev)
{ conststruct phy_driver *phydrv = phydev->drv; int ret;
lockdep_assert_held(&phydev->lock);
if (!phydrv || !phydrv->resume) return 0;
ret = phydrv->resume(phydev); if (!ret)
phydev->suspended = false;
return ret;
}
EXPORT_SYMBOL(__phy_resume);
int phy_resume(struct phy_device *phydev)
{ int ret;
mutex_lock(&phydev->lock);
ret = __phy_resume(phydev);
mutex_unlock(&phydev->lock);
return ret;
}
EXPORT_SYMBOL(phy_resume);
/** * phy_reset_after_clk_enable - perform a PHY reset if needed * @phydev: target phy_device struct * * Description: Some PHYs are known to need a reset after their refclk was * enabled. This function evaluates the flags and perform the reset if it's * needed. Returns < 0 on error, 0 if the phy wasn't reset and 1 if the phy * was reset.
*/ int phy_reset_after_clk_enable(struct phy_device *phydev)
{ if (!phydev || !phydev->drv) return -ENODEV;
/** * genphy_config_advert - sanitize and advertise auto-negotiation parameters * @phydev: target phy_device struct * @advert: auto-negotiation parameters to advertise * * Description: Writes MII_ADVERTISE with the appropriate values, * after sanitizing the values to make sure we only advertise * what is supported. Returns < 0 on error, 0 if the PHY's advertisement * hasn't changed, and > 0 if it has changed.
*/ staticint genphy_config_advert(struct phy_device *phydev, constunsignedlong *advert)
{ int err, bmsr, changed = 0;
u32 adv;
adv = linkmode_adv_to_mii_adv_t(advert);
/* Setup standard advertisement */
err = phy_modify_changed(phydev, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_100BASE4 |
ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
adv); if (err < 0) return err; if (err > 0)
changed = 1;
bmsr = phy_read(phydev, MII_BMSR); if (bmsr < 0) return bmsr;
/* Per 802.3-2008, Section 22.2.4.2.16 Extended status all * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a * logical 1.
*/ if (!(bmsr & BMSR_ESTATEN)) return changed;
/** * genphy_c37_config_advert - sanitize and advertise auto-negotiation parameters * @phydev: target phy_device struct * * Description: Writes MII_ADVERTISE with the appropriate values, * after sanitizing the values to make sure we only advertise * what is supported. Returns < 0 on error, 0 if the PHY's advertisement * hasn't changed, and > 0 if it has changed. This function is intended * for Clause 37 1000Base-X mode.
*/ staticint genphy_c37_config_advert(struct phy_device *phydev)
{
u16 adv = 0;
/* Only allow advertising what this PHY supports */
linkmode_and(phydev->advertising, phydev->advertising,
phydev->supported);
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->advertising))
adv |= ADVERTISE_1000XFULL; if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
phydev->advertising))
adv |= ADVERTISE_1000XPAUSE; if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
phydev->advertising))
adv |= ADVERTISE_1000XPSE_ASYM;
/** * genphy_setup_forced - configures/forces speed/duplex from @phydev * @phydev: target phy_device struct * * Description: Configures MII_BMCR to force speed/duplex * to the values in phydev. Assumes that the values are valid. * Please see phy_sanitize_settings().
*/ int genphy_setup_forced(struct phy_device *phydev)
{
u16 ctl;
val = phy_read(phydev, MII_STAT1000); if (val < 0) return val;
if (val & LPA_1000MSFAIL) {
state = MASTER_SLAVE_STATE_ERR;
} elseif (phydev->link) { /* this bits are valid only for active link */ if (val & LPA_1000MSRES)
state = MASTER_SLAVE_STATE_MASTER; else
state = MASTER_SLAVE_STATE_SLAVE;
} else {
state = MASTER_SLAVE_STATE_UNKNOWN;
}
/** * genphy_restart_aneg - Enable and Restart Autonegotiation * @phydev: target phy_device struct
*/ int genphy_restart_aneg(struct phy_device *phydev)
{ /* Don't isolate the PHY if we're negotiating */ return phy_modify(phydev, MII_BMCR, BMCR_ISOLATE,
BMCR_ANENABLE | BMCR_ANRESTART);
}
EXPORT_SYMBOL(genphy_restart_aneg);
/** * genphy_check_and_restart_aneg - Enable and restart auto-negotiation * @phydev: target phy_device struct * @restart: whether aneg restart is requested * * Check, and restart auto-negotiation if needed.
*/ int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)
{ int ret;
if (!restart) { /* Advertisement hasn't changed, but maybe aneg was never on to * begin with? Or maybe phy was isolated?
*/
ret = phy_read(phydev, MII_BMCR); if (ret < 0) return ret;
/** * __genphy_config_aneg - restart auto-negotiation or write BMCR * @phydev: target phy_device struct * @changed: whether autoneg is requested * * Description: If auto-negotiation is enabled, we configure the * advertising, and then restart auto-negotiation. If it is not * enabled, then we write the BMCR.
*/ int __genphy_config_aneg(struct phy_device *phydev, bool changed)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(fixed_advert); conststruct link_capabilities *c; unsignedlong *advert; int err;
/** * genphy_c37_config_aneg - restart auto-negotiation or write BMCR * @phydev: target phy_device struct * * Description: If auto-negotiation is enabled, we configure the * advertising, and then restart auto-negotiation. If it is not * enabled, then we write the BMCR. This function is intended * for use with Clause 37 1000Base-X mode.
*/ int genphy_c37_config_aneg(struct phy_device *phydev)
{ int err, changed;
if (phydev->autoneg != AUTONEG_ENABLE) return genphy_setup_forced(phydev);
if (!changed) { /* Advertisement hasn't changed, but maybe aneg was never on to * begin with? Or maybe phy was isolated?
*/ int ctl = phy_read(phydev, MII_BMCR);
if (ctl < 0) return ctl;
if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
changed = 1; /* do restart aneg */
}
/* Only restart aneg if we are advertising something different * than we were before.
*/ if (changed > 0) return genphy_restart_aneg(phydev);
/** * genphy_aneg_done - return auto-negotiation status * @phydev: target phy_device struct * * Description: Reads the status register and returns 0 either if * auto-negotiation is incomplete, or if there was an error. * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
*/ int genphy_aneg_done(struct phy_device *phydev)
{ int retval = phy_read(phydev, MII_BMSR);
/** * genphy_update_link - update link status in @phydev * @phydev: target phy_device struct * * Description: Update the value in phydev->link to reflect the * current link value. In order to do this, we need to read * the status register twice, keeping the second value.
*/ int genphy_update_link(struct phy_device *phydev)
{ int status = 0, bmcr;
bmcr = phy_read(phydev, MII_BMCR); if (bmcr < 0) return bmcr;
/* Autoneg is being started, therefore disregard BMSR value and * report link as down.
*/ if (bmcr & BMCR_ANRESTART) goto done;
/* The link state is latched low so that momentary link * drops can be detected. Do not double-read the status * in polling mode to detect such short link drops except * the link was already down.
*/ if (!phy_polling_mode(phydev) || !phydev->link) {
status = phy_read(phydev, MII_BMSR); if (status < 0) return status; elseif (status & BMSR_LSTATUS) goto done;
}
/* Read link and autonegotiation status */
status = phy_read(phydev, MII_BMSR); if (status < 0) return status;
done:
phydev->link = status & BMSR_LSTATUS ? 1 : 0;
phydev->autoneg_complete = status & BMSR_ANEGCOMPLETE ? 1 : 0;
/* Consider the case that autoneg was started and "aneg complete" * bit has been reset, but "link up" bit not yet.
*/ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
phydev->link = 0;
return 0;
}
EXPORT_SYMBOL(genphy_update_link);
int genphy_read_lpa(struct phy_device *phydev)
{ int lpa, lpagb;
if (phydev->autoneg == AUTONEG_ENABLE) { if (!phydev->autoneg_complete) {
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising,
0);
mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); return 0;
}
if (phydev->is_gigabit_capable) {
lpagb = phy_read(phydev, MII_STAT1000); if (lpagb < 0) return lpagb;
if (lpagb & LPA_1000MSFAIL) { int adv = phy_read(phydev, MII_CTRL1000);
/** * genphy_read_status_fixed - read the link parameters for !aneg mode * @phydev: target phy_device struct * * Read the current duplex and speed state for a PHY operating with * autonegotiation disabled.
*/ int genphy_read_status_fixed(struct phy_device *phydev)
{ int bmcr = phy_read(phydev, MII_BMCR);
/** * genphy_read_status - check the link status and update current link state * @phydev: target phy_device struct * * Description: Check the link, then figure out the current state * by comparing what we advertise with what the link partner * advertises. Start by checking the gigabit possibilities, * then move on to 10/100.
*/ int genphy_read_status(struct phy_device *phydev)
{ int err, old_link = phydev->link;
/* Update the link, but return if there was an error */
err = genphy_update_link(phydev); if (err) return err;
/* why bother the PHY if nothing can have changed */ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) return 0;
/** * genphy_c37_read_status - check the link status and update current link state * @phydev: target phy_device struct * @changed: pointer where to store if link changed * * Description: Check the link, then figure out the current state * by comparing what we advertise with what the link partner * advertises. This function is for Clause 37 1000Base-X mode. * * If link has changed, @changed is set to true, false otherwise.
*/ int genphy_c37_read_status(struct phy_device *phydev, bool *changed)
{ int lpa, err, old_link = phydev->link;
/* Update the link, but return if there was an error */
err = genphy_update_link(phydev); if (err) return err;
/* why bother the PHY if nothing can have changed */ if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link) {
*changed = false; return 0;
}
/* Signal link has changed */
*changed = true;
phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
phydev->asym_pause = 0;
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
lpa = phy_read(phydev, MII_LPA); if (lpa < 0) return lpa;
/** * genphy_soft_reset - software reset the PHY via BMCR_RESET bit * @phydev: target phy_device struct * * Description: Perform a software PHY reset using the standard * BMCR_RESET bit and poll for the reset bit to be cleared. * * Returns: 0 on success, < 0 on failure
*/ int genphy_soft_reset(struct phy_device *phydev)
{
u16 res = BMCR_RESET; int ret;
if (phydev->autoneg == AUTONEG_ENABLE)
res |= BMCR_ANRESTART;
ret = phy_modify(phydev, MII_BMCR, BMCR_ISOLATE, res); if (ret < 0) return ret;
/* Clause 22 states that setting bit BMCR_RESET sets control registers * to their default value. Therefore the POWER DOWN bit is supposed to * be cleared after soft reset.
*/
phydev->suspended = 0;
ret = phy_poll_reset(phydev); if (ret) return ret;
/* BMCR may be reset to defaults */ if (phydev->autoneg == AUTONEG_DISABLE)
ret = genphy_setup_forced(phydev);
return ret;
}
EXPORT_SYMBOL(genphy_soft_reset);
irqreturn_t genphy_handle_interrupt_no_ack(struct phy_device *phydev)
{ /* It seems there are cases where the interrupts are handled by another * entity (ie an IRQ controller embedded inside the PHY) and do not * need any other interraction from phylib. In this case, just trigger * the state machine directly.
*/
phy_trigger_machine(phydev);
val = phy_read(phydev, MII_BMSR); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported,
val & BMSR_ANEGCAPABLE);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported,
val & BMSR_100FULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported,
val & BMSR_100HALF);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported,
val & BMSR_10FULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported,
val & BMSR_10HALF);
if (val & BMSR_ESTATEN) {
val = phy_read(phydev, MII_ESTATUS); if (val < 0) return val;
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported, val & ESTATUS_1000_TFULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported, val & ESTATUS_1000_THALF);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->supported, val & ESTATUS_1000_XFULL);
}
/* This is optional functionality. If not supported, we may get an error * which should be ignored.
*/
genphy_c45_read_eee_abilities(phydev);
return 0;
}
EXPORT_SYMBOL(genphy_read_abilities);
/* This is used for the phy device which doesn't support the MMD extended * register access, but it does have side effect when we are trying to access * the MMD register via indirect method.
*/ int genphy_read_mmd_unsupported(struct phy_device *phdev, int devad, u16 regnum)
{ return -EOPNOTSUPP;
}
EXPORT_SYMBOL(genphy_read_mmd_unsupported);
int genphy_write_mmd_unsupported(struct phy_device *phdev, int devnum,
u16 regnum, u16 val)
{ return -EOPNOTSUPP;
}
EXPORT_SYMBOL(genphy_write_mmd_unsupported);
ret = phy_read_poll_timeout(phydev, MII_BMSR, val,
val & BMSR_LSTATUS,
5000, 500000, true); if (ret) return ret;
} else {
phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
phy_config_aneg(phydev);
}
return 0;
}
EXPORT_SYMBOL(genphy_loopback);
/** * phy_remove_link_mode - Remove a supported link mode * @phydev: phy_device structure to remove link mode from * @link_mode: Link mode to be removed * * Description: Some MACs don't support all link modes which the PHY * does. e.g. a 1G MAC often does not support 1000Half. Add a helper * to remove a link mode.
*/ void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode)
{
linkmode_clear_bit(link_mode, phydev->supported);
phy_advertise_supported(phydev);
}
EXPORT_SYMBOL(phy_remove_link_mode);
/** * phy_advertise_eee_all - Advertise all supported EEE modes * @phydev: target phy_device struct * * Description: Per default phylib preserves the EEE advertising at the time of * phy probing, which might be a subset of the supported EEE modes. Use this * function when all supported EEE modes should be advertised. This does not * trigger auto-negotiation, so must be called before phy_start()/ * phylink_start() which will start auto-negotiation.
*/ void phy_advertise_eee_all(struct phy_device *phydev)
{
linkmode_copy(phydev->advertising_eee, phydev->supported_eee);
}
EXPORT_SYMBOL_GPL(phy_advertise_eee_all);
/** * phy_support_eee - Set initial EEE policy configuration * @phydev: Target phy_device struct * * This function configures the initial policy for Energy Efficient Ethernet * (EEE) on the specified PHY device, influencing that EEE capabilities are * advertised before the link is established. It should be called during PHY * registration by the MAC driver and/or the PHY driver (for SmartEEE PHYs) * if MAC supports LPI or PHY is capable to compensate missing LPI functionality * of the MAC. * * The function sets default EEE policy parameters, including preparing the PHY * to advertise EEE capabilities based on hardware support. * * It also sets the expected configuration for Low Power Idle (LPI) in the MAC * driver. If the PHY framework determines that both local and remote * advertisements support EEE, and the negotiated link mode is compatible with * EEE, it will set enable_tx_lpi = true. The MAC driver is expected to act on * this setting by enabling the LPI timer if enable_tx_lpi is set.
*/ void phy_support_eee(struct phy_device *phydev)
{
linkmode_copy(phydev->advertising_eee, phydev->supported_eee);
phydev->eee_cfg.tx_lpi_enabled = true;
phydev->eee_cfg.eee_enabled = true;
}
EXPORT_SYMBOL(phy_support_eee);
/** * phy_disable_eee - Disable EEE for the PHY * @phydev: Target phy_device struct * * This function is used by MAC drivers for MAC's which don't support EEE. * It disables EEE on the PHY layer.
*/ void phy_disable_eee(struct phy_device *phydev)
{
linkmode_zero(phydev->advertising_eee);
phydev->eee_cfg.tx_lpi_enabled = false;
phydev->eee_cfg.eee_enabled = false; /* don't let userspace re-enable EEE advertisement */
linkmode_fill(phydev->eee_disabled_modes);
}
EXPORT_SYMBOL_GPL(phy_disable_eee);
/** * phy_support_sym_pause - Enable support of symmetrical pause * @phydev: target phy_device struct * * Description: Called by the MAC to indicate is supports symmetrical * Pause, but not asym pause.
*/ void phy_support_sym_pause(struct phy_device *phydev)
{
linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported);
phy_copy_pause_bits(phydev->advertising, phydev->supported);
}
EXPORT_SYMBOL(phy_support_sym_pause);
/** * phy_support_asym_pause - Enable support of asym pause * @phydev: target phy_device struct * * Description: Called by the MAC to indicate is supports Asym Pause.
*/ void phy_support_asym_pause(struct phy_device *phydev)
{
phy_copy_pause_bits(phydev->advertising, phydev->supported);
}
EXPORT_SYMBOL(phy_support_asym_pause);
/** * phy_set_sym_pause - Configure symmetric Pause * @phydev: target phy_device struct * @rx: Receiver Pause is supported * @tx: Transmit Pause is supported * @autoneg: Auto neg should be used * * Description: Configure advertised Pause support depending on if * receiver pause and pause auto neg is supported. Generally called * from the set_pauseparam .ndo.
*/ void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx, bool autoneg)
{
linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported);
if (rx && tx && autoneg)
linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
phydev->supported);
/** * phy_set_asym_pause - Configure Pause and Asym Pause * @phydev: target phy_device struct * @rx: Receiver Pause is supported * @tx: Transmit Pause is supported * * Description: Configure advertised Pause support depending on if * transmit and receiver pause is supported. If there has been a * change in adverting, trigger a new autoneg. Generally called from * the set_pauseparam .ndo.
*/ void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(oldadv);
if (!linkmode_equal(oldadv, phydev->advertising) &&
phydev->autoneg)
phy_start_aneg(phydev);
}
EXPORT_SYMBOL(phy_set_asym_pause);
/** * phy_validate_pause - Test if the PHY/MAC support the pause configuration * @phydev: phy_device struct * @pp: requested pause configuration * * Description: Test if the PHY/MAC combination supports the Pause * configuration the user is requesting. Returns True if it is * supported, false otherwise.
*/ bool phy_validate_pause(struct phy_device *phydev, struct ethtool_pauseparam *pp)
{ if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
phydev->supported) && pp->rx_pause) returnfalse;
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
phydev->supported) &&
pp->rx_pause != pp->tx_pause) returnfalse;
returntrue;
}
EXPORT_SYMBOL(phy_validate_pause);
/** * phy_get_pause - resolve negotiated pause modes * @phydev: phy_device struct * @tx_pause: pointer to bool to indicate whether transmit pause should be * enabled. * @rx_pause: pointer to bool to indicate whether receive pause should be * enabled. * * Resolve and return the flow control modes according to the negotiation * result. This includes checking that we are operating in full duplex mode. * See linkmode_resolve_pause() for further details.
*/ void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause)
{ if (phydev->duplex != DUPLEX_FULL) {
*tx_pause = false;
*rx_pause = false; return;
}
/** * phy_get_internal_delay - returns the index of the internal delay * @phydev: phy_device struct * @delay_values: array of delays the PHY supports * @size: the size of the delay array * @is_rx: boolean to indicate to get the rx internal delay * * Returns the index within the array of internal delay passed in. * If the device property is not present then the interface type is checked * if the interface defines use of internal delay then a 1 is returned otherwise * a 0 is returned. * The array must be in ascending order. If PHY does not have an ascending order * array then size = 0 and the value of the delay property is returned. * Return -EINVAL if the delay is invalid or cannot be found.
*/
s32 phy_get_internal_delay(struct phy_device *phydev, constint *delay_values, int size, bool is_rx)
{ struct device *dev = &phydev->mdio.dev; int i, ret;
u32 delay;
if (is_rx) {
ret = phy_get_u32_property(dev, "rx-internal-delay-ps", &delay); if (ret < 0 && size == 0) { if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) return 1; else return 0;
}
err = of_property_read_u32(led, "reg", &index); if (err) return err; if (index > U8_MAX) return -EINVAL;
if (of_property_read_bool(led, "active-high"))
set_bit(PHY_LED_ACTIVE_HIGH, &modes); if (of_property_read_bool(led, "active-low"))
set_bit(PHY_LED_ACTIVE_LOW, &modes); if (of_property_read_bool(led, "inactive-high-impedance"))
set_bit(PHY_LED_INACTIVE_HIGH_IMPEDANCE, &modes);
if (WARN_ON(modes & BIT(PHY_LED_ACTIVE_LOW) &&
modes & BIT(PHY_LED_ACTIVE_HIGH))) return -EINVAL;
if (modes) { /* Return error if asked to set polarity modes but not supported */ if (!phydev->drv->led_polarity_set) return -EINVAL;
err = phydev->drv->led_polarity_set(phydev, index, modes); if (err) return err;
}
phyled->index = index; if (phydev->drv->led_brightness_set)
cdev->brightness_set_blocking = phy_led_set_brightness; if (phydev->drv->led_blink_set)
cdev->blink_set = phy_led_blink_set;
leds = of_get_child_by_name(node, "leds"); if (!leds) return 0;
/* Check if the PHY driver have at least an OP to * set the LEDs.
*/ if (!(phydev->drv->led_brightness_set ||
phydev->drv->led_blink_set ||
phydev->drv->led_hw_control_set)) {
phydev_dbg(phydev, "ignoring leds node defined with no PHY driver support\n"); gotoexit;
}
/** * fwnode_mdio_find_device - Given a fwnode, find the mdio_device * @fwnode: pointer to the mdio_device's fwnode * * If successful, returns a pointer to the mdio_device with the embedded * struct device refcount incremented by one, or NULL on failure. * The caller should call put_device() on the mdio_device after its use.
*/ struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
{ struct device *d;
if (!fwnode) return NULL;
d = bus_find_device_by_fwnode(&mdio_bus_type, fwnode); if (!d) return NULL;
/** * fwnode_phy_find_device - For provided phy_fwnode, find phy_device. * * @phy_fwnode: Pointer to the phy's fwnode. * * If successful, returns a pointer to the phy_device with the embedded * struct device refcount incremented by one, or NULL on failure.
*/ struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
{ struct mdio_device *mdiodev;
mdiodev = fwnode_mdio_find_device(phy_fwnode); if (!mdiodev) return NULL;
if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY) return to_phy_device(&mdiodev->dev);
/** * fwnode_get_phy_node - Get the phy_node using the named reference. * @fwnode: Pointer to fwnode from which phy_node has to be obtained. * * Refer return conditions of fwnode_find_reference(). * For ACPI, only "phy-handle" is supported. Legacy DT properties "phy" * and "phy-device" are not supported in ACPI. DT supports all the three * named references to the phy node.
*/ struct fwnode_handle *fwnode_get_phy_node(conststruct fwnode_handle *fwnode)
{ struct fwnode_handle *phy_node;
/* Only phy-handle is used for ACPI */
phy_node = fwnode_find_reference(fwnode, "phy-handle", 0); if (!IS_ERR(phy_node) || is_acpi_node(fwnode)) return phy_node;
phy_node = fwnode_find_reference(fwnode, "phy", 0); if (!IS_ERR(phy_node)) return phy_node; return fwnode_find_reference(fwnode, "phy-device", 0);
}
EXPORT_SYMBOL_GPL(fwnode_get_phy_node);
/** * phy_probe - probe and init a PHY device * @dev: device to probe and init * * Take care of setting up the phy_device structure, set the state to READY.
*/ staticint phy_probe(struct device *dev)
{ struct phy_device *phydev = to_phy_device(dev); struct device_driver *drv = phydev->mdio.dev.driver; struct phy_driver *phydrv = to_phy_driver(drv); int err = 0;
phydev->drv = phydrv;
/* Disable the interrupt if the PHY doesn't support it * but the interrupt is still a valid one
*/ if (!phy_drv_supports_irq(phydrv) && phy_interrupt_is_valid(phydev))
phydev->irq = PHY_POLL;
if (phydrv->flags & PHY_IS_INTERNAL)
phydev->is_internal = true;
/* Deassert the reset signal */
phy_device_reset(phydev, 0);
if (phydev->drv->probe) {
err = phydev->drv->probe(phydev); if (err) goto out;
}
phy_disable_interrupts(phydev);
/* Start out supporting everything. Eventually, * a controller will attach, and may modify one * or both of these values
*/ if (phydrv->features) {
linkmode_copy(phydev->supported, phydrv->features);
genphy_c45_read_eee_abilities(phydev);
} elseif (phydrv->get_features)
err = phydrv->get_features(phydev); elseif (phydev->is_c45)
err = genphy_c45_pma_read_abilities(phydev); else
err = genphy_read_abilities(phydev);
if (err) goto out;
if (!linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
phydev->supported))
phydev->autoneg = 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported))
phydev->is_gigabit_capable = 1; if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported))
phydev->is_gigabit_capable = 1;
/* Get PHY default EEE advertising modes and handle them as potentially * safe initial configuration.
*/
err = genphy_c45_read_eee_adv(phydev, phydev->advertising_eee); if (err) goto out;
/* Get the EEE modes we want to prohibit. */
of_set_phy_eee_broken(phydev);
/* Some PHYs may advertise, by default, not support EEE modes. So, * we need to clean them. In addition remove all disabled EEE modes.
*/
linkmode_and(phydev->advertising_eee, phydev->supported_eee,
phydev->advertising_eee);
linkmode_andnot(phydev->advertising_eee, phydev->advertising_eee,
phydev->eee_disabled_modes);
/* There is no "enabled" flag. If PHY is advertising, assume it is * kind of enabled.
*/
phydev->eee_cfg.eee_enabled = !linkmode_empty(phydev->advertising_eee);
/* Get master/slave strap overrides */
of_set_phy_timing_role(phydev);
/* The Pause Frame bits indicate that the PHY can support passing * pause frames. During autonegotiation, the PHYs will determine if * they should allow pause frames to pass. The MAC driver should then * use that result to determine whether to enable flow control via * pause frames. * * Normally, PHY drivers should not set the Pause bits, and instead * allow phylib to do that. However, there may be some situations * (e.g. hardware erratum) where the driver wants to set only one * of these bits.
*/ if (!test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported) &&
!test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported)) {
linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
phydev->supported);
}
/* Set the state to READY by default */
phydev->state = PHY_READY;
/* Get the LEDs from the device tree, and instantiate standard * LEDs for them.
*/ if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev))
err = of_phy_leds(phydev);
out: /* Re-assert the reset signal on error */ if (err)
phy_device_reset(phydev, 1);
if (phydev->drv && phydev->drv->remove)
phydev->drv->remove(phydev);
/* Assert the reset signal */
phy_device_reset(phydev, 1);
phydev->drv = NULL;
return 0;
}
/** * phy_driver_register - register a phy_driver with the PHY layer * @new_driver: new phy_driver to register * @owner: module owning this PHY
*/ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
{ int retval;
/* Either the features are hard coded, or dynamically * determined. It cannot be both.
*/ if (WARN_ON(new_driver->features && new_driver->get_features)) {
pr_err("%s: features and get_features must not both be set\n",
new_driver->name); return -EINVAL;
}
/* PHYLIB device drivers must not match using a DT compatible table * as this bypasses our checks that the mdiodev that is being matched * is backed by a struct phy_device. If such a case happens, we will * make out-of-bounds accesses and lockup in phydev->lock.
*/ if (WARN(new_driver->mdiodrv.driver.of_match_table, "%s: driver must not provide a DT match table\n",
new_driver->name)) return -EINVAL;
retval = driver_register(&new_driver->mdiodrv.driver); if (retval) {
pr_err("%s: Error %d in registering driver\n",
new_driver->name, retval);
return retval;
}
pr_debug("%s: Registered new driver\n", new_driver->name);
return 0;
}
EXPORT_SYMBOL(phy_driver_register);
int phy_drivers_register(struct phy_driver *new_driver, int n, struct module *owner)
{ int i, ret = 0;
for (i = 0; i < n; i++) {
ret = phy_driver_register(new_driver + i, owner); if (ret) { while (i-- > 0)
phy_driver_unregister(new_driver + i); break;
}
} return ret;
}
EXPORT_SYMBOL(phy_drivers_register);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.