// SPDX-License-Identifier: GPL-2.0+ /* * Core PHY library, taken from phy.c */ #include <linux/export.h> #include <linux/phy.h> #include <linux/of.h> /** * phy_speed_to_str - Return a string representing the PHY link speed * * @speed: Speed of the link */ const char *phy_speed_to_str(int speed) { … } EXPORT_SYMBOL_GPL(…); /** * phy_duplex_to_str - Return string describing the duplex * * @duplex: Duplex setting to describe */ const char *phy_duplex_to_str(unsigned int duplex) { … } EXPORT_SYMBOL_GPL(…); /** * phy_rate_matching_to_str - Return a string describing the rate matching * * @rate_matching: Type of rate matching to describe */ const char *phy_rate_matching_to_str(int rate_matching) { … } EXPORT_SYMBOL_GPL(…); /** * phy_interface_num_ports - Return the number of links that can be carried by * a given MAC-PHY physical link. Returns 0 if this is * unknown, the number of links else. * * @interface: The interface mode we want to get the number of ports */ int phy_interface_num_ports(phy_interface_t interface) { … } EXPORT_SYMBOL_GPL(…); /* A mapping of all SUPPORTED settings to speed/duplex. This table * must be grouped by speed and sorted in descending match priority * - iow, descending speed. */ #define PHY_SETTING … static const struct phy_setting settings[] = …; #undef PHY_SETTING /** * phy_lookup_setting - lookup a PHY setting * @speed: speed to match * @duplex: duplex to match * @mask: allowed link modes * @exact: an exact match is required * * Search the settings array for a setting that matches the speed and * duplex, and which is supported. * * If @exact is unset, either an exact match or %NULL for no match will * be returned. * * If @exact is set, an exact match, the fastest supported setting at * or below the specified speed, the slowest supported setting, or if * they all fail, %NULL will be returned. */ const struct phy_setting * phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact) { … } EXPORT_SYMBOL_GPL(…); size_t phy_speeds(unsigned int *speeds, size_t size, unsigned long *mask) { … } static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr) { … } static void __set_phy_supported(struct phy_device *phydev, u32 max_speed) { … } /** * phy_set_max_speed - Set the maximum speed the PHY should support * * @phydev: The phy_device struct * @max_speed: Maximum speed * * The PHY might be more capable than the MAC. For example a Fast Ethernet * is connected to a 1G PHY. This function allows the MAC to indicate its * maximum speed, and so limit what the PHY will advertise. */ void phy_set_max_speed(struct phy_device *phydev, u32 max_speed) { … } EXPORT_SYMBOL(…); void of_set_phy_supported(struct phy_device *phydev) { … } void of_set_phy_eee_broken(struct phy_device *phydev) { … } /** * phy_resolve_aneg_pause - Determine pause autoneg results * * @phydev: The phy_device struct * * Once autoneg has completed the local pause settings can be * resolved. Determine if pause and asymmetric pause should be used * by the MAC. */ void phy_resolve_aneg_pause(struct phy_device *phydev) { … } EXPORT_SYMBOL_GPL(…); /** * phy_resolve_aneg_linkmode - resolve the advertisements into PHY settings * @phydev: The phy_device struct * * Resolve our and the link partner advertisements into their corresponding * speed and duplex. If full duplex was negotiated, extract the pause mode * from the link partner mask. */ void phy_resolve_aneg_linkmode(struct phy_device *phydev) { … } EXPORT_SYMBOL_GPL(…); /** * phy_check_downshift - check whether downshift occurred * @phydev: The phy_device struct * * Check whether a downshift to a lower speed occurred. If this should be the * case warn the user. * Prerequisite for detecting downshift is that PHY driver implements the * read_status callback and sets phydev->speed to the actual link speed. */ void phy_check_downshift(struct phy_device *phydev) { … } EXPORT_SYMBOL_GPL(…); static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only) { … } int phy_speed_down_core(struct phy_device *phydev) { … } static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad, u16 regnum) { … } static int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, int devad, u32 regnum) { … } static int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, int devad, u32 regnum, u16 val) { … } /** * __phy_read_mmd - Convenience function for reading a register * from an MMD on a given PHY. * @phydev: The phy_device struct * @devad: The MMD to read from (0..31) * @regnum: The register on the MMD to read (0..65535) * * Same rules as for __phy_read(); */ int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) { … } EXPORT_SYMBOL(…); /** * phy_read_mmd - Convenience function for reading a register * from an MMD on a given PHY. * @phydev: The phy_device struct * @devad: The MMD to read from * @regnum: The register on the MMD to read * * Same rules as for phy_read(); */ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) { … } EXPORT_SYMBOL(…); /** * __phy_write_mmd - Convenience function for writing a register * on an MMD on a given PHY. * @phydev: The phy_device struct * @devad: The MMD to read from * @regnum: The register on the MMD to read * @val: value to write to @regnum * * Same rules as for __phy_write(); */ int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) { … } EXPORT_SYMBOL(…); /** * phy_write_mmd - Convenience function for writing a register * on an MMD on a given PHY. * @phydev: The phy_device struct * @devad: The MMD to read from * @regnum: The register on the MMD to read * @val: value to write to @regnum * * Same rules as for phy_write(); */ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) { … } EXPORT_SYMBOL(…); /** * __phy_package_read_mmd - read MMD reg relative to PHY package base addr * @phydev: The phy_device struct * @addr_offset: The offset to be added to PHY package base_addr * @devad: The MMD to read from * @regnum: The register on the MMD to read * * Convenience helper for reading a register of an MMD on a given PHY * using the PHY package base address. The base address is added to * the addr_offset value. * * Same calling rules as for __phy_read(); * * NOTE: It's assumed that the entire PHY package is either C22 or C45. */ int __phy_package_read_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum) { … } EXPORT_SYMBOL(…); /** * phy_package_read_mmd - read MMD reg relative to PHY package base addr * @phydev: The phy_device struct * @addr_offset: The offset to be added to PHY package base_addr * @devad: The MMD to read from * @regnum: The register on the MMD to read * * Convenience helper for reading a register of an MMD on a given PHY * using the PHY package base address. The base address is added to * the addr_offset value. * * Same calling rules as for phy_read(); * * NOTE: It's assumed that the entire PHY package is either C22 or C45. */ int phy_package_read_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum) { … } EXPORT_SYMBOL(…); /** * __phy_package_write_mmd - write MMD reg relative to PHY package base addr * @phydev: The phy_device struct * @addr_offset: The offset to be added to PHY package base_addr * @devad: The MMD to write to * @regnum: The register on the MMD to write * @val: value to write to @regnum * * Convenience helper for writing a register of an MMD on a given PHY * using the PHY package base address. The base address is added to * the addr_offset value. * * Same calling rules as for __phy_write(); * * NOTE: It's assumed that the entire PHY package is either C22 or C45. */ int __phy_package_write_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum, u16 val) { … } EXPORT_SYMBOL(…); /** * phy_package_write_mmd - write MMD reg relative to PHY package base addr * @phydev: The phy_device struct * @addr_offset: The offset to be added to PHY package base_addr * @devad: The MMD to write to * @regnum: The register on the MMD to write * @val: value to write to @regnum * * Convenience helper for writing a register of an MMD on a given PHY * using the PHY package base address. The base address is added to * the addr_offset value. * * Same calling rules as for phy_write(); * * NOTE: It's assumed that the entire PHY package is either C22 or C45. */ int phy_package_write_mmd(struct phy_device *phydev, unsigned int addr_offset, int devad, u32 regnum, u16 val) { … } EXPORT_SYMBOL(…); /** * phy_modify_changed - Function for modifying a PHY register * @phydev: the phy_device struct * @regnum: register number to modify * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * NOTE: MUST NOT be called from interrupt context, * because the bus read/write functions may wait for an interrupt * to conclude the operation. * * Returns negative errno, 0 if there was no change, and 1 in case of change */ int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); /** * __phy_modify - Convenience function for modifying a PHY register * @phydev: the phy_device struct * @regnum: register number to modify * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * NOTE: MUST NOT be called from interrupt context, * because the bus read/write functions may wait for an interrupt * to conclude the operation. */ int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); /** * phy_modify - Convenience function for modifying a given PHY register * @phydev: the phy_device struct * @regnum: register number to write * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * NOTE: MUST NOT be called from interrupt context, * because the bus read/write functions may wait for an interrupt * to conclude the operation. */ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); /** * __phy_modify_mmd_changed - Function for modifying a register on MMD * @phydev: the phy_device struct * @devad: the MMD containing register to modify * @regnum: register number to modify * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * Unlocked helper function which allows a MMD register to be modified as * new register value = (old register value & ~mask) | set * * Returns negative errno, 0 if there was no change, and 1 in case of change */ int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); /** * phy_modify_mmd_changed - Function for modifying a register on MMD * @phydev: the phy_device struct * @devad: the MMD containing register to modify * @regnum: register number to modify * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * NOTE: MUST NOT be called from interrupt context, * because the bus read/write functions may wait for an interrupt * to conclude the operation. * * Returns negative errno, 0 if there was no change, and 1 in case of change */ int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); /** * __phy_modify_mmd - Convenience function for modifying a register on MMD * @phydev: the phy_device struct * @devad: the MMD containing register to modify * @regnum: register number to modify * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * NOTE: MUST NOT be called from interrupt context, * because the bus read/write functions may wait for an interrupt * to conclude the operation. */ int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); /** * phy_modify_mmd - Convenience function for modifying a register on MMD * @phydev: the phy_device struct * @devad: the MMD containing register to modify * @regnum: register number to modify * @mask: bit mask of bits to clear * @set: new value of bits set in mask to write to @regnum * * NOTE: MUST NOT be called from interrupt context, * because the bus read/write functions may wait for an interrupt * to conclude the operation. */ int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL_GPL(…); static int __phy_read_page(struct phy_device *phydev) { … } static int __phy_write_page(struct phy_device *phydev, int page) { … } /** * phy_save_page() - take the bus lock and save the current page * @phydev: a pointer to a &struct phy_device * * Take the MDIO bus lock, and return the current page number. On error, * returns a negative errno. phy_restore_page() must always be called * after this, irrespective of success or failure of this call. */ int phy_save_page(struct phy_device *phydev) { … } EXPORT_SYMBOL_GPL(…); /** * phy_select_page() - take the bus lock, save the current page, and set a page * @phydev: a pointer to a &struct phy_device * @page: desired page * * Take the MDIO bus lock to protect against concurrent access, save the * current PHY page, and set the current page. On error, returns a * negative errno, otherwise returns the previous page number. * phy_restore_page() must always be called after this, irrespective * of success or failure of this call. */ int phy_select_page(struct phy_device *phydev, int page) { … } EXPORT_SYMBOL_GPL(…); /** * phy_restore_page() - restore the page register and release the bus lock * @phydev: a pointer to a &struct phy_device * @oldpage: the old page, return value from phy_save_page() or phy_select_page() * @ret: operation's return code * * Release the MDIO bus lock, restoring @oldpage if it is a valid page. * This function propagates the earliest error code from the group of * operations. * * Returns: * @oldpage if it was a negative value, otherwise * @ret if it was a negative errno value, otherwise * phy_write_page()'s negative value if it were in error, otherwise * @ret. */ int phy_restore_page(struct phy_device *phydev, int oldpage, int ret) { … } EXPORT_SYMBOL_GPL(…); /** * phy_read_paged() - Convenience function for reading a paged register * @phydev: a pointer to a &struct phy_device * @page: the page for the phy * @regnum: register number * * Same rules as for phy_read(). */ int phy_read_paged(struct phy_device *phydev, int page, u32 regnum) { … } EXPORT_SYMBOL(…); /** * phy_write_paged() - Convenience function for writing a paged register * @phydev: a pointer to a &struct phy_device * @page: the page for the phy * @regnum: register number * @val: value to write * * Same rules as for phy_write(). */ int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val) { … } EXPORT_SYMBOL(…); /** * phy_modify_paged_changed() - Function for modifying a paged register * @phydev: a pointer to a &struct phy_device * @page: the page for the phy * @regnum: register number * @mask: bit mask of bits to clear * @set: bit mask of bits to set * * Returns negative errno, 0 if there was no change, and 1 in case of change */ int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL(…); /** * phy_modify_paged() - Convenience function for modifying a paged register * @phydev: a pointer to a &struct phy_device * @page: the page for the phy * @regnum: register number * @mask: bit mask of bits to clear * @set: bit mask of bits to set * * Same rules as for phy_read() and phy_write(). */ int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum, u16 mask, u16 set) { … } EXPORT_SYMBOL(…);