Commit dceb393a authored by Romain Gantois's avatar Romain Gantois Committed by Jakub Kicinski
Browse files

net: phylink: add rxc_always_on flag to phylink_pcs



Some MAC drivers (e.g. stmmac) require a continuous receive clock signal to
be generated by a PCS that is handled by a standalone PCS driver.

Such a PCS driver does not have access to a PHY device, thus cannot check
the PHY_F_RXC_ALWAYS_ON flag. They cannot check max_requires_rxc in the
phylink config either, since it is a private member. Therefore, a new flag
is needed to signal to the PCS that it should keep the RX clock signal up
at all times.

Co-developed-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarRomain Gantois <romain.gantois@bootlin.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20240326-rxc_bugfix-v6-2-24a74e5c761f@bootlin.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 21d9ba5b
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1042,6 +1042,21 @@ static void phylink_pcs_poll_start(struct phylink *pl)
		mod_timer(&pl->link_poll, jiffies + HZ);
}

int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs)
{
	int ret = 0;

	/* Signal to PCS driver that MAC requires RX clock for init */
	if (pl->config->mac_requires_rxc)
		pcs->rxc_always_on = true;

	if (pcs->ops->pcs_pre_init)
		ret = pcs->ops->pcs_pre_init(pcs);

	return ret;
}
EXPORT_SYMBOL_GPL(phylink_pcs_pre_init);

static void phylink_mac_config(struct phylink *pl,
			       const struct phylink_link_state *state)
{
+38 −0
Original line number Diff line number Diff line
@@ -396,6 +396,10 @@ struct phylink_pcs_ops;
 * @phylink: pointer to &struct phylink_config
 * @neg_mode: provide PCS neg mode via "mode" argument
 * @poll: poll the PCS for link changes
 * @rxc_always_on: The MAC driver requires the reference clock
 *                 to always be on. Standalone PCS drivers which
 *                 do not have access to a PHY device can check
 *                 this instead of PHY_F_RXC_ALWAYS_ON.
 *
 * This structure is designed to be embedded within the PCS private data,
 * and will be passed between phylink and the PCS.
@@ -408,6 +412,7 @@ struct phylink_pcs {
	struct phylink *phylink;
	bool neg_mode;
	bool poll;
	bool rxc_always_on;
};

/**
@@ -422,6 +427,8 @@ struct phylink_pcs {
 * @pcs_an_restart: restart 802.3z BaseX autonegotiation.
 * @pcs_link_up: program the PCS for the resolved link configuration
 *               (where necessary).
 * @pcs_pre_init: configure PCS components necessary for MAC hardware
 *                initialization e.g. RX clock for stmmac.
 */
struct phylink_pcs_ops {
	int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
@@ -441,6 +448,7 @@ struct phylink_pcs_ops {
	void (*pcs_an_restart)(struct phylink_pcs *pcs);
	void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode,
			    phy_interface_t interface, int speed, int duplex);
	int (*pcs_pre_init)(struct phylink_pcs *pcs);
};

#if 0 /* For kernel-doc purposes only. */
@@ -546,6 +554,34 @@ void pcs_an_restart(struct phylink_pcs *pcs);
 */
void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
		 phy_interface_t interface, int speed, int duplex);

/**
 * pcs_pre_init() - Configure PCS components necessary for MAC initialization
 * @pcs: a pointer to a &struct phylink_pcs.
 *
 * This function can be called by MAC drivers through the
 * phylink_pcs_pre_init() wrapper, before their hardware is initialized. It
 * should not be called after the link is brought up, as reconfiguring the PCS
 * at this point could break the link.
 *
 * Some MAC devices require specific hardware initialization to be performed by
 * their associated PCS device before they can properly initialize their own
 * hardware. An example of this is the initialization of stmmac controllers,
 * which requires an active REF_CLK signal to be provided by the PHY/PCS.
 *
 * By calling phylink_pcs_pre_init(), MAC drivers can ensure that the PCS is
 * setup in a way that allows for successful hardware initialization.
 *
 * The specific configuration performed by pcs_pre_init() is dependent on the
 * model of PCS and the requirements of the MAC device attached to it. PCS
 * driver authors should consider whether their target device is to be used in
 * conjunction with a MAC device whose driver calls phylink_pcs_pre_init(). MAC
 * driver authors should document their requirements for the PCS
 * pre-initialization.
 *
 */
int pcs_pre_init(struct phylink_pcs *pcs);

#endif

struct phylink *phylink_create(struct phylink_config *,
@@ -565,6 +601,8 @@ void phylink_disconnect_phy(struct phylink *);
void phylink_mac_change(struct phylink *, bool up);
void phylink_pcs_change(struct phylink_pcs *, bool up);

int phylink_pcs_pre_init(struct phylink *pl, struct phylink_pcs *pcs);

void phylink_start(struct phylink *);
void phylink_stop(struct phylink *);