phy: Add RGMII support on lan966x
The serdes driver contains also a mux to decide which interface type to use. Currently the driver supports GMII/SGMII/QSGMII and partially RGMII. As it doesn't support all the other RGMII interfaces like RGMII_TXID/RXID/ID and it could run only at 1G. Therefore extend this for all the other speeds(10/100) and also allow the other interfaces. Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com> Link: https://lore.kernel.org/r/20220901121455.245103-1-horatiu.vultur@microchip.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
f340ed8664
commit
b013110733
|
@ -42,7 +42,10 @@
|
|||
#define SERDES_MUX_QSGMII(i, p, m, c) \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c)
|
||||
#define SERDES_MUX_RGMII(i, p, m, c) \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c)
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII, m, c), \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_TXID, m, c), \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_RXID, m, c), \
|
||||
SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_RGMII_ID, m, c)
|
||||
|
||||
static void lan_rmw_(u32 val, u32 mask, void __iomem *mem, u32 offset)
|
||||
{
|
||||
|
@ -94,21 +97,29 @@ static const struct serdes_mux lan966x_serdes_muxes[] = {
|
|||
HSIO_HW_CFG_SD6G_1_CFG_SET(1)),
|
||||
|
||||
SERDES_MUX_RGMII(RGMII(0), 2, HSIO_HW_CFG_RGMII_0_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0))),
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_0_CFG_SET(0) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(2))),
|
||||
SERDES_MUX_RGMII(RGMII(1), 3, HSIO_HW_CFG_RGMII_1_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1))),
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_1_CFG_SET(0) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(3))),
|
||||
SERDES_MUX_RGMII(RGMII(0), 5, HSIO_HW_CFG_RGMII_0_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_0_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0))),
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(5))),
|
||||
SERDES_MUX_RGMII(RGMII(1), 6, HSIO_HW_CFG_RGMII_1_CFG |
|
||||
HSIO_HW_CFG_RGMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_ENA |
|
||||
HSIO_HW_CFG_GMII_ENA,
|
||||
HSIO_HW_CFG_RGMII_1_CFG_SET(BIT(0)) |
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1))),
|
||||
HSIO_HW_CFG_RGMII_ENA_SET(BIT(1)) |
|
||||
HSIO_HW_CFG_GMII_ENA_SET(BIT(6))),
|
||||
};
|
||||
|
||||
struct serdes_ctrl {
|
||||
|
@ -382,6 +393,67 @@ static int lan966x_sd6g40_setup(struct serdes_macro *macro, u32 idx, int mode)
|
|||
return lan966x_sd6g40_setup_lane(macro, conf, idx);
|
||||
}
|
||||
|
||||
static int lan966x_rgmii_setup(struct serdes_macro *macro, u32 idx, int mode)
|
||||
{
|
||||
bool tx_delay = false;
|
||||
bool rx_delay = false;
|
||||
|
||||
/* Configure RGMII */
|
||||
lan_rmw(HSIO_RGMII_CFG_RGMII_RX_RST_SET(0) |
|
||||
HSIO_RGMII_CFG_RGMII_TX_RST_SET(0) |
|
||||
HSIO_RGMII_CFG_TX_CLK_CFG_SET(macro->speed == SPEED_1000 ? 1 :
|
||||
macro->speed == SPEED_100 ? 2 :
|
||||
macro->speed == SPEED_10 ? 3 : 0),
|
||||
HSIO_RGMII_CFG_RGMII_RX_RST |
|
||||
HSIO_RGMII_CFG_RGMII_TX_RST |
|
||||
HSIO_RGMII_CFG_TX_CLK_CFG,
|
||||
macro->ctrl->regs, HSIO_RGMII_CFG(idx));
|
||||
|
||||
if (mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_TXID)
|
||||
rx_delay = true;
|
||||
|
||||
if (mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_RXID)
|
||||
tx_delay = true;
|
||||
|
||||
/* Setup DLL configuration */
|
||||
lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) |
|
||||
HSIO_DLL_CFG_DLL_ENA_SET(rx_delay),
|
||||
HSIO_DLL_CFG_DLL_RST |
|
||||
HSIO_DLL_CFG_DLL_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2));
|
||||
|
||||
lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(rx_delay),
|
||||
HSIO_DLL_CFG_DELAY_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x0 : 0x2));
|
||||
|
||||
lan_rmw(HSIO_DLL_CFG_DLL_RST_SET(0) |
|
||||
HSIO_DLL_CFG_DLL_ENA_SET(tx_delay),
|
||||
HSIO_DLL_CFG_DLL_RST |
|
||||
HSIO_DLL_CFG_DLL_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3));
|
||||
|
||||
lan_rmw(HSIO_DLL_CFG_DELAY_ENA_SET(tx_delay),
|
||||
HSIO_DLL_CFG_DELAY_ENA,
|
||||
macro->ctrl->regs, HSIO_DLL_CFG(idx == 0 ? 0x1 : 0x3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_set_speed(struct phy *phy, int speed)
|
||||
{
|
||||
struct serdes_macro *macro = phy_get_drvdata(phy);
|
||||
|
||||
if (!phy_interface_mode_is_rgmii(macro->mode))
|
||||
return 0;
|
||||
|
||||
macro->speed = speed;
|
||||
lan966x_rgmii_setup(macro, macro->idx - (SERDES6G_MAX + 1), macro->mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
||||
{
|
||||
struct serdes_macro *macro = phy_get_drvdata(phy);
|
||||
|
@ -424,7 +496,9 @@ static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
|||
macro->mode);
|
||||
|
||||
if (macro->idx < RGMII_MAX)
|
||||
return 0;
|
||||
return lan966x_rgmii_setup(macro,
|
||||
macro->idx - (SERDES6G_MAX + 1),
|
||||
macro->mode);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -434,6 +508,7 @@ static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
|||
|
||||
static const struct phy_ops serdes_ops = {
|
||||
.set_mode = serdes_set_mode,
|
||||
.set_speed = serdes_set_speed,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
|
|
@ -206,4 +206,46 @@ enum lan966x_target {
|
|||
#define HSIO_HW_CFG_QSGMII_ENA_GET(x)\
|
||||
FIELD_GET(HSIO_HW_CFG_QSGMII_ENA, x)
|
||||
|
||||
/* HSIO:HW_CFGSTAT:RGMII_CFG */
|
||||
#define HSIO_RGMII_CFG(r) __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 20, r, 2, 4)
|
||||
|
||||
#define HSIO_RGMII_CFG_TX_CLK_CFG GENMASK(4, 2)
|
||||
#define HSIO_RGMII_CFG_TX_CLK_CFG_SET(x)\
|
||||
FIELD_PREP(HSIO_RGMII_CFG_TX_CLK_CFG, x)
|
||||
#define HSIO_RGMII_CFG_TX_CLK_CFG_GET(x)\
|
||||
FIELD_GET(HSIO_RGMII_CFG_TX_CLK_CFG, x)
|
||||
|
||||
#define HSIO_RGMII_CFG_RGMII_TX_RST BIT(1)
|
||||
#define HSIO_RGMII_CFG_RGMII_TX_RST_SET(x)\
|
||||
FIELD_PREP(HSIO_RGMII_CFG_RGMII_TX_RST, x)
|
||||
#define HSIO_RGMII_CFG_RGMII_TX_RST_GET(x)\
|
||||
FIELD_GET(HSIO_RGMII_CFG_RGMII_TX_RST, x)
|
||||
|
||||
#define HSIO_RGMII_CFG_RGMII_RX_RST BIT(0)
|
||||
#define HSIO_RGMII_CFG_RGMII_RX_RST_SET(x)\
|
||||
FIELD_PREP(HSIO_RGMII_CFG_RGMII_RX_RST, x)
|
||||
#define HSIO_RGMII_CFG_RGMII_RX_RST_GET(x)\
|
||||
FIELD_GET(HSIO_RGMII_CFG_RGMII_RX_RST, x)
|
||||
|
||||
/* HSIO:HW_CFGSTAT:DLL_CFG */
|
||||
#define HSIO_DLL_CFG(r) __REG(TARGET_HSIO, 0, 1, 104, 0, 1, 52, 36, r, 4, 4)
|
||||
|
||||
#define HSIO_DLL_CFG_DELAY_ENA BIT(2)
|
||||
#define HSIO_DLL_CFG_DELAY_ENA_SET(x)\
|
||||
FIELD_PREP(HSIO_DLL_CFG_DELAY_ENA, x)
|
||||
#define HSIO_DLL_CFG_DELAY_ENA_GET(x)\
|
||||
FIELD_GET(HSIO_DLL_CFG_DELAY_ENA, x)
|
||||
|
||||
#define HSIO_DLL_CFG_DLL_ENA BIT(1)
|
||||
#define HSIO_DLL_CFG_DLL_ENA_SET(x)\
|
||||
FIELD_PREP(HSIO_DLL_CFG_DLL_ENA, x)
|
||||
#define HSIO_DLL_CFG_DLL_ENA_GET(x)\
|
||||
FIELD_GET(HSIO_DLL_CFG_DLL_ENA, x)
|
||||
|
||||
#define HSIO_DLL_CFG_DLL_RST BIT(0)
|
||||
#define HSIO_DLL_CFG_DLL_RST_SET(x)\
|
||||
FIELD_PREP(HSIO_DLL_CFG_DLL_RST, x)
|
||||
#define HSIO_DLL_CFG_DLL_RST_GET(x)\
|
||||
FIELD_GET(HSIO_DLL_CFG_DLL_RST, x)
|
||||
|
||||
#endif /* _LAN966X_HSIO_REGS_H_ */
|
||||
|
|
Loading…
Reference in New Issue