summaryrefslogtreecommitdiff
path: root/drivers/phy/microchip/lan966x_serdes.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-10-08 02:03:01 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-10-08 02:03:01 +0300
commit33e591dee915832c618cf68bb1058c8e7d296128 (patch)
tree64e39a54a2949c0aad8787e3fd808dc3681e27ba /drivers/phy/microchip/lan966x_serdes.c
parent416a2f4f91525fcdec821320bc4608cf012d418e (diff)
parent9aa0dade8f6b4cdcbb114e1a06037939ee3238bc (diff)
downloadlinux-33e591dee915832c618cf68bb1058c8e7d296128.tar.xz
Merge tag 'phy-for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy
Pull phy updates from Vinod Koul: "This contains bunch of new device support and one new Sunplus driver along with updates which include another big round of qmp phy conversion. New support: - Qualcomm SC8280XP eDP & DP and USB3 UNI phy (Bjorn Andersson) - Rockchip rk3568 inno dsidphy (Chris Morgan) - ocelot-serdes phy yaml binding (Colin Foster) - Renesas gen2-usb phy yaml binding (Geert Uytterhoeven) - RGMII suport in lan966x driver (Horatiu Vultur) - Qualcomm SM6375 usb snps-femto-v2 bindings (Konrad Dybcio) - Rockchip rk356x csi-dphya (Michael Riesch) - Qualcomm sdm670 usb2 bindings (Richard Acayan) - Sunplus USB2 PHY (Vincent Shih) Updates: - Mediatek hdmi, ufs, tphy and xsphy updates to use bitfield helpers (Chunfeng Yun) - Continued Qualcomm qmp phy driver split and cleanup. More patches are under review and expected that next cycle might see completion of this activity (Dmitry Baryshkov & Johan Hovold) - TI wiz driver support for j7200 10g (Roger Quadros) - Qualcomm femto phy driver support for override params to help with tuning (Sandeep Maheswaram) - SGMII support in TI wiz driver (Siddharth Vadapalli) - dev_err_probe simplification (Yuan Can)" * tag 'phy-for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy: (170 commits) phy: phy-mtk-dp: make array driving_params static const dt-bindings: phy: qcom,qusb2: document sdm670 compatible phy: qcom-qmp-pcie: fix resource mapping for SDM845 QHP PHY phy: rockchip-snps-pcie3: only look for rockchip,pipe-grf on rk3588 phy: tegra: xusb: Enable usb role switch attribute phy: mediatek: fix build warning of FIELD_PREP() phy: qcom-qmp-usb: Use dev_err_probe() to simplify code phy: qcom-qmp-ufs: Use dev_err_probe() to simplify code phy: qcom-qmp-pcie-msm8996: Use dev_err_probe() to simplify code phy: qcom-qmp-combo: Use dev_err_probe() to simplify code phy: qualcomm: call clk_disable_unprepare in the error handling phy: intel: Use dev_err_probe() to simplify code phy: tegra: xusb: Use dev_err_probe() to simplify code phy: qcom-snps: Use dev_err_probe() to simplify code phy: qcom-qusb2: Use dev_err_probe() to simplify code phy: qcom-qmp-pcie: Use dev_err_probe() to simplify code phy: ti: phy-j721e-wiz: fix reference leaks in wiz_probe() phy: mediatek: mipi: remove register access helpers phy: mediatek: mipi: mt8183: use common helper to access registers phy: mediatek: mipi: mt8183: use GENMASK to generate bits mask ...
Diffstat (limited to 'drivers/phy/microchip/lan966x_serdes.c')
-rw-r--r--drivers/phy/microchip/lan966x_serdes.c99
1 files changed, 87 insertions, 12 deletions
diff --git a/drivers/phy/microchip/lan966x_serdes.c b/drivers/phy/microchip/lan966x_serdes.c
index d1a50fa81130..c1a41b6cd29b 100644
--- a/drivers/phy/microchip/lan966x_serdes.c
+++ b/drivers/phy/microchip/lan966x_serdes.c
@@ -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);
@@ -427,7 +499,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;
}
@@ -437,6 +511,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,
};