mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
phy: lynx-10g: new driver
Introduce a driver for the networking lanes of the 10G Lynx SerDes block, present on the majority of Layerscape and QorIQ (Freescale/NXP) SoCs. As with the 28G Lynx, the SerDes lanes come pre-initialized out of reset and the consumers use them that way outside the Generic PHY framework (for networking, the static configuration remains for the entire SoC lifetime, whereas for SATA and PCIe, the hardware reconfigures itself automatically for other link speeds). The need for the Generic PHY framework comes specifically for networking use cases where a static lane configuration is not sufficient. For example a network MAC is connected to an SFP cage, where various SFP or SFP+ modules can be connected. Each of them may require a different SerDes protocol (SGMII, 1000Base-X, 10GBase-R), which phylink + sfp-bus are responsible of figuring out. The phylink drivers are: - enetc - felix - dpaa_eth (fman_memac) - dpaa2-eth - dpaa2-switch and they all need to reconfigure the SerDes for the requested link mode, using phy_set_mode_ext() (and phy_validate() to see if it is supported in the first place). Note that SerDes 2 on LS1088A is exclusively non-networking, so there is currently no need for this driver. Therefore we skip matching on its compatible string and do not probe on that device. Co-developed-by: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://patch.msgid.link/20260610151952.2141019-16-vladimir.oltean@nxp.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
a7dc4e95d3
commit
6dc92ba487
|
|
@ -54,6 +54,16 @@ endif
|
|||
config PHY_FSL_LYNX_CORE
|
||||
tristate
|
||||
|
||||
config PHY_FSL_LYNX_10G
|
||||
tristate "Freescale Layerscape Lynx 10G SerDes PHY support"
|
||||
depends on OF
|
||||
depends on ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
select GENERIC_PHY
|
||||
select PHY_FSL_LYNX_CORE
|
||||
help
|
||||
Enable this to add support for the Lynx 10G SerDes PHY as found on
|
||||
NXP's Layerscape platform such as LS1088A or LS1028A.
|
||||
|
||||
config PHY_FSL_LYNX_28G
|
||||
tristate "Freescale Layerscape Lynx 28G SerDes PHY support"
|
||||
depends on OF
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@ obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
|
|||
obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
|
||||
obj-$(CONFIG_PHY_FSL_IMX8QM_HSIO) += phy-fsl-imx8qm-hsio.o
|
||||
obj-$(CONFIG_PHY_FSL_LYNX_CORE) += phy-fsl-lynx-core.o
|
||||
obj-$(CONFIG_PHY_FSL_LYNX_10G) += phy-fsl-lynx-10g.o
|
||||
obj-$(CONFIG_PHY_FSL_LYNX_28G) += phy-fsl-lynx-28g.o
|
||||
obj-$(CONFIG_PHY_FSL_SAMSUNG_HDMI_PHY) += phy-fsl-samsung-hdmi.o
|
||||
|
|
|
|||
1321
drivers/phy/freescale/phy-fsl-lynx-10g.c
Normal file
1321
drivers/phy/freescale/phy-fsl-lynx-10g.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -11,6 +11,12 @@ const char *lynx_lane_mode_str(enum lynx_lane_mode lane_mode)
|
|||
switch (lane_mode) {
|
||||
case LANE_MODE_1000BASEX_SGMII:
|
||||
return "1000Base-X/SGMII";
|
||||
case LANE_MODE_2500BASEX:
|
||||
return "2500Base-X";
|
||||
case LANE_MODE_QSGMII:
|
||||
return "QSGMII";
|
||||
case LANE_MODE_10G_QXGMII:
|
||||
return "10G-QXGMII";
|
||||
case LANE_MODE_10GBASER:
|
||||
return "10GBase-R";
|
||||
case LANE_MODE_USXGMII:
|
||||
|
|
@ -29,6 +35,12 @@ enum lynx_lane_mode phy_interface_to_lane_mode(phy_interface_t intf)
|
|||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
return LANE_MODE_1000BASEX_SGMII;
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
return LANE_MODE_2500BASEX;
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
return LANE_MODE_QSGMII;
|
||||
case PHY_INTERFACE_MODE_10G_QXGMII:
|
||||
return LANE_MODE_10G_QXGMII;
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
return LANE_MODE_10GBASER;
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
|
|
@ -89,6 +101,29 @@ bool lynx_lane_supports_mode(struct lynx_lane *lane, enum lynx_lane_mode mode)
|
|||
}
|
||||
EXPORT_SYMBOL_NS_GPL(lynx_lane_supports_mode, "PHY_FSL_LYNX");
|
||||
|
||||
/* The quad protocols are fixed because the lane has multiple consumers, and
|
||||
* one phy_set_mode_ext() affects the other consumers as well. We have no use
|
||||
* case for dynamic protocol changing here, so disallow it.
|
||||
*/
|
||||
static enum lynx_lane_mode lynx_fixed_protocols[] = {
|
||||
LANE_MODE_QSGMII,
|
||||
LANE_MODE_10G_QXGMII,
|
||||
};
|
||||
|
||||
static bool lynx_lane_restrict_fixed_mode_change(struct lynx_lane *lane,
|
||||
enum lynx_lane_mode new)
|
||||
{
|
||||
enum lynx_lane_mode curr = lane->mode;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(lynx_fixed_protocols); i++)
|
||||
if ((curr == lynx_fixed_protocols[i] ||
|
||||
new == lynx_fixed_protocols[i]) &&
|
||||
curr != new)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Translate the mode/submode from phy_validate() and phy_set_mode_ext() to a
|
||||
* lane_mode and return 0 if it is supported and we can transition to it from
|
||||
* the current lane mode, or return negative error otherwise.
|
||||
|
|
@ -112,6 +147,9 @@ int lynx_phy_mode_to_lane_mode(struct phy *phy, enum phy_mode mode,
|
|||
if (!lynx_lane_supports_mode(lane, tmp_lane_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (lynx_lane_restrict_fixed_mode_change(lane, tmp_lane_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (lane_mode)
|
||||
*lane_mode = tmp_lane_mode;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <soc/fsl/phy-fsl-lynx.h>
|
||||
|
||||
#define LYNX_NUM_PLL 2
|
||||
#define LYNX_QUIRK_HAS_HARDCODED_USXGMII BIT(0)
|
||||
|
||||
struct lynx_priv;
|
||||
struct lynx_lane;
|
||||
|
|
@ -36,6 +37,7 @@ struct lynx_lane {
|
|||
bool init;
|
||||
unsigned int id;
|
||||
enum lynx_lane_mode mode;
|
||||
u32 default_pccr[LANE_MODE_MAX];
|
||||
};
|
||||
|
||||
struct lynx_info {
|
||||
|
|
@ -48,6 +50,8 @@ struct lynx_info {
|
|||
void (*cdr_lock_check)(struct lynx_lane *lane);
|
||||
int first_lane;
|
||||
int num_lanes;
|
||||
int index;
|
||||
unsigned long quirks;
|
||||
};
|
||||
|
||||
struct lynx_priv {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,37 @@
|
|||
enum lynx_lane_mode {
|
||||
LANE_MODE_UNKNOWN,
|
||||
LANE_MODE_1000BASEX_SGMII,
|
||||
LANE_MODE_2500BASEX,
|
||||
LANE_MODE_QSGMII,
|
||||
LANE_MODE_10G_QXGMII,
|
||||
LANE_MODE_10GBASER,
|
||||
LANE_MODE_USXGMII,
|
||||
LANE_MODE_25GBASER,
|
||||
LANE_MODE_MAX,
|
||||
};
|
||||
|
||||
static inline bool lynx_lane_mode_uses_gmii_mac(enum lynx_lane_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case LANE_MODE_1000BASEX_SGMII:
|
||||
case LANE_MODE_2500BASEX:
|
||||
case LANE_MODE_QSGMII:
|
||||
case LANE_MODE_10G_QXGMII:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool lynx_lane_mode_uses_xgmii_mac(enum lynx_lane_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case LANE_MODE_10GBASER:
|
||||
case LANE_MODE_USXGMII:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __PHY_FSL_LYNX_H_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user