summaryrefslogtreecommitdiffstats
path: root/drivers/net/pcs/pcs-xpcs-wx.c
diff options
context:
space:
mode:
authorKees Cook <kees+treewide@kernel.org>2026-09-02 15:31:14 -0700
committerKees Cook <kees@kernel.org>2026-09-04 21:37:00 -0700
commit3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d (patch)
treec65086f9bdcd48c6360fb7cb4598bca084da1f32 /drivers/net/pcs/pcs-xpcs-wx.c
downloadlinux-stable-3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d.tar.gz
linux-stable-3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d.zip
treewide: refresh kmalloc_obj() conversionsgrafted
This is another run of the Coccinelle script for converting kmalloc() family of allocations to kmalloc_obj() via the existing rules in scripts/coccinelle/api/kmalloc_objs.cocci This catches both the set of kmalloc() uses added since the first kmalloc_obj() conversions in v7.0 and adds a large group missed in the first pass due to Coccinelle not interacting well with the cleanup.h scoped_...() family of macros[1]. I worked around this with spatch's "--macro-file" argument to a file with all the scoped_...() macros mapped to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control flow indicator I could find. Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc, riscv, and s390 with no new warnings. Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1] Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2] Signed-off-by: Kees Cook <kees+treewide@kernel.org>
Diffstat (limited to 'drivers/net/pcs/pcs-xpcs-wx.c')
-rw-r--r--drivers/net/pcs/pcs-xpcs-wx.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/net/pcs/pcs-xpcs-wx.c b/drivers/net/pcs/pcs-xpcs-wx.c
new file mode 100644
index 000000000..fc52f7aa5
--- /dev/null
+++ b/drivers/net/pcs/pcs-xpcs-wx.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/pcs/pcs-xpcs.h>
+#include <linux/mdio.h>
+#include "pcs-xpcs.h"
+
+/* VR_XS_PMA_MMD */
+#define TXGBE_PMA_MMD 0x8020
+#define TXGBE_TX_GENCTL1 0x11
+#define TXGBE_TX_GENCTL1_VBOOST_LVL GENMASK(10, 8)
+#define TXGBE_TX_GENCTL1_VBOOST_EN0 BIT(4)
+#define TXGBE_TX_GEN_CTL2 0x12
+#define TXGBE_TX_GEN_CTL2_TX0_WIDTH(v) FIELD_PREP(GENMASK(9, 8), v)
+#define TXGBE_TX_RATE_CTL 0x14
+#define TXGBE_TX_RATE_CTL_TX0_RATE(v) FIELD_PREP(GENMASK(2, 0), v)
+#define TXGBE_RX_GEN_CTL2 0x32
+#define TXGBE_RX_GEN_CTL2_RX0_WIDTH(v) FIELD_PREP(GENMASK(9, 8), v)
+#define TXGBE_RX_GEN_CTL3 0x33
+#define TXGBE_RX_GEN_CTL3_LOS_TRSHLD0 GENMASK(2, 0)
+#define TXGBE_RX_RATE_CTL 0x34
+#define TXGBE_RX_RATE_CTL_RX0_RATE(v) FIELD_PREP(GENMASK(1, 0), v)
+#define TXGBE_RX_EQ_ATTN_CTL 0x37
+#define TXGBE_RX_EQ_ATTN_LVL0 GENMASK(2, 0)
+#define TXGBE_RX_EQ_CTL0 0x38
+#define TXGBE_RX_EQ_CTL0_VGA1_GAIN(v) FIELD_PREP(GENMASK(15, 12), v)
+#define TXGBE_RX_EQ_CTL0_VGA2_GAIN(v) FIELD_PREP(GENMASK(11, 8), v)
+#define TXGBE_RX_EQ_CTL0_CTLE_POLE(v) FIELD_PREP(GENMASK(7, 5), v)
+#define TXGBE_RX_EQ_CTL0_CTLE_BOOST(v) FIELD_PREP(GENMASK(4, 0), v)
+#define TXGBE_RX_EQ_CTL4 0x3C
+#define TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0 BIT(4)
+#define TXGBE_RX_EQ_CTL4_CONT_ADAPT0 BIT(0)
+#define TXGBE_AFE_DFE_ENABLE 0x3D
+#define TXGBE_DFE_EN_0 BIT(4)
+#define TXGBE_AFE_EN_0 BIT(0)
+#define TXGBE_DFE_TAP_CTL0 0x3E
+#define TXGBE_MPLLA_CTL0 0x51
+#define TXGBE_MPLLA_CTL2 0x53
+#define TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN BIT(10)
+#define TXGBE_MPLLA_CTL2_DIV10_CLK_EN BIT(9)
+#define TXGBE_MPLLA_CTL3 0x57
+#define TXGBE_MISC_CTL0 0x70
+#define TXGBE_MISC_CTL0_PLL BIT(15)
+#define TXGBE_MISC_CTL0_CR_PARA_SEL BIT(14)
+#define TXGBE_MISC_CTL0_RX_VREF(v) FIELD_PREP(GENMASK(12, 8), v)
+#define TXGBE_VCO_CAL_LD0 0x72
+#define TXGBE_VCO_CAL_REF0 0x76
+
+static int txgbe_write_pma(struct dw_xpcs *xpcs, int reg, u16 val)
+{
+ return xpcs_write(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
+}
+
+static int txgbe_modify_pma(struct dw_xpcs *xpcs, int reg, u16 mask, u16 set)
+{
+ return xpcs_modify(xpcs, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, mask,
+ set);
+}
+
+static void txgbe_pma_config_10gbaser(struct dw_xpcs *xpcs)
+{
+ txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x21);
+ txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0);
+ txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1, TXGBE_TX_GENCTL1_VBOOST_LVL,
+ FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
+ txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
+ TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
+ txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x549);
+ txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x29);
+ txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, 0);
+ txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, 0);
+ txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(3));
+ txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(3));
+ txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV16P5_CLK_EN |
+ TXGBE_MPLLA_CTL2_DIV10_CLK_EN);
+
+ txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_CTLE_POLE(2) |
+ TXGBE_RX_EQ_CTL0_CTLE_BOOST(5));
+ txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
+ txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0xBE);
+ txgbe_modify_pma(xpcs, TXGBE_AFE_DFE_ENABLE,
+ TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0, 0);
+ txgbe_modify_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_ADAPT0,
+ 0);
+}
+
+static void txgbe_pma_config_1g(struct dw_xpcs *xpcs)
+{
+ txgbe_modify_pma(xpcs, TXGBE_TX_GENCTL1,
+ TXGBE_TX_GENCTL1_VBOOST_LVL |
+ TXGBE_TX_GENCTL1_VBOOST_EN0,
+ FIELD_PREP(TXGBE_TX_GENCTL1_VBOOST_LVL, 0x5));
+ txgbe_write_pma(xpcs, TXGBE_MISC_CTL0, TXGBE_MISC_CTL0_PLL |
+ TXGBE_MISC_CTL0_CR_PARA_SEL | TXGBE_MISC_CTL0_RX_VREF(0xF));
+
+ txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL0, TXGBE_RX_EQ_CTL0_VGA1_GAIN(7) |
+ TXGBE_RX_EQ_CTL0_VGA2_GAIN(7) | TXGBE_RX_EQ_CTL0_CTLE_BOOST(6));
+ txgbe_modify_pma(xpcs, TXGBE_RX_EQ_ATTN_CTL, TXGBE_RX_EQ_ATTN_LVL0, 0);
+ txgbe_write_pma(xpcs, TXGBE_DFE_TAP_CTL0, 0);
+ txgbe_modify_pma(xpcs, TXGBE_RX_GEN_CTL3, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0,
+ FIELD_PREP(TXGBE_RX_GEN_CTL3_LOS_TRSHLD0, 0x4));
+
+ txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL0, 0x20);
+ txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL3, 0x46);
+ txgbe_write_pma(xpcs, TXGBE_VCO_CAL_LD0, 0x540);
+ txgbe_write_pma(xpcs, TXGBE_VCO_CAL_REF0, 0x2A);
+ txgbe_write_pma(xpcs, TXGBE_AFE_DFE_ENABLE, 0);
+ txgbe_write_pma(xpcs, TXGBE_RX_EQ_CTL4, TXGBE_RX_EQ_CTL4_CONT_OFF_CAN0);
+ txgbe_write_pma(xpcs, TXGBE_TX_RATE_CTL, TXGBE_TX_RATE_CTL_TX0_RATE(3));
+ txgbe_write_pma(xpcs, TXGBE_RX_RATE_CTL, TXGBE_RX_RATE_CTL_RX0_RATE(3));
+ txgbe_write_pma(xpcs, TXGBE_TX_GEN_CTL2, TXGBE_TX_GEN_CTL2_TX0_WIDTH(1));
+ txgbe_write_pma(xpcs, TXGBE_RX_GEN_CTL2, TXGBE_RX_GEN_CTL2_RX0_WIDTH(1));
+ txgbe_write_pma(xpcs, TXGBE_MPLLA_CTL2, TXGBE_MPLLA_CTL2_DIV10_CLK_EN);
+}
+
+static int txgbe_pcs_poll_power_up(struct dw_xpcs *xpcs)
+{
+ int val, ret;
+
+ /* Wait xpcs power-up good */
+ ret = read_poll_timeout(xpcs_read_vpcs, val,
+ (val & DW_PSEQ_ST) == DW_PSEQ_ST_GOOD,
+ 10000, 1000000, false,
+ xpcs, DW_VR_XS_PCS_DIG_STS);
+ if (ret < 0)
+ dev_err(&xpcs->mdiodev->dev, "xpcs power-up timeout\n");
+
+ return ret;
+}
+
+static int txgbe_pma_init_done(struct dw_xpcs *xpcs)
+{
+ int val, ret;
+
+ xpcs_write_vpcs(xpcs, DW_VR_XS_PCS_DIG_CTRL1, DW_VR_RST | DW_EN_VSMMD1);
+
+ /* wait pma initialization done */
+ ret = read_poll_timeout(xpcs_read_vpcs, val, !(val & DW_VR_RST),
+ 100000, 10000000, false,
+ xpcs, DW_VR_XS_PCS_DIG_CTRL1);
+ if (ret < 0)
+ dev_err(&xpcs->mdiodev->dev, "xpcs pma initialization timeout\n");
+
+ return ret;
+}
+
+static bool txgbe_xpcs_mode_quirk(struct dw_xpcs *xpcs)
+{
+ int ret;
+
+ /* When txgbe do LAN reset, PCS will change to default 10GBASE-R mode */
+ ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL2);
+ ret &= MDIO_PCS_CTRL2_TYPE;
+ if ((ret == MDIO_PCS_CTRL2_10GBR &&
+ xpcs->interface != PHY_INTERFACE_MODE_10GBASER) ||
+ xpcs->interface == PHY_INTERFACE_MODE_SGMII)
+ return true;
+
+ return false;
+}
+
+int txgbe_xpcs_switch_mode(struct dw_xpcs *xpcs, phy_interface_t interface)
+{
+ int ret;
+
+ switch (interface) {
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ break;
+ default:
+ return 0;
+ }
+
+ if (xpcs->interface == interface && !txgbe_xpcs_mode_quirk(xpcs))
+ return 0;
+
+ xpcs->interface = interface;
+
+ ret = txgbe_pcs_poll_power_up(xpcs);
+ if (ret < 0)
+ return ret;
+
+ if (interface == PHY_INTERFACE_MODE_10GBASER) {
+ xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR);
+ xpcs_modify(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1,
+ MDIO_CTRL1_SPEED10G, MDIO_CTRL1_SPEED10G);
+ txgbe_pma_config_10gbaser(xpcs);
+ } else {
+ xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX);
+ xpcs_write(xpcs, MDIO_MMD_PMAPMD, MDIO_CTRL1, 0);
+ xpcs_write(xpcs, MDIO_MMD_PCS, MDIO_CTRL1, 0);
+ txgbe_pma_config_1g(xpcs);
+ }
+
+ return txgbe_pma_init_done(xpcs);
+}