History

net: phy: Add a helper to return the index for of the internal delay

Add a helper function that will return the index in the array for the passed in internal delay value. The helper requires the array, size and delay value. The helper will then return the index for the exact match or return the index for the index to the closest smaller value.

Dan Murphy committed 6 years ago

Commit 92252ee1 parent 91500692 files · +103 −0Browse files

Unified · Split

2 files
  1. drivers/net/phy/phy_device.c +99 −0
  2. include/linux/phy.h +4 −0
drivers/net/phy/phy_device.c+99−0
@@ -31,6 +31,7 @@ · 30 unmodified lines
31#include <linux/mdio.h>31#include <linux/mdio.h>
32#include <linux/io.h>32#include <linux/io.h>
33#include <linux/uaccess.h>33#include <linux/uaccess.h>
34#include <linux/property.h>
34 35
35MODULE_DESCRIPTION("PHY library");36MODULE_DESCRIPTION("PHY library");
36MODULE_AUTHOR("Andy Fleming");37MODULE_AUTHOR("Andy Fleming");
@@ -2708,6 +2709,104 @@ void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause) · 2671 unmodified lines
2708}2709}
2709EXPORT_SYMBOL(phy_get_pause);2710EXPORT_SYMBOL(phy_get_pause);
2710 2711
2712#if IS_ENABLED(CONFIG_OF_MDIO)
2713static int phy_get_int_delay_property(struct device *dev, const char *name)
2714{
2715 s32 int_delay;
2716 int ret;
2717
2718 ret = device_property_read_u32(dev, name, &int_delay);
2719 if (ret)
2720 return ret;
2721
2722 return int_delay;
2723}
2724#else
2725static int phy_get_int_delay_property(struct device *dev, const char *name)
2726{
2727 return -EINVAL;
2728}
2729#endif
2730
2731/**
2732 * phy_get_delay_index - returns the index of the internal delay
2733 * @phydev: phy_device struct
2734 * @dev: pointer to the devices device struct
2735 * @delay_values: array of delays the PHY supports
2736 * @size: the size of the delay array
2737 * @is_rx: boolean to indicate to get the rx internal delay
2738 *
2739 * Returns the index within the array of internal delay passed in.
2740 * If the device property is not present then the interface type is checked
2741 * if the interface defines use of internal delay then a 1 is returned otherwise
2742 * a 0 is returned.
2743 * The array must be in ascending order. If PHY does not have an ascending order
2744 * array then size = 0 and the value of the delay property is returned.
2745 * Return -EINVAL if the delay is invalid or cannot be found.
2746 */
2747s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
2748 const int *delay_values, int size, bool is_rx)
2749{
2750 s32 delay;
2751 int i;
2752
2753 if (is_rx) {
2754 delay = phy_get_int_delay_property(dev, "rx-internal-delay-ps");
2755 if (delay < 0 && size == 0) {
2756 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
2757 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
2758 return 1;
2759 else
2760 return 0;
2761 }
2762
2763 } else {
2764 delay = phy_get_int_delay_property(dev, "tx-internal-delay-ps");
2765 if (delay < 0 && size == 0) {
2766 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
2767 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
2768 return 1;
2769 else
2770 return 0;
2771 }
2772 }
2773
2774 if (delay < 0)
2775 return delay;
2776
2777 if (delay && size == 0)
2778 return delay;
2779
2780 if (delay < delay_values[0] || delay > delay_values[size - 1]) {
2781 phydev_err(phydev, "Delay %d is out of range\n", delay);
2782 return -EINVAL;
2783 }
2784
2785 if (delay == delay_values[0])
2786 return 0;
2787
2788 for (i = 1; i < size; i++) {
2789 if (delay == delay_values[i])
2790 return i;
2791
2792 /* Find an approximate index by looking up the table */
2793 if (delay > delay_values[i - 1] &&
2794 delay < delay_values[i]) {
2795 if (delay - delay_values[i - 1] <
2796 delay_values[i] - delay)
2797 return i - 1;
2798 else
2799 return i;
2800 }
2801 }
2802
2803 phydev_err(phydev, "error finding internal delay index for %d\n",
2804 delay);
2805
2806 return -EINVAL;
2807}
2808EXPORT_SYMBOL(phy_get_internal_delay);
2809
2711static bool phy_drv_supports_irq(struct phy_driver *phydrv)2810static bool phy_drv_supports_irq(struct phy_driver *phydrv)
2712{2811{
2713 return phydrv->config_intr && phydrv->ack_interrupt;2812 return phydrv->config_intr && phydrv->ack_interrupt;
include/linux/phy.h+4−0
@@ -1443,6 +1443,10 @@ void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx); · 1442 unmodified lines
1443bool phy_validate_pause(struct phy_device *phydev,1443bool phy_validate_pause(struct phy_device *phydev,
1444 struct ethtool_pauseparam *pp);1444 struct ethtool_pauseparam *pp);
1445void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause);1445void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause);
1446
1447s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
1448 const int *delay_values, int size, bool is_rx);
1449
1446void phy_resolve_pause(unsigned long *local_adv, unsigned long *partner_adv,1450void phy_resolve_pause(unsigned long *local_adv, unsigned long *partner_adv,
1447 bool *tx_pause, bool *rx_pause);1451 bool *tx_pause, bool *rx_pause);
1448 1452