[PATCH] net: phy: TI DP83869 fix invalid clock delay configuration
Ramon Fried
rfried.dev at gmail.com
Fri Oct 6 22:30:58 CEST 2023
On Fri, Oct 6, 2023 at 3:24 PM Frank de Brabander <debrabander at gmail.com> wrote:
>
> Setting the clock delay from the device tree settings
> rx-internal-delay-ps and tx-internal-delay-ps was broken:
>
> - The expected value in the device tree is suppose to be a
> delay in picoseconds, but the driver only allowed an array index.
> - Driver converted this array index to the actual delay in
> picoseconds and tried to apply this in the device register. This
> however is not a valid register value. The actual logic here was
> reversed, it converted an register representation of the delay to
> the device tree delay in picoseconds.
>
> Only when the internal delays were NOT configured in the device tree
> and they default value of 7 (=2000ps) was used, a valid value was
> loaded in the register.
>
> Signed-off-by: Frank de Brabander <debrabander at gmail.com>
> ---
> drivers/net/phy/dp83869.c | 53 +++++++++++++++++++++++----------------
> 1 file changed, 32 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
> index 8d32d73b07..f9d4782580 100644
> --- a/drivers/net/phy/dp83869.c
> +++ b/drivers/net/phy/dp83869.c
> @@ -81,7 +81,10 @@
>
> /* RGMIIDCTL bits */
> #define DP83869_RGMII_TX_CLK_DELAY_SHIFT 4
> -#define DP83869_CLK_DELAY_DEF 7
> +#define DP83869_CLK_DELAY_STEP 250
> +#define DP83869_CLK_DELAY_MIN 250
> +#define DP83869_CLK_DELAY_MAX 4000
> +#define DP83869_CLK_DELAY_DEFAULT 2000
>
> /* CFG2 bits */
> #define MII_DP83869_CFG2_SPEEDOPT_10EN 0x0040
> @@ -157,10 +160,6 @@ static int dp83869_config_port_mirroring(struct phy_device *phydev)
> return 0;
> }
>
> -static const int dp83869_internal_delay[] = {250, 500, 750, 1000, 1250, 1500,
> - 1750, 2000, 2250, 2500, 2750, 3000,
> - 3250, 3500, 3750, 4000};
> -
> static int dp83869_set_strapped_mode(struct phy_device *phydev)
> {
> struct dp83869_private *dp83869 = phydev->priv;
> @@ -183,7 +182,6 @@ static int dp83869_set_strapped_mode(struct phy_device *phydev)
> static int dp83869_of_init(struct phy_device *phydev)
> {
> struct dp83869_private * const dp83869 = phydev->priv;
> - const int delay_entries = ARRAY_SIZE(dp83869_internal_delay);
> int ret;
> ofnode node;
>
> @@ -238,32 +236,45 @@ static int dp83869_of_init(struct phy_device *phydev)
> dp83869->tx_fifo_depth = ofnode_read_s32_default(node, "tx-fifo-depth",
> DP83869_PHYCR_FIFO_DEPTH_4_B_NIB);
>
> + /* Internal clock delay values can be configured in steps of
> + * 250ps (0.25ns). The register field for clock delay is 4-bits wide,
> + * the values range from 0b0000 for 0.25ns to 0b1111 for 4ns.
> + */
> +
> /* RX delay *must* be specified if internal delay of RX is used. */
> if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
> phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
> - dp83869->rx_int_delay = ofnode_read_u32_default(node, "rx-internal-delay-ps",
> - DP83869_CLK_DELAY_DEF);
> - if (dp83869->rx_int_delay > delay_entries) {
> - dp83869->rx_int_delay = DP83869_CLK_DELAY_DEF;
> - pr_debug("rx-internal-delay-ps not set/invalid, default to %ups\n",
> - dp83869_internal_delay[dp83869->rx_int_delay]);
> + dp83869->rx_int_delay = ofnode_read_u32_default(node,
> + "rx-internal-delay-ps", DP83869_CLK_DELAY_DEFAULT);
> + if (dp83869->rx_int_delay > DP83869_CLK_DELAY_MAX ||
> + dp83869->rx_int_delay < DP83869_CLK_DELAY_MIN ||
> + dp83869->rx_int_delay % DP83869_CLK_DELAY_STEP) {
> + dp83869->rx_int_delay = DP83869_CLK_DELAY_DEFAULT;
> + pr_warn("rx-internal-delay-ps not set/invalid, default"
> + " to %ups\n", DP83869_CLK_DELAY_DEFAULT);
> }
>
> - dp83869->rx_int_delay = dp83869_internal_delay[dp83869->rx_int_delay];
> + dp83869->rx_int_delay =
> + (dp83869->rx_int_delay - DP83869_CLK_DELAY_STEP)
> + / DP83869_CLK_DELAY_STEP;
> }
>
> - /* TX delay *must* be specified if internal delay of RX is used. */
> + /* TX delay *must* be specified if internal delay of TX is used. */
> if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
> phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
> - dp83869->tx_int_delay = ofnode_read_u32_default(node, "tx-internal-delay-ps",
> - DP83869_CLK_DELAY_DEF);
> - if (dp83869->tx_int_delay > delay_entries) {
> - dp83869->tx_int_delay = DP83869_CLK_DELAY_DEF;
> - pr_debug("tx-internal-delay-ps not set/invalid, default to %ups\n",
> - dp83869_internal_delay[dp83869->tx_int_delay]);
> + dp83869->tx_int_delay = ofnode_read_u32_default(node,
> + "tx-internal-delay-ps", DP83869_CLK_DELAY_DEFAULT);
> + if (dp83869->tx_int_delay > DP83869_CLK_DELAY_MAX ||
> + dp83869->tx_int_delay < DP83869_CLK_DELAY_MIN ||
> + dp83869->tx_int_delay % DP83869_CLK_DELAY_STEP) {
> + dp83869->tx_int_delay = DP83869_CLK_DELAY_DEFAULT;
> + pr_warn("tx-internal-delay-ps not set/invalid, default"
> + " to %ups\n", DP83869_CLK_DELAY_DEFAULT);
> }
>
> - dp83869->tx_int_delay = dp83869_internal_delay[dp83869->tx_int_delay];
> + dp83869->tx_int_delay =
> + (dp83869->tx_int_delay - DP83869_CLK_DELAY_STEP)
> + / DP83869_CLK_DELAY_STEP;
> }
>
> return 0;
> --
> 2.30.2
>
Reviewed-by: Ramon Fried <rfried.dev at gmail.com>
More information about the U-Boot
mailing list