diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/net/calxedaxgmac.c | 2 | ||||
| -rw-r--r-- | drivers/net/dwc_eth_qos_adi.c | 2 | ||||
| -rw-r--r-- | drivers/net/dwc_eth_xgmac.c | 2 | ||||
| -rw-r--r-- | drivers/net/fsl-mc/mc.c | 45 | ||||
| -rw-r--r-- | drivers/net/fsl_enetc.c | 57 | ||||
| -rw-r--r-- | drivers/net/fsl_enetc.h | 1 | ||||
| -rw-r--r-- | drivers/net/fsl_enetc_xpcs_phy.c | 970 | ||||
| -rw-r--r-- | drivers/net/macb.c | 94 | ||||
| -rw-r--r-- | drivers/net/macb.h | 2 | ||||
| -rw-r--r-- | drivers/net/phy/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/net/phy/adin.c | 13 | ||||
| -rw-r--r-- | drivers/net/phy/airoha/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/phy/airoha/air_en8811.c | 60 | ||||
| -rw-r--r-- | drivers/net/phy/aquantia.c | 2 | ||||
| -rw-r--r-- | drivers/net/phy/dp83867.c | 16 | ||||
| -rw-r--r-- | drivers/net/phy/mscc.c | 11 | ||||
| -rw-r--r-- | drivers/net/qe/dm_qe_uec_phy.c | 2 | ||||
| -rw-r--r-- | drivers/net/sandbox.c | 2 | ||||
| -rw-r--r-- | drivers/net/sni_netsec.c | 2 | ||||
| -rw-r--r-- | drivers/net/ti/cpsw.c | 188 | ||||
| -rw-r--r-- | drivers/net/xilinx_axi_emac.c | 20 | ||||
| -rw-r--r-- | drivers/net/zynq_gem.c | 61 |
23 files changed, 1405 insertions, 158 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ed07e286676..666618681df 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -339,7 +339,7 @@ config ESSEDMA config ETH_SANDBOX depends on SANDBOX - depends on NET || NET_LWIP + depends on NET default y bool "Sandbox: Mocked Ethernet driver" help @@ -350,7 +350,7 @@ config ETH_SANDBOX config ETH_SANDBOX_RAW depends on SANDBOX - depends on NET + depends on NET_LEGACY default y bool "Sandbox: Bridge to Linux Raw Sockets" help @@ -476,7 +476,7 @@ config FTMAC100 config FTGMAC100 bool "Ftgmac100 Ethernet Support" select PHYLIB - depends on NET + depends on NET_LEGACY help This driver supports the Faraday's FTGMAC100 Gigabit SoC Ethernet controller that can be found on Aspeed SoCs (which diff --git a/drivers/net/calxedaxgmac.c b/drivers/net/calxedaxgmac.c index ebb399457fb..92990fa6d47 100644 --- a/drivers/net/calxedaxgmac.c +++ b/drivers/net/calxedaxgmac.c @@ -597,7 +597,7 @@ static const struct udevice_id xgmac_eth_ids[] = { { } }; -U_BOOT_DRIVER(eth_xgmac) = { +U_BOOT_DRIVER(calxeda_hb_xgmac) = { .name = "eth_xgmac", .id = UCLASS_ETH, .of_match = xgmac_eth_ids, diff --git a/drivers/net/dwc_eth_qos_adi.c b/drivers/net/dwc_eth_qos_adi.c index b578225eaad..37db8525b48 100644 --- a/drivers/net/dwc_eth_qos_adi.c +++ b/drivers/net/dwc_eth_qos_adi.c @@ -15,7 +15,7 @@ #include <reset.h> #include <linux/io.h> -#include <asm/arch-adi/sc5xx/sc5xx.h> +#include <asm/arch/sc5xx.h> #include "dwc_eth_qos.h" diff --git a/drivers/net/dwc_eth_xgmac.c b/drivers/net/dwc_eth_xgmac.c index 2ab5ec5f0d9..311b57011c3 100644 --- a/drivers/net/dwc_eth_xgmac.c +++ b/drivers/net/dwc_eth_xgmac.c @@ -1206,7 +1206,7 @@ static const struct udevice_id xgmac_ids[] = { { } }; -U_BOOT_DRIVER(eth_xgmac) = { +U_BOOT_DRIVER(dwc_eth_xgmac) = { .name = "eth_xgmac", .id = UCLASS_ETH, .of_match = of_match_ptr(xgmac_ids), diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index c8ed702f50a..e28f8d96ed7 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2014 Freescale Semiconductor, Inc. - * Copyright 2017-2018, 2020-2021 NXP + * Copyright 2017-2018, 2020-2021, 2025 NXP */ #include <config.h> #include <command.h> @@ -72,6 +72,7 @@ static u64 mc_lazy_dpl_addr; static u32 dpsparser_obj_id; static u16 dpsparser_handle; static char *mc_err_msg_apply_spb[] = MC_ERROR_MSG_APPLY_SPB; +static bool wait_for_dpl; #ifdef DEBUG void dump_ram_words(const char *title, void *addr) @@ -653,7 +654,7 @@ static int load_mc_aiop_img(u64 aiop_fw_addr) } #endif -static int wait_for_mc(bool booting_mc, u32 *final_reg_gsr) +static int wait_for_mc(u32 *final_reg_gsr) { u32 reg_gsr; u32 mc_fw_boot_status; @@ -792,7 +793,7 @@ int mc_init(u64 mc_fw_addr, u64 mc_dpc_addr) * Deassert reset and release MC core 0 to run */ out_le32(&mc_ccsr_regs->reg_gcr1, GCR1_P1_DE_RST | GCR1_M_ALL_DE_RST); - error = wait_for_mc(true, ®_gsr); + error = wait_for_mc(®_gsr); if (error != 0) goto out; @@ -855,13 +856,20 @@ int mc_apply_dpl(u64 mc_dpl_addr) * Tell the MC to deploy the DPL: */ out_le32(&mc_ccsr_regs->reg_gsr, 0x0); - printf("fsl-mc: Deploying data path layout ... "); - error = wait_for_mc(false, ®_gsr); - if (!error) - mc_dpl_applied = 0; + /* Wait for the MC firmware to finish processing the DPL */ + if (wait_for_dpl) { + printf("fsl-mc: Deploying data path layout ... "); + error = wait_for_mc(®_gsr); + if (error) + return error; + } else { + printf("fsl-mc: Started the DPL deploy process\n"); + } - return error; + mc_dpl_applied = 0; + + return 0; } int get_mc_boot_status(void) @@ -1995,6 +2003,11 @@ static int do_fsl_mc(struct cmd_tbl *cmdtp, int flag, int argc, * later from announce_and_cleanup(). */ mc_lazy_dpl_addr = mc_dpl_addr; + + wait_for_dpl = true; + if (argc >= 5 && strcmp(argv[4], "nowait") == 0) + wait_for_dpl = false; + break; } @@ -2023,6 +2036,10 @@ static int do_fsl_mc(struct cmd_tbl *cmdtp, int flag, int argc, mc_apply_addr = simple_strtoull(argv[3], NULL, 16); + wait_for_dpl = true; + if (argc >= 5 && strcmp(argv[4], "nowait") == 0) + wait_for_dpl = false; + /* The user wants DPL applied now */ if (!fsl_mc_ldpaa_exit(NULL)) err = mc_apply_dpl(mc_apply_addr); @@ -2070,12 +2087,12 @@ static int do_fsl_mc(struct cmd_tbl *cmdtp, int flag, int argc, U_BOOT_CMD( fsl_mc, CONFIG_SYS_MAXARGS, 1, do_fsl_mc, "DPAA2 command to manage Management Complex (MC)", - "start mc [FW_addr] [DPC_addr] - Start Management Complex\n" - "fsl_mc apply DPL [DPL_addr] - Apply DPL file\n" - "fsl_mc lazyapply DPL [DPL_addr] - Apply DPL file on exit\n" - "fsl_mc apply spb [spb_addr] - Apply SPB Soft Parser Blob\n" - "fsl_mc start aiop [FW_addr] - Start AIOP\n" - "fsl_mc dump_log - Dump MC Log\n" + "fsl_mc start mc <fw_addr> <DPC_addr> - Start the Management Complex firmware\n" + "fsl_mc apply dpl <dpl_addr> [nowait] - Apply the DPL (Data Path Layout) file\n" + "fsl_mc lazyapply dpl <DPL_addr> [nowait] - Apply the DPL (Data Path Layout) file on exit\n" + "fsl_mc apply spb <spb_addr> - Apply the SPB Soft Parser Blob\n" + "fsl_mc start aiop <fw_addr> - Start AIOP\n" + "fsl_mc dump_log - Dump the MC Log\n" ); void mc_env_boot(void) diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index a4ba27904bc..206f1a381bb 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -8,6 +8,7 @@ #include <clk.h> #include <cpu_func.h> #include <dm.h> +#include <dm/device_compat.h> #include <errno.h> #include <fdt_support.h> #include <malloc.h> @@ -20,14 +21,21 @@ #include <linux/bug.h> #include <linux/delay.h> #include <linux/build_bug.h> +#include <linux/bitfield.h> +#include <power/regulator.h> +#include "fsl_enetc.h" #ifdef CONFIG_ARCH_IMX9 #include <asm/mach-imx/sys_proto.h> #include <cpu_func.h> +#include "fsl_enetc_xpcs_phy.c" +#else +static inline int xpcs_phy_usxgmii_pma_config(struct udevice *dev) +{ + return 0; +} #endif -#include "fsl_enetc.h" - #define ENETC_DRIVER_NAME "enetc_eth" /* @@ -454,19 +462,23 @@ static void enetc_setup_mac_iface(struct udevice *dev, /* set up serdes for SXGMII */ static int enetc_init_sxgmii(struct udevice *dev) { - struct enetc_priv *priv = dev_get_priv(dev); - if (!enetc_has_imdio(dev)) return 0; - /* Dev ability - SXGMII */ - enetc_mdio_write(&priv->imdio, ENETC_PCS_PHY_ADDR, ENETC_PCS_DEVAD_REPL, - ENETC_PCS_DEV_ABILITY, ENETC_PCS_DEV_ABILITY_SXGMII); + if (enetc_is_imx95(dev)) { + xpcs_phy_usxgmii_pma_config(dev); + } else { + struct enetc_priv *priv = dev_get_priv(dev); + + /* Dev ability - SXGMII */ + enetc_mdio_write(&priv->imdio, ENETC_PCS_PHY_ADDR, ENETC_PCS_DEVAD_REPL, + ENETC_PCS_DEV_ABILITY, ENETC_PCS_DEV_ABILITY_SXGMII); - /* Restart PCS AN */ - enetc_mdio_write(&priv->imdio, ENETC_PCS_PHY_ADDR, ENETC_PCS_DEVAD_REPL, - ENETC_PCS_CR, - ENETC_PCS_CR_RST | ENETC_PCS_CR_RESET_AN); + /* Restart PCS AN */ + enetc_mdio_write(&priv->imdio, ENETC_PCS_PHY_ADDR, ENETC_PCS_DEVAD_REPL, + ENETC_PCS_CR, + ENETC_PCS_CR_RST | ENETC_PCS_CR_RESET_AN); + } return 0; } @@ -523,6 +535,10 @@ static int enetc_config_phy(struct udevice *dev) return -ENODEV; supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full; + + if (enetc_is_imx95(dev)) + supported |= PHY_10G_FEATURES; + priv->phy->supported &= supported; priv->phy->advertising &= supported; @@ -537,12 +553,31 @@ static int enetc_probe(struct udevice *dev) { struct enetc_priv *priv = dev_get_priv(dev); int res; + struct udevice *supply = NULL; if (ofnode_valid(dev_ofnode(dev)) && !ofnode_is_enabled(dev_ofnode(dev))) { enetc_dbg(dev, "interface disabled\n"); return -ENODEV; } + if (CONFIG_IS_ENABLED(DM_REGULATOR)) { + res = device_get_supply_regulator(dev, "serdes-supply", + &supply); + if (res && res != -ENOENT) { + printf("%s: device_get_supply_regulator failed: %d\n", + __func__, res); + return res; + } + + if (supply) { + res = regulator_set_enable_if_allowed(supply, true); + if (res) { + printf("%s: Error enabling phy supply\n", dev->name); + return res; + } + } + } + priv->enetc_txbd = memalign(ENETC_BD_ALIGN, sizeof(struct enetc_tx_bd) * ENETC_BD_CNT); priv->enetc_rxbd = memalign(ENETC_BD_ALIGN, diff --git a/drivers/net/fsl_enetc.h b/drivers/net/fsl_enetc.h index 804df853bf5..6d868e82f8c 100644 --- a/drivers/net/fsl_enetc.h +++ b/drivers/net/fsl_enetc.h @@ -205,6 +205,7 @@ struct enetc_data { /* PCS / internal SoC PHY ID, it defaults to 0 on all interfaces */ #define ENETC_PCS_PHY_ADDR 0 +#define ENETC_NON_PCS_PHY_ADDR 16 /* PCS registers */ #define ENETC_PCS_CR 0x00 diff --git a/drivers/net/fsl_enetc_xpcs_phy.c b/drivers/net/fsl_enetc_xpcs_phy.c new file mode 100644 index 00000000000..4039690223d --- /dev/null +++ b/drivers/net/fsl_enetc_xpcs_phy.c @@ -0,0 +1,970 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2024 NXP + */ + +#define XPCS_PHY_GLOBAL 0x0 +#define XPCS_PHY_MPLLA 0x1 +#define XPCS_PHY_MPLLB 0x2 +#define XPCS_PHY_LANE 0x3 +#define XPCS_PHY_MAC_ADAPTER 0x1f + +#define XPCS_PHY_REG(x) (((x) & 0x1fffe) >> 1) + +/* MAC ADAPTER */ +#define MAC_ADAPTER_LOCK_PHY 0x200 +#define MAC_ADAPTER_LOCK_MPLLA 0x204 +#define MAC_ADAPTER_LOCK_MPLLB 0x208 +#define MAC_ADAPTER_LOCK_ROM 0x20c +#define MAC_ADAPTER_LOCK_RAM 0x210 +#define MAC_ADAPTER_LOCK_EVENT 0x214 + +#define MAC_ADAPTER_LOCK_LOCK BIT(7) + +/* PMA */ +#define PMA_RX_LSTS 0x10040 +#define PMA_RX_LSTS_RX_VALID_0 BIT(12) +#define PMA_MP_12G_16G_25G_TX_GENCTRL0 0x10060 +#define PMA_TX_GENCTRL0_TX_RST_0 BIT(8) +#define PMA_TX_GENCTRL0_TX_DT_EN_0 BIT(12) +#define PMA_MP_12G_16G_25G_TX_GENCTRL1 0x10062 +#define PMA_TX_GENCTRL1_VBOOST_EN_0 BIT(4) +#define PMA_TX_GENCTRL1_VBOOST_LVL_MASK GENMASK(10, 8) +#define PMA_TX_GENCTRL1_VBOOST_LVL(x) (((x) << 8) & GENMASK(10, 8)) +#define PMA_TX_GENCTRL1_TX_CLK_RDY_0 BIT(12) +#define PMA_MP_12G_16G_TX_GENCTRL2 0x10064 +#define PMA_TX_GENCTRL2_TX_REQ_0 BIT(0) +#define PMA_TX_GENCTRL2_TX0_WIDTH_MASK GENMASK(9, 8) +#define PMA_TX_GENCTRL2_TX0_WIDTH(x) (((x) << 8) & GENMASK(9, 8)) +#define PMA_MP_12G_16G_25G_TX_BOOST_CTRL 0x10066 +#define PMA_TX_BOOST_CTRL_TX0_IBOOST_MASK GENMASK(3, 0) +#define PMA_TX_BOOST_CTRL_TX0_IBOOST(x) ((x) & GENMASK(3, 0)) +#define PMA_MP_12G_16G_25G_TX_RATE_CTRL 0x10068 +#define PMA_TX_RATE_CTRL_TX0_RATE_MASK GENMASK(2, 0) +#define PMA_TX_RATE_CTRL_TX0_RATE(x) ((x) & GENMASK(2, 0)) +#define PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL 0x1006A +#define PMA_POWER_STATE_CTRL_TX0_PSTATE_MASK GENMASK(1, 0) +#define PMA_POWER_STATE_CTRL_TX0_PSTATE(x) ((x) & GENMASK(1, 0)) +#define PMA_POWER_STATE_CTRL_TX_DISABLE_0 BIT(8) +#define PMA_MP_12G_16G_25G_TX_EQ_CTRL0 0x1006C +#define PMA_TX_EQ_CTRL0_TX_EQ_PRE_MASK GENMASK(5, 0) +#define PMA_TX_EQ_CTRL0_TX_EQ_PRE(x) ((x) & GENMASK(5, 0)) +#define PMA_TX_EQ_CTRL0_TX_EQ_MAIN_MASK GENMASK(13, 8) +#define PMA_TX_EQ_CTRL0_TX_EQ_MAIN(x) (((x) << 8) & GENMASK(13, 8)) +#define PMA_MP_12G_16G_25G_TX_EQ_CTRL1 0x1006E +#define PMA_TX_EQ_CTRL1_TX_EQ_POST_MASK GENMASK(5, 0) +#define PMA_TX_EQ_CTRL1_TX_EQ_POST(x) ((x) & GENMASK(5, 0)) +#define PMA_MP_16G_25G_TX_MISC_CTRL0 0x1007C +#define PMA_TX_MISC_CTRL0_TX0_MISC_MASK GENMASK(7, 0) +#define PMA_TX_MISC_CTRL0_TX0_MISC(x) ((x) & GENMASK(7, 0)) +#define PMA_MP_12G_16G_25G_RX_GENCTRL0 0x100A0 +#define PMA_RX_GENCTRL0_RX_DT_EN_0 BIT(8) +#define PMA_MP_12G_16G_25G_RX_GENCTRL1 0x100A2 +#define PMA_RX_GENCTRL1_RX_RST_0 BIT(4) +#define PMA_RX_GENCTRL1_RX_TERM_ACDC_0 BIT(8) +#define PMA_RX_GENCTRL1_RX_DIV16P5_CLK_EN_0 BIT(12) +#define PMA_MP_12G_16G_RX_GENCTRL2 0x100A4 +#define PMA_RX_GENCTRL2_RX_REQ_0 BIT(0) +#define PMA_RX_GENCTRL2_RX0_WIDTH_MASK GENMASK(9, 8) +#define PMA_RX_GENCTRL2_RX0_WIDTH(x) (((x) << 8) & GENMASK(9, 8)) +#define PMA_MP_12G_16G_RX_GENCTRL3 0x100A6 +#define PMA_RX_GENCTRL3_LOS_TRSHLD_0_MASK GENMASK(2, 0) +#define PMA_RX_GENCTRL3_LOS_TRSHLD_0(x) ((x) & GENMASK(2, 0)) +#define PMA_RX_GENCTRL3_LOS_LFPS_EN_0 BIT(12) +#define PMA_MP_12G_16G_25G_RX_RATE_CTRL 0x100A8 +#define PMA_RX_RATE_CTRL_RX0_RATE_MASK GENMASK(1, 0) +#define PMA_RX_RATE_CTRL_RX0_RATE(x) ((x) & GENMASK(1, 0)) +#define PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL 0x100AA +#define PMA_RX_POWER_STATE_CTRL_RX0_PSTATE_MASK GENMASK(1, 0) +#define PMA_RX_POWER_STATE_CTRL_RX0_PSTATE(x) ((x) & GENMASK(1, 0)) +#define PMA_RX_POWER_STATE_CTRL_RX_DISABLE_0 BIT(8) +#define PMA_MP_12G_16G_25G_RX_CDR_CTRL 0x100AC +#define PMA_RX_CDR_CTRL_CDR_SSC_EN_0 BIT(4) +#define PMA_MP_12G_16G_25G_RX_ATTN_CTRL 0x100AE +#define PMA_RX_ATTN_CTRL_RX0_EQ_ATT_LVL_MASK GENMASK(2, 0) +#define PMA_RX_ATTN_CTRL_RX0_EQ_ATT_LVL(x) ((x) & GENMASK(2, 0)) +#define PMA_MP_16G_25G_RX_EQ_CTRL0 0x100B0 +#define PMA_RX_EQ_CTRL0_CTLE_BOOST_0_MASK GENMASK(4, 0) +#define PMA_RX_EQ_CTRL0_CTLE_BOOST_0(x) ((x) & GENMASK(4, 0)) +#define PMA_RX_EQ_CTRL0_CTLE_POLE_0_MASK GENMASK(6, 5) +#define PMA_RX_EQ_CTRL0_CTLE_POLE_0(x) (((x) << 5) & GENMASK(6, 5)) +#define PMA_RX_EQ_CTRL0_VGA2_GAIN_0_MASK GENMASK(10, 8) +#define PMA_RX_EQ_CTRL0_VGA2_GAIN_0(x) (((x) << 8) & GENMASK(10, 8)) +#define PMA_RX_EQ_CTRL0_VGA1_GAIN_0_MASK GENMASK(14, 12) +#define PMA_RX_EQ_CTRL0_VGA1_GAIN_0(x) (((x) << 12) & GENMASK(14, 12)) +#define PMA_MP_12G_16G_25G_RX_EQ_CTRL4 0x100B8 +#define PMA_RX_EQ_CTRL4_CONT_ADAPT_0 BIT(0) +#define PMA_RX_EQ_CTRL4_RX_AD_REQ BIT(12) +#define PMA_MP_16G_25G_RX_EQ_CTRL5 0x100BA +#define PMA_RX_EQ_CTRL5_RX_ADPT_SEL_0 BIT(0) +#define PMA_RX_EQ_CTRL5_RX0_ADPT_MODE_MASK GENMASK(5, 4) +#define PMA_RX_EQ_CTRL5_RX0_ADPT_MODE(x) (((x) << 4) & GENMASK(5, 4)) +#define PMA_MP_12G_16G_25G_DFE_TAP_CTRL0 0x100BC +#define PMA_DFE_TAP_CTRL0_DFE_TAP1_0_MASK GENMASK(7, 0) +#define PMA_DFE_TAP_CTRL0_DFE_TAP1_0(x) ((x) & GENMASK(7, 0)) +#define PMA_MP_16G_RX_CDR_CTRL1 0x100C8 +#define PMA_RX_CDR_CTRL1_VCO_TEMP_COMP_EN_0 BIT(0) +#define PMA_RX_CDR_CTRL1_VCO_STEP_CTRL_0 BIT(4) +#define PMA_RX_CDR_CTRL1_VCO_FRQBAND_0_MASK GENMASK(9, 8) +#define PMA_RX_CDR_CTRL1_VCO_FRQBAND_0(x) (((x) << 8) & GENMASK(9, 8)) +#define PMA_MP_16G_25G_RX_PPM_CTRL0 0x100CA +#define PMA_RX_PPM_CTRL0_RX0_CDR_PPM_MAX_MASK GENMASK(4, 0) +#define PMA_RX_PPM_CTRL0_RX0_CDR_PPM_MAX(x) ((x) & GENMASK(4, 0)) +#define PMA_MP_16G_25G_RX_GENCTRL4 0x100D0 +#define PMA_RX_GENCTRL4_RX_DFE_BYP_0 BIT(8) +#define PMA_MP_16G_25G_RX_MISC_CTRL0 0x100D2 +#define PMA_RX_MISC_CTRL0_RX0_MISC_MASK GENMASK(7, 0) +#define PMA_RX_MISC_CTRL0_RX0_MISC(x) ((x) & GENMASK(7, 0)) +#define PMA_MP_16G_25G_RX_IQ_CTRL0 0x100D6 +#define PMA_RX_IQ_CTRL0_RX0_MARGIN_IQ_MASK GENMASK(6, 0) +#define PMA_RX_IQ_CTRL0_RX0_MARGIN_IQ(x) ((x) & GENMASK(6, 0)) +#define PMA_RX_IQ_CTRL0_RX0_DELTA_IQ_MASK GENMASK(11, 8) +#define PMA_RX_IQ_CTRL0_RX0_DELTA_IQ(x) (((x) << 8) & GENMASK(11, 8)) +#define PMA_MP_12G_16G_25G_MPLL_CMN_CTRL 0x100E0 +#define PMA_MPLL_CMN_CTRL_MPLL_EN_0 BIT(0) +#define PMA_MPLL_CMN_CTRL_MPLLB_SEL_0 BIT(4) +#define PMA_MP_12G_16G_MPLLA_CTRL0 0x100E2 +#define PMA_MPLLA_CTRL0_MPLLA_MULTIPLIER_MASK GENMASK(7, 0) +#define PMA_MPLLA_CTRL0_MPLLA_MULTIPLIER(x) ((x) & GENMASK(7, 0)) +#define PMA_MP_16G_MPLLA_CTRL1 0x100E4 +#define PMA_MPLLA_CTRL1_MPLLA_SSC_EN BIT(0) +#define PMA_MPLLA_CTRL1_MPLLA_SSC_CLK_SEL BIT(4) +#define PMA_MPLLA_CTRL1_MPLLA_FRACN_CTRL_MASK GENMASK(15, 5) +#define PMA_MPLLA_CTRL1_MPLLA_FRACN_CTRL(x) (((x) << 5) & GENMASK(15, 5)) +#define PMA_MP_12G_16G_MPLLA_CTRL2 0x100E6 +#define PMA_MPLLA_CTRL2_MPLLA_DIV_MULT_MASK GENMASK(6, 0) +#define PMA_MPLLA_CTRL2_MPLLA_DIV_MULT(x) ((x) & GENMASK(6, 0)) +#define PMA_MPLLA_CTRL2_MPLLA_DIV_CLK_EN BIT(7) +#define PMA_MPLLA_CTRL2_MPLLA_DIV8_CLK_EN BIT(8) +#define PMA_MPLLA_CTRL2_MPLLA_DIV10_CLK_EN BIT(9) +#define PMA_MPLLA_CTRL2_MPLLA_DIV16P5_CLK_EN BIT(10) +#define PMA_MPLLA_CTRL2_MPLLA_TX_CLK_DIV_MASK GENMASK(12, 11) +#define PMA_MPLLA_CTRL2_MPLLA_TX_CLK_DIV(x) (((x) << 11) & GENMASK(12, 11)) +#define PMA_MP_16G_MPLLA_CTRL3 0x100EE +#define PMA_MPLLA_CTRL3_MPLLA_BANDWIDTH_MASK GENMASK(15, 0) +#define PMA_MPLLA_CTRL3_MPLLA_BANDWIDTH(x) ((x) & GENMASK(15, 0)) +#define PMA_MP_16G_MPLLA_CTRL4 0x100F2 +#define PMA_MPLLA_CTRL4_MPLLA_SSC_FRQ_CNT_INT_MASK GENMASK(11, 0) +#define PMA_MPLLA_CTRL4_MPLLA_SSC_FRQ_CNT_INT(x) ((x) & GENMASK(11, 0)) +#define PMA_MP_16G_MPLLA_CTRL5 0x100F4 +#define PMA_MPLLA_CTRL5_MPLLA_SSC_FRQ_CNT_PK_MASK GENMASK(7, 0) +#define PMA_MPLLA_CTRL5_MPLLA_SSC_FRQ_CNT_PK(x) ((x) & GENMASK(7, 0)) +#define PMA_MPLLA_CTRL5_MPLLA_SSC_SPD_EN BIT(8) +#define PMA_MP_12G_16G_25G_MISC_CTRL0 0x10120 +#define PMA_MISC_CTRL0_RX_VREF_CTRL_MASK GENMASK(12, 8) +#define PMA_MISC_CTRL0_RX_VREF_CTRL(x) (((x) << 8) & GENMASK(12, 8)) +#define PMA_MP_12G_16G_25G_REF_CLK_CTRL 0x10122 +#define PMA_REF_CLK_CTRL_REF_CLK_DIV2 BIT(2) +#define PMA_REF_CLK_CTRL_REF_RANGE_MASK GENMASK(5, 3) +#define PMA_REF_CLK_CTRL_REF_RANGE(x) (((x) << 3) & GENMASK(5, 3)) +#define PMA_REF_CLK_CTRL_REF_MPLLA_DIV2 BIT(6) +#define PMA_MP_12G_16G_25G_VCO_CAL_LD0 0x10124 +#define PMA_VCO_CAL_LD0_VCO_LD_VAL_0_MASK GENMASK(12, 0) +#define PMA_VCO_CAL_LD0_VCO_LD_VAL_0(x) ((x) & GENMASK(12, 0)) +#define PMA_MP_16G_25G_VCO_CAL_REF0 0x1012C +#define PMA_VCO_CAL_REF0_VCO_REF_LD_0_MASK GENMASK(6, 0) +#define PMA_VCO_CAL_REF0_VCO_REF_LD_0(x) ((x) & GENMASK(6, 0)) +#define PMA_MP_12G_16G_25G_MISC_STS 0x10130 +#define PMA_MISC_STS_RX_ADPT_ACK BIT(12) +#define PMA_MP_12G_16G_25G_SRAM 0x10136 +#define PMA_SRAM_INIT_DN BIT(0) +#define PMA_SRAM_EXT_LD_DN BIT(1) +#define PMA_MP_16G_25G_MISC_CTRL2 0x10138 +#define PMA_MISC_CTRL2_SUP_MISC_MASK GENMASK(7, 0) +#define PMA_MISC_CTRL2_SUP_MISC(x) ((x) & GENMASK(7, 0)) + +/* PCS */ +#define PCS_CTRL1 0x0 +#define PCS_CTRL1_RESET BIT(15) +#define PCS_CTRL2 0xE +#define PCS_CTRL2_PCS_TYPE_SEL_MASK GENMASK(3, 0) +#define PCS_CTRL2_PCS_TYPE_SEL(x) ((x) & GENMASK(3, 0)) +#define PCS_DIG_CTRL1 0x10000 +#define PCS_DIG_CTRL1_USXG_EN BIT(9) +#define PCS_DIG_CTRL1_USRA_RST BIT(10) +#define PCS_DIG_CTRL1_VR_RST BIT(15) +#define PCS_DEBUG_CTRL 0x1000A +#define PCS_DEBUG_CTRL_SUPRESS_LOS_DET BIT(4) +#define PCS_DEBUG_CTRL_RX_DT_EN_CTL BIT(6) +#define PCS_DEBUG_CTRL_TX_PMBL_CTL BIT(8) +#define PCS_KR_CTRL1 0x1000E +#define PCS_KR_CTRL1_USXG_MODE_MASK GENMASK(12, 10) +#define PCS_KR_CTRL1_USXG_MODE(x) (((x) << 10) & GENMASK(12, 10)) + +/* VS MII MMD */ +#define MII_CTRL 0x0 +#define MII_CTRL_SS5 BIT(5) +#define MII_CTRL_SS6 BIT(6) +#define MII_CTRL_AN_ENABLE BIT(12) +#define MII_CTRL_SS13 BIT(13) +#define MII_DIG_CTRL1 0x10000 +#define MII_DIG_CTRL1_CL37_TMR_OVR_RIDE BIT(3) +#define MII_AN_CTRL 0x10002 +#define MII_AN_CTRL_MII_AN_INTR_EN BIT(0) +#define MII_AN_CTRL_TX_CONFIG BIT(3) +#define MII_AN_INTR_STS 0x10004 +#define MII_AN_INTR_STS_CL37_ANCMPLT_INTR BIT(0) +#define MII_LINK_TIMER_CTRL 0x10014 +#define MII_LINK_TIMER_CTRL_CL37_LINK_TIME_MASK GENMASK(15, 0) +#define MII_LINK_TIMER_CTRL_CL37_LINK_TIME(x) ((x) & GENMASK(15, 0)) + +/* E16 MEM MAP */ +#define IDCODE_LO 0x0 +#define IDCODE_HI 0x4 +#define GLOBAL_CTRL_EX_0 0x114 +#define GLOBAL_CTRL_EX_0_PHY_SRAM_BYPASS BIT(0) +#define L0_RX_VCO_OVRD_OUT_0 0x20c +#define L0_RX_VCO_OVRD_OUT_0_RX_ANA_CDR_FREQ_TUNE_MASK GENMASK(12, 3) +#define L0_RX_VCO_OVRD_OUT_0_RX_ANA_CDR_FREQ_TUNE(x) (((x) << 3) & GENMASK(12, 3)) +#define L0_RX_VCO_OVRD_OUT_0_RX_CDR_FREQ_TUNE_OVRD_EN BIT(15) +#define L0_RX_VCO_OVRD_OUT_2 0x214 +#define L0_RX_VCO_OVRD_OUT_2_RX_ANA_CDR_FREQ_TUNE_CLK BIT(0) + +static int enetc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg); +static int enetc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, u16 val); + +int xpcs_read(struct udevice *dev, int devaddr, u32 reg) +{ + struct enetc_priv *priv = dev_get_priv(dev); + + return enetc_mdio_read(&priv->imdio, ENETC_PCS_PHY_ADDR, devaddr, reg); +} + +int xpcs_write(struct udevice *dev, int devaddr, u32 reg, u16 val) +{ + struct enetc_priv *priv = dev_get_priv(dev); + + return enetc_mdio_write(&priv->imdio, ENETC_PCS_PHY_ADDR, devaddr, reg, val); +} + +int xpcs_phy_read(struct udevice *dev, int devaddr, u32 reg) +{ + struct enetc_priv *priv = dev_get_priv(dev); + + return enetc_mdio_read(&priv->imdio, ENETC_NON_PCS_PHY_ADDR, devaddr, reg); +} + +int xpcs_phy_write(struct udevice *dev, int devaddr, u32 reg, u16 val) +{ + struct enetc_priv *priv = dev_get_priv(dev); + + return enetc_mdio_write(&priv->imdio, ENETC_NON_PCS_PHY_ADDR, devaddr, reg, val); +} + +int xpcs_phy_read_pma(struct udevice *dev, u32 reg) +{ + return xpcs_read(dev, MDIO_MMD_PMAPMD, XPCS_PHY_REG(reg)); +} + +int xpcs_phy_write_pma(struct udevice *dev, int reg, u16 val) +{ + return xpcs_write(dev, MDIO_MMD_PMAPMD, XPCS_PHY_REG(reg), val); +} + +int xpcs_phy_usxgmii_init_seq_2(struct udevice *dev) +{ + ulong begin; + u16 val; + + /* Seq 2.1 Keep preamble data */ + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DEBUG_CTRL)); + val |= PCS_DEBUG_CTRL_TX_PMBL_CTL; + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DEBUG_CTRL), val); + + /* Seq 2.2 Power up MPLLA to P1 state */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL); + val = u16_replace_bits(val, 2, PMA_POWER_STATE_CTRL_TX0_PSTATE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL); + val |= PMA_MPLL_CMN_CTRL_MPLL_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL, val); + + /* Seq 2.3 Assert request of transmitand receive */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + val |= PMA_TX_GENCTRL2_TX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + val |= PMA_RX_GENCTRL2_RX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2, val); + + /* Seq 2.4 Poll for acknowledge */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PMA_TX_GENCTRL2_TX_REQ_0); + + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PMA_RX_GENCTRL2_RX_REQ_0); + + /* Seq 2.5 Turn transmit to P0 state */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL); + val = u16_replace_bits(val, 0, PMA_POWER_STATE_CTRL_TX0_PSTATE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0); + val &= ~PMA_TX_GENCTRL0_TX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL); + val &= ~PMA_POWER_STATE_CTRL_TX_DISABLE_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL); + val |= PMA_MPLL_CMN_CTRL_MPLL_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL, val); + + /* Seq 2.6 Turn receive to P0 state */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1); + val &= ~PMA_RX_GENCTRL1_RX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL); + val &= ~PMA_RX_POWER_STATE_CTRL_RX0_PSTATE_MASK; + val &= ~PMA_RX_POWER_STATE_CTRL_RX_DISABLE_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL); + val &= ~PMA_RX_POWER_STATE_CTRL_RX0_PSTATE_MASK; + val &= ~PMA_RX_POWER_STATE_CTRL_RX_DISABLE_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL, val); + + /* Seq 2.7 Enable transmitter output driver in the PHY */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0); + val |= PMA_TX_GENCTRL0_TX_DT_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0, val); + + /* Seq 2.8 Enable receiver data output from PHY */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL0); + val |= PMA_RX_GENCTRL0_RX_DT_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL0, val); + + /* Seq 2.9 Assert request of transmit and receive */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + val |= PMA_TX_GENCTRL2_TX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + val |= PMA_RX_GENCTRL2_RX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2, val); + + /* Seq 2.10 Poll for acknowledge */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + schedule(); + } while (val & PMA_TX_GENCTRL2_TX_REQ_0); + + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + schedule(); + } while (val & PMA_RX_GENCTRL2_RX_REQ_0); + + return 0; + +timeout: + return -ETIMEDOUT; +} + +void xpcs_phy_reg_lock(struct udevice *dev) +{ + u16 val; + ulong begin; + + if (xpcs_phy_read(dev, XPCS_PHY_MAC_ADAPTER, XPCS_PHY_REG(MAC_ADAPTER_LOCK_PHY)) & MAC_ADAPTER_LOCK_LOCK) + return; + + xpcs_phy_write(dev, XPCS_PHY_MAC_ADAPTER, XPCS_PHY_REG(MAC_ADAPTER_LOCK_PHY), MAC_ADAPTER_LOCK_LOCK); + xpcs_phy_write(dev, XPCS_PHY_MAC_ADAPTER, XPCS_PHY_REG(MAC_ADAPTER_LOCK_MPLLA), MAC_ADAPTER_LOCK_LOCK); + xpcs_phy_write(dev, XPCS_PHY_MAC_ADAPTER, XPCS_PHY_REG(MAC_ADAPTER_LOCK_MPLLB), MAC_ADAPTER_LOCK_LOCK); + xpcs_phy_write(dev, XPCS_PHY_MAC_ADAPTER, XPCS_PHY_REG(MAC_ADAPTER_LOCK_ROM), MAC_ADAPTER_LOCK_LOCK); + xpcs_phy_write(dev, XPCS_PHY_MAC_ADAPTER, XPCS_PHY_REG(MAC_ADAPTER_LOCK_RAM), MAC_ADAPTER_LOCK_LOCK); + + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_SRAM); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (!(val & PMA_SRAM_INIT_DN)); + + /* Work around */ + // xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_SRAM, PMA_SRAM_EXT_LD_DN); + xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_0), GLOBAL_CTRL_EX_0_PHY_SRAM_BYPASS); + + begin = get_timer(0); + do { + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_CTRL1)); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PCS_CTRL1_RESET); + + mdelay(1); + +timeout: + return; +} + +int xpcs_phy_usxgmii_pma_config(struct udevice *dev) +{ + ulong begin; + u16 val; + + xpcs_phy_reg_lock(dev); + + /* 1.6 Turn off C37 auto-negotiation */ + val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL)); + val &= ~MII_CTRL_AN_ENABLE; + xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL), val); + + /* 1.7 Assert tx_reset and rx_reset*/ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0); + val |= PMA_TX_GENCTRL0_TX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1); + val |= PMA_RX_GENCTRL1_RX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1, val); + + /* 1.8 Wait for more than 1us */ + udelay(5); + + /* 1.9 Deassert tx_reset and rx_reset*/ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0); + val &= ~PMA_TX_GENCTRL0_TX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1); + val &= ~PMA_RX_GENCTRL1_RX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1, val); + + /* 1.10 Power down MPLLA */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL); + val = u16_replace_bits(val, 3, PMA_POWER_STATE_CTRL_TX0_PSTATE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL); + val &= ~PMA_MPLL_CMN_CTRL_MPLL_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0); + val &= ~PMA_TX_GENCTRL0_TX_DT_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL0, val); + + /* 1.11 Change RX0 power state to P2 */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL0); + val &= ~PMA_RX_GENCTRL0_RX_DT_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL0, val); + + /* TODO: check if it is needed */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL); + val = u16_replace_bits(val, 1, PMA_RX_POWER_STATE_CTRL_RX0_PSTATE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL); + val = u16_replace_bits(val, 3, PMA_RX_POWER_STATE_CTRL_RX0_PSTATE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL, val); + + /* 1.12 Assert request of transmit and receive */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + val |= PMA_TX_GENCTRL2_TX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + val |= PMA_RX_GENCTRL2_RX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2, val); + + /* 1.13 Poll for acknlowledge */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PMA_TX_GENCTRL2_TX_REQ_0); + + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PMA_RX_GENCTRL2_RX_REQ_0); + + /* 2 Config MPLL for 10G XGMII */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_REF_CLK_CTRL); + val = u16_replace_bits(val, 6, PMA_REF_CLK_CTRL_REF_RANGE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_REF_CLK_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_REF_CLK_CTRL); + val &= ~PMA_REF_CLK_CTRL_REF_CLK_DIV2; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_REF_CLK_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_REF_CLK_CTRL); + val |= PMA_REF_CLK_CTRL_REF_MPLLA_DIV2; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_REF_CLK_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val &= ~PMA_MPLLA_CTRL2_MPLLA_DIV8_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val |= PMA_MPLLA_CTRL2_MPLLA_DIV10_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val |= PMA_MPLLA_CTRL2_MPLLA_DIV16P5_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val &= ~PMA_MPLLA_CTRL2_MPLLA_TX_CLK_DIV_MASK; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val |= PMA_MPLLA_CTRL2_MPLLA_DIV_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val = u16_replace_bits(val, 5, PMA_MPLLA_CTRL2_MPLLA_DIV_MULT_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_MPLLA_CTRL1); + val &= ~PMA_MPLLA_CTRL1_MPLLA_SSC_EN; + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_MPLLA_CTRL1); + val &= ~PMA_MPLLA_CTRL1_MPLLA_SSC_CLK_SEL; + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_MPLLA_CTRL5); + val &= ~PMA_MPLLA_CTRL5_MPLLA_SSC_FRQ_CNT_PK_MASK; + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL5, val); + + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL4, 0); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_MPLLA_CTRL5); + val &= ~PMA_MPLLA_CTRL5_MPLLA_SSC_SPD_EN; + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL5, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_MPLLA_CTRL1); + val &= ~PMA_MPLLA_CTRL1_MPLLA_FRACN_CTRL_MASK; + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL0); + val = u16_replace_bits(val, 33, PMA_MPLLA_CTRL0_MPLLA_MULTIPLIER_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1); + val = u16_replace_bits(val, 5, PMA_TX_GENCTRL1_VBOOST_LVL_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1, val); + + val = PMA_MPLLA_CTRL3_MPLLA_BANDWIDTH(0xA016); + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL3, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_MISC_CTRL0); + val = u16_replace_bits(val, 0x11, PMA_MISC_CTRL0_RX_VREF_CTRL_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_MISC_CTRL0, val); + + val = PMA_MISC_CTRL2_SUP_MISC(1); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_MISC_CTRL2, val); + + val = PMA_VCO_CAL_REF0_VCO_REF_LD_0(0x29); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_VCO_CAL_REF0, val); + + val = PMA_VCO_CAL_LD0_VCO_LD_VAL_0(0x549); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_VCO_CAL_LD0, val); + + val = PMA_RX_PPM_CTRL0_RX0_CDR_PPM_MAX(0x12); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_PPM_CTRL0, val); + + /* 3 Configure LANE0 for 10G XGMII */ + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_TX_MISC_CTRL0, 0x0); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_RATE_CTRL, 0x0); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL); + val &= ~PMA_MPLL_CMN_CTRL_MPLLB_SEL_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_MPLL_CMN_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + val = u16_replace_bits(val, 3, PMA_TX_GENCTRL2_TX0_WIDTH_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1); + val |= PMA_TX_GENCTRL1_VBOOST_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1, val); + + val = PMA_TX_BOOST_CTRL_TX0_IBOOST(0xf); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_BOOST_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_EQ_CTRL0); + val = u16_replace_bits(val, 0, PMA_TX_EQ_CTRL0_TX_EQ_PRE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_EQ_CTRL0, val); + + val = PMA_TX_EQ_CTRL1_TX_EQ_POST(0x20); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_EQ_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_EQ_CTRL0); + val = u16_replace_bits(val, 0x20, PMA_TX_EQ_CTRL0_TX_EQ_MAIN_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_EQ_CTRL0, val); + + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_RATE_CTRL, 0x0); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0); + val = u16_replace_bits(val, 0x2, PMA_RX_EQ_CTRL0_CTLE_POLE_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0); + val = u16_replace_bits(val, 0x10, PMA_RX_EQ_CTRL0_CTLE_BOOST_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL3); + val = u16_replace_bits(val, 0x7, PMA_RX_GENCTRL3_LOS_TRSHLD_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL3, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_RX_CDR_CTRL1); + val |= PMA_RX_CDR_CTRL1_VCO_STEP_CTRL_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_RX_CDR_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_RX_CDR_CTRL1); + val |= PMA_RX_CDR_CTRL1_VCO_TEMP_COMP_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_RX_CDR_CTRL1, val); + + val = PMA_RX_MISC_CTRL0_RX0_MISC(0x12); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_MISC_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + val = u16_replace_bits(val, 0x3, PMA_RX_GENCTRL2_RX0_WIDTH_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1); + val |= PMA_RX_GENCTRL1_RX_DIV16P5_CLK_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1, val); + + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_CDR_CTRL, 0x0); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL3); + val &= ~PMA_RX_GENCTRL3_LOS_LFPS_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL3, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_GENCTRL4); + val &= ~PMA_RX_GENCTRL4_RX_DFE_BYP_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_GENCTRL4, val); + + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_ATTN_CTRL, 0x0); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0); + val = u16_replace_bits(val, 0x5, PMA_RX_EQ_CTRL0_VGA1_GAIN_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0); + val = u16_replace_bits(val, 0x5, PMA_RX_EQ_CTRL0_VGA2_GAIN_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0, val); + + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_DFE_TAP_CTRL0, 0x0); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_RX_CDR_CTRL1); + val = u16_replace_bits(val, 0x1, PMA_RX_CDR_CTRL1_VCO_FRQBAND_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_RX_CDR_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1); + val |= PMA_RX_GENCTRL1_RX_TERM_ACDC_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_IQ_CTRL0); + val = u16_replace_bits(val, 0x0, PMA_RX_IQ_CTRL0_RX0_DELTA_IQ_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_IQ_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL5); + val &= ~PMA_RX_EQ_CTRL5_RX_ADPT_SEL_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL5, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL5); + val = u16_replace_bits(val, 0x3, PMA_RX_EQ_CTRL5_RX0_ADPT_MODE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL5, val); + + /* 4 Configure XPCS for 10G XGMII */ + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_CTRL2), 0x0); + + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DIG_CTRL1)); + val |= PCS_DIG_CTRL1_USXG_EN; + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DIG_CTRL1), val); + + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_KR_CTRL1)); + val = u16_replace_bits(val, 0x0, PCS_KR_CTRL1_USXG_MODE_MASK); + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_KR_CTRL1), val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL0); + val = u16_replace_bits(val, 0x21, PMA_MPLLA_CTRL0_MPLLA_MULTIPLIER_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL0, val); + + val = PMA_MPLLA_CTRL3_MPLLA_BANDWIDTH(0xA016); + xpcs_phy_write_pma(dev, PMA_MP_16G_MPLLA_CTRL3, val); + + val = PMA_VCO_CAL_LD0_VCO_LD_VAL_0(0x549); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_VCO_CAL_LD0, val); + + val = PMA_VCO_CAL_REF0_VCO_REF_LD_0(0x29); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_VCO_CAL_REF0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_EQ_CTRL4); + val |= PMA_RX_EQ_CTRL4_CONT_ADAPT_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_EQ_CTRL4, val); + + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_RATE_CTRL, 0x0); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_RATE_CTRL, 0x0); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2); + val = u16_replace_bits(val, 0x3, PMA_TX_GENCTRL2_TX0_WIDTH_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_TX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + val = u16_replace_bits(val, 0x3, PMA_RX_GENCTRL2_RX0_WIDTH_MASK); + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val |= PMA_MPLLA_CTRL2_MPLLA_DIV16P5_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val |= PMA_MPLLA_CTRL2_MPLLA_DIV10_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2); + val &= ~PMA_MPLLA_CTRL2_MPLLA_DIV8_CLK_EN; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_MPLLA_CTRL2, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1); + val |= PMA_TX_GENCTRL1_VBOOST_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0); + val = u16_replace_bits(val, 0x10, PMA_RX_EQ_CTRL0_CTLE_BOOST_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_RX_CDR_CTRL1); + val |= PMA_RX_CDR_CTRL1_VCO_STEP_CTRL_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_RX_CDR_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_RX_CDR_CTRL1); + val |= PMA_RX_CDR_CTRL1_VCO_TEMP_COMP_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_RX_CDR_CTRL1, val); + + val = PMA_RX_MISC_CTRL0_RX0_MISC(0x12); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_MISC_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_GENCTRL4); + val &= ~PMA_RX_GENCTRL4_RX_DFE_BYP_0; + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_GENCTRL4, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_RX_CDR_CTRL1); + val = u16_replace_bits(val, 0x1, PMA_RX_CDR_CTRL1_VCO_FRQBAND_0_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_RX_CDR_CTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_IQ_CTRL0); + val = u16_replace_bits(val, 0x0, PMA_RX_IQ_CTRL0_RX0_DELTA_IQ_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_IQ_CTRL0, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL5); + val = u16_replace_bits(val, 0x3, PMA_RX_EQ_CTRL5_RX0_ADPT_MODE_MASK); + xpcs_phy_write_pma(dev, PMA_MP_16G_25G_RX_EQ_CTRL5, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1); + val &= ~PMA_TX_GENCTRL1_TX_CLK_RDY_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1, val); + + /* 5 Assert soft reset */ + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DIG_CTRL1)); + val |= PCS_DIG_CTRL1_VR_RST; + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DIG_CTRL1), val); + + /* 6 Poll for SRAM initialization done */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_SRAM); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (!(val & PMA_SRAM_INIT_DN)); + + /* 7 Assert SRAM external loading done */ + /* Workaround */ + // xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_SRAM, PMA_SRAM_EXT_LD_DN); + xpcs_phy_write(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(GLOBAL_CTRL_EX_0), GLOBAL_CTRL_EX_0_PHY_SRAM_BYPASS); + + /* 8 Poll for vendor-specific soft reset */ + begin = get_timer(0); + do { + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DIG_CTRL1)); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PCS_DIG_CTRL1_VR_RST); + + /* 9 Turn receive to P0 state */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1); + val &= ~PMA_RX_GENCTRL1_RX_RST_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL1, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL); + val &= ~PMA_RX_POWER_STATE_CTRL_RX_DISABLE_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL, val); + + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL); + val &= ~PMA_RX_POWER_STATE_CTRL_RX0_PSTATE_MASK; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_POWER_STATE_CTRL, val); + + /* 10 Enable receiver data output from PHY */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL0); + val |= PMA_RX_GENCTRL0_RX_DT_EN_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_GENCTRL0, val); + + /* 11 Assert request of receive */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + val |= PMA_RX_GENCTRL2_RX_REQ_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2, val); + + /* 11.1 Poll for acknowledge */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_RX_GENCTRL2); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (val & PMA_RX_GENCTRL2_RX_REQ_0); + + /* 12 Assert TX0 clock is active and stable */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1); + val |= PMA_TX_GENCTRL1_TX_CLK_RDY_0; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_TX_GENCTRL1, val); + + /* + * 13.1 Configure XPCS to consider Loss-of-Signal indicated by the + * PHY while evaluating the receive link status + */ + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DEBUG_CTRL)); + val |= PCS_DEBUG_CTRL_SUPRESS_LOS_DET; + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DEBUG_CTRL), val); + /* + * 13.2 Configure XPCS to deassert "receiver data enable" on + * detecting of Loss-of-Signal + */ + val = xpcs_read(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DEBUG_CTRL)); + val |= PCS_DEBUG_CTRL_RX_DT_EN_CTL; + xpcs_write(dev, MDIO_MMD_PCS, XPCS_PHY_REG(PCS_DEBUG_CTRL), val); + + /* 14 Poll for DPLL lock status for Lane 0 */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_RX_LSTS); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (!(val & PMA_RX_LSTS_RX_VALID_0)); + + /* 15 Assert request of receive adaptation */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_EQ_CTRL4); + val |= PMA_RX_EQ_CTRL4_RX_AD_REQ; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_EQ_CTRL4, val); + + /* 16 Poll for acknowledge */ + begin = get_timer(0); + do { + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_MISC_STS); + if (get_timer(begin) > 500) { + dev_err(dev, "Polling timeout, line: %d\n", __LINE__); + goto timeout; + } + mdelay(10); + } while (!(val & PMA_MISC_STS_RX_ADPT_ACK)); + + /* 17 Deassert request of receive adaptation */ + val = xpcs_phy_read_pma(dev, PMA_MP_12G_16G_25G_RX_EQ_CTRL4); + val &= ~PMA_RX_EQ_CTRL4_RX_AD_REQ; + xpcs_phy_write_pma(dev, PMA_MP_12G_16G_25G_RX_EQ_CTRL4, val); + + /* 18 Set the value of Config_Reg to 0 for Clause 37 autonegotiation. */ + val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_AN_CTRL)); + val &= ~MII_AN_CTRL_TX_CONFIG; + xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_AN_CTRL), val); + + /* 19 Select XGMII speed */ + val = xpcs_read(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL)); + val &= ~MII_CTRL_SS5; + val |= MII_CTRL_SS6 | MII_CTRL_SS13; + xpcs_write(dev, MDIO_MMD_VEND2, XPCS_PHY_REG(MII_CTRL), val); + + val = xpcs_phy_usxgmii_init_seq_2(dev); + if (val) + return val; + + return 0; + +timeout: + return -ETIMEDOUT; +} + +u32 xpcs_phy_get_id(struct udevice *dev) +{ + int ret; + u32 id; + + /* First, search C73 PCS using PCS MMD */ + ret = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(IDCODE_HI)); + if (ret < 0) + return 0xffffffff; + + id = ret << 16; + + ret = xpcs_phy_read(dev, XPCS_PHY_GLOBAL, XPCS_PHY_REG(IDCODE_LO)); + if (ret < 0) + return 0xffffffff; + + /* If Device IDs are not all zeros or all ones, + * we found C73 AN-type device + */ + if ((id | ret) && (id | ret) != 0xffffffff) + return id | ret; + + return 0xffffffff; +} diff --git a/drivers/net/macb.c b/drivers/net/macb.c index cbf5f605518..bea1dfed892 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -38,9 +38,13 @@ #include <linux/mii.h> #include <asm/io.h> #include <linux/dma-mapping.h> -#include <asm/arch/clk.h> #include <linux/errno.h> +/* Without CLK, we rely on the arch definition */ +#if !defined(CONFIG_CLK) +#include <asm/arch/clk.h> +#endif + #include "macb.h" DECLARE_GLOBAL_DATA_PTR; @@ -768,18 +772,40 @@ static int macb_phy_init(struct udevice *dev, const char *name) lpa); } else { /* if macb port is a fixed link */ - /* TODO : manage gigabit capable processors */ + const char *human_readable_speed; + speed = macb->speed; duplex = macb->duplex; + switch (speed) { + case 2: + human_readable_speed = "1000"; + break; + case 1: + human_readable_speed = "100"; + break; + case 0: + human_readable_speed = "10"; + break; + default: + printf("%s: speed %d not supported\n", name, speed); + return -EINVAL; + } printf("%s: link up, %sMbps %s-duplex\n", name, - speed ? "100" : "10", + human_readable_speed, duplex ? "full" : "half"); } ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); - if (speed) { + if (speed == 2) { + if (!gem_is_gigabit_capable(macb)) { + printf("%s: is not gigabit Ethernet capable\n", name); + return -EINVAL; + } + ncfgr |= GEM_BIT(GBE); + ret = macb_linkspd_cb(dev, _1000BASET); + } else if (speed == 1) { ncfgr |= MACB_BIT(SPD); ret = macb_linkspd_cb(dev, _100BASET); } else { @@ -923,26 +949,39 @@ static int _macb_init(struct udevice *dev, const char *name) /* Check the multi queue and initialize the queue for tx */ gmac_init_multi_queues(macb); - /* - * When the GMAC IP with GE feature, this bit is used to - * select interface between RGMII and GMII. - * When the GMAC IP without GE feature, this bit is used - * to select interface between RMII and MII. + /* This driver uses the user I/O to select the PHY features, + * but some GEM instances come with a fixed configuration and + * no USERIO. */ - if (macb->phy_interface == PHY_INTERFACE_MODE_RGMII || - macb->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || - macb->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID || - macb->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) - val = macb->config->usrio->rgmii; - else if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) - val = macb->config->usrio->rmii; - else if (macb->phy_interface == PHY_INTERFACE_MODE_MII) - val = macb->config->usrio->mii; + if (gem_readl(macb, DCFG1) & GEM_BIT(USERIO)) { + /* + * When the GMAC IP with GE feature, this bit is used to + * select interface between RGMII and GMII. + * When he GMAC IP without GE feature, this bit is used + * to select interface between RMII and MII. + */ + switch (macb->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + val = macb->config->usrio->rgmii; + break; + case PHY_INTERFACE_MODE_RMII: + val = macb->config->usrio->rmii; + break; + case PHY_INTERFACE_MODE_MII: + val = macb->config->usrio->mii; + break; + default: + break; + } - if (macb->config->caps & MACB_CAPS_USRIO_HAS_CLKEN) - val |= macb->config->usrio->clken; + if (macb->config->caps & MACB_CAPS_USRIO_HAS_CLKEN) + val |= macb->config->usrio->clken; - gem_writel(macb, USRIO, val); + gem_writel(macb, USRIO, val); + } if (macb->phy_interface == PHY_INTERFACE_MODE_SGMII) { unsigned int ncfgr = macb_readl(macb, NCFGR); @@ -1003,9 +1042,14 @@ static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr) /* set hardware address */ hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 | enetaddr[2] << 16 | enetaddr[3] << 24; - macb_writel(macb, SA1B, hwaddr_bottom); hwaddr_top = enetaddr[4] | enetaddr[5] << 8; - macb_writel(macb, SA1T, hwaddr_top); + if (macb_is_gem(macb)) { + gem_writel(macb, SA1B, hwaddr_bottom); + gem_writel(macb, SA1T, hwaddr_top); + } else { + macb_writel(macb, SA1B, hwaddr_bottom); + macb_writel(macb, SA1T, hwaddr_top); + } return 0; } @@ -1307,7 +1351,9 @@ static int macb_eth_of_to_plat(struct udevice *dev) macb->phy_addr = PHY_MAX_ADDR + 1; macb->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); speed_fdt = fdtdec_get_int(blob, fl_node, "speed", 0); - if (speed_fdt == 100) { + if (speed_fdt == 1000) { + macb->speed = 2; + } else if (speed_fdt == 100) { macb->speed = 1; } else if (speed_fdt == 10) { macb->speed = 0; diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 0eb90574618..002d5bd31b2 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -443,6 +443,8 @@ #define MACB_REV_SIZE 16 /* Bitfields in DCFG1. */ +#define GEM_USERIO_OFFSET 9 +#define GEM_USERIO_SIZE 1 #define GEM_IRQCOR_OFFSET 23 #define GEM_IRQCOR_SIZE 1 #define GEM_DBWDEF_OFFSET 25 diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 5d2277a4602..0025c895f12 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -7,7 +7,7 @@ config MV88E6352_SWITCH menuconfig PHYLIB bool "Ethernet PHY (physical media interface) support" - depends on NET || NET_LWIP + depends on NET help Enable Ethernet PHY (physical media interface) support. @@ -381,7 +381,7 @@ config PHY_FIXED config PHY_NCSI bool "NC-SI based PHY" - depends on NET + depends on NET_LEGACY endif #PHYLIB diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c index ce448810ff6..4d42e56dada 100644 --- a/drivers/net/phy/adin.c +++ b/drivers/net/phy/adin.c @@ -10,6 +10,7 @@ #include <linux/bitops.h> #include <linux/bitfield.h> +#define PHY_ID_ADIN1200 0x0283bc20 #define PHY_ID_ADIN1300 0x0283bc30 #define ADIN1300_EXT_REG_PTR 0x10 #define ADIN1300_EXT_REG_DATA 0x11 @@ -263,6 +264,18 @@ static int adin1300_config(struct phy_device *phydev) return genphy_config(phydev); } +U_BOOT_PHY_DRIVER(ADIN1200) = { + .name = "ADIN1200", + .uid = PHY_ID_ADIN1200, + .mask = 0xffffffff, + .features = PHY_BASIC_FEATURES, + .config = adin1300_config, + .startup = genphy_startup, + .shutdown = genphy_shutdown, + .readext = adin_extread, + .writeext = adin_extwrite, +}; + U_BOOT_PHY_DRIVER(ADIN1300) = { .name = "ADIN1300", .uid = PHY_ID_ADIN1300, diff --git a/drivers/net/phy/airoha/Kconfig b/drivers/net/phy/airoha/Kconfig index da8747939e3..4139df343ad 100644 --- a/drivers/net/phy/airoha/Kconfig +++ b/drivers/net/phy/airoha/Kconfig @@ -7,6 +7,7 @@ config PHY_AIROHA_EN8811 depends on PHY_AIROHA depends on SUPPORTS_FW_LOADER select FW_LOADER + select PHY_COMMON_PROPS help AIROHA EN8811H supported. AIROHA AN8811HB supported. diff --git a/drivers/net/phy/airoha/air_en8811.c b/drivers/net/phy/airoha/air_en8811.c index 0b974472732..32f06dd6dfa 100644 --- a/drivers/net/phy/airoha/air_en8811.c +++ b/drivers/net/phy/airoha/air_en8811.c @@ -23,6 +23,7 @@ #include <linux/compat.h> #include <dm/device_compat.h> #include <u-boot/crc.h> +#include <linux/phy/phy-common-props.h> /* MII Registers */ #define AIR_AUX_CTRL_STATUS 0x1d @@ -1046,11 +1047,50 @@ static int air_leds_init(struct phy_device *phydev, int num, u16 dur, int mode) return 0; } -static int en8811h_config(struct phy_device *phydev) +static int en8811h_config_serdes_polarity(struct phy_device *phydev) { - struct en8811h_priv *priv = phydev->priv; ofnode node = phy_get_ofnode(phydev); + unsigned int pol, default_pol; u32 pbus_value = 0; + int ret; + + if (!ofnode_valid(node)) + return 0; + + default_pol = PHY_POL_NORMAL; + if (ofnode_read_bool(node, "airoha,pnswap-rx")) + default_pol = PHY_POL_INVERT; + + ret = phy_get_rx_polarity(node, + phy_string_for_interface(phydev->interface), + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), + default_pol, &pol); + if (ret) + return ret; + if (pol == PHY_POL_INVERT) + pbus_value |= EN8811H_POLARITY_RX_REVERSE; + + default_pol = PHY_POL_NORMAL; + if (ofnode_read_bool(node, "airoha,pnswap-tx")) + default_pol = PHY_POL_INVERT; + + ret = phy_get_tx_polarity(node, + phy_string_for_interface(phydev->interface), + BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT), + default_pol, &pol); + if (ret) + return ret; + if (pol == PHY_POL_NORMAL) + pbus_value |= EN8811H_POLARITY_TX_NORMAL; + + return air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, + EN8811H_POLARITY_RX_REVERSE | + EN8811H_POLARITY_TX_NORMAL, pbus_value); +} + +static int en8811h_config(struct phy_device *phydev) +{ + struct en8811h_priv *priv = phydev->priv; int ret = 0; /* If restart happened in .probe(), no need to restart now */ @@ -1081,20 +1121,8 @@ static int en8811h_config(struct phy_device *phydev) if (ret < 0) return ret; - /* Serdes polarity */ - pbus_value = 0; - if (ofnode_read_bool(node, "airoha,pnswap-rx")) - pbus_value |= EN8811H_POLARITY_RX_REVERSE; - else - pbus_value &= ~EN8811H_POLARITY_RX_REVERSE; - if (ofnode_read_bool(node, "airoha,pnswap-tx")) - pbus_value &= ~EN8811H_POLARITY_TX_NORMAL; - else - pbus_value |= EN8811H_POLARITY_TX_NORMAL; - ret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, - EN8811H_POLARITY_RX_REVERSE | - EN8811H_POLARITY_TX_NORMAL, - pbus_value); + /* Configure Serdes polarity from device tree */ + ret = en8811h_config_serdes_polarity(phydev); if (ret < 0) return ret; diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 10b87dfb8ab..83da3e1cc77 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -400,7 +400,7 @@ int aquantia_config(struct phy_device *phydev) int interface = phydev->interface; u32 val, id, rstatus, fault; u32 reg_val1 = 0; - int num_retries = 5; + int num_retries = 200; int usx_an = 0; /* diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 7ce03b59b6a..ebed61de133 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -203,32 +203,24 @@ static int dp83867_of_init(struct phy_device *phydev) "Should be 'rgmii-id' to use internal delays\n"); } - /* RX delay *must* be specified if internal delay of RX is used. */ + dp83867->rx_id_delay = DP83867_RGMIIDCTL_2_00_NS; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { ret = ofnode_read_u32(node, "ti,rx-internal-delay", &dp83867->rx_id_delay); - if (ret) { - pr_debug("ti,rx-internal-delay must be specified\n"); - return ret; - } - if (dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { + if (!ret && dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) { pr_debug("ti,rx-internal-delay value of %u out of range\n", dp83867->rx_id_delay); return -EINVAL; } } - /* TX delay *must* be specified if internal delay of RX is used. */ + dp83867->tx_id_delay = DP83867_RGMIIDCTL_2_00_NS; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { ret = ofnode_read_u32(node, "ti,tx-internal-delay", &dp83867->tx_id_delay); - if (ret) { - debug("ti,tx-internal-delay must be specified\n"); - return ret; - } - if (dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { + if (!ret && dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) { pr_debug("ti,tx-internal-delay value of %u out of range\n", dp83867->tx_id_delay); return -EINVAL; diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index a65e81dff0c..d96970949bc 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -23,6 +23,7 @@ #define PHY_ID_VSC8502 0x00070630 #define PHY_ID_VSC8540 0x00070760 #define PHY_ID_VSC8541 0x00070770 +#define PHY_ID_VSC8572 0x000704d0 #define PHY_ID_VSC8574 0x000704a0 #define PHY_ID_VSC8584 0x000707c0 @@ -1612,6 +1613,16 @@ U_BOOT_PHY_DRIVER(vsc8541) = { .shutdown = &genphy_shutdown, }; +U_BOOT_PHY_DRIVER(vsc8572) = { + .name = "Microsemi VSC8572", + .uid = PHY_ID_VSC8572, + .mask = 0x000ffff0, + .features = PHY_GBIT_FEATURES, + .config = &vsc8574_config, + .startup = &mscc_startup, + .shutdown = &genphy_shutdown, +}; + U_BOOT_PHY_DRIVER(vsc8574) = { .name = "Microsemi VSC8574", .uid = PHY_ID_VSC8574, diff --git a/drivers/net/qe/dm_qe_uec_phy.c b/drivers/net/qe/dm_qe_uec_phy.c index 8c0168be859..107c7686b3b 100644 --- a/drivers/net/qe/dm_qe_uec_phy.c +++ b/drivers/net/qe/dm_qe_uec_phy.c @@ -152,7 +152,7 @@ static const struct udevice_id qe_uec_mdio_ids[] = { { } }; -U_BOOT_DRIVER(mvmdio) = { +U_BOOT_DRIVER(qe_uec_mdio) = { .name = "qe_uec_mdio", .id = UCLASS_MDIO, .of_match = qe_uec_mdio_ids, diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c index 0ea50c484c0..e1daeb6c1e6 100644 --- a/drivers/net/sandbox.c +++ b/drivers/net/sandbox.c @@ -15,7 +15,7 @@ /* * Structure definitions for network protocols. Since this file is used for - * both NET and NET_LWIP, and given that the two network stacks do have + * both NET_LEGACY and NET_LWIP, and given that the two network stacks do have * conflicting types (for instance struct icmp_hdr), it is on purpose that the * structures are defined locally with minimal dependencies -- <asm/types.h> is * included for the bit types and that's it. diff --git a/drivers/net/sni_netsec.c b/drivers/net/sni_netsec.c index 71afe78fd28..b74a5c27cae 100644 --- a/drivers/net/sni_netsec.c +++ b/drivers/net/sni_netsec.c @@ -1138,7 +1138,7 @@ static const struct udevice_id netsec_ids[] = { {} }; -U_BOOT_DRIVER(ave) = { +U_BOOT_DRIVER(synquacer_netsec) = { .name = "synquacer_netsec", .id = UCLASS_ETH, .of_match = netsec_ids, diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c index d7746f454ba..7a7cb83bd98 100644 --- a/drivers/net/ti/cpsw.c +++ b/drivers/net/ti/cpsw.c @@ -33,6 +33,7 @@ #define PKT_MAX (1500 + 14 + 4 + 4) #define CLEAR_BIT 1 #define GIGABITEN BIT(7) +#define GMII_EN BIT(5) #define FULLDUPLEXEN BIT(0) #define MIIEN BIT(15) #define CTL_EXT_EN BIT(18) @@ -216,6 +217,10 @@ struct cpsw_priv { u32 phy_mask; }; +struct cpsw_driver_data { + void (*gmii_sel)(struct cpsw_priv *priv, phy_interface_t phy_mode); +}; + static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) { int idx; @@ -1064,9 +1069,17 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, writel(reg, priv->data->gmii_sel); } -static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, - phy_interface_t phy_mode) +static void cpsw_phy_sel(struct cpsw_priv *priv, phy_interface_t phy_mode) { + const char *compat = priv->data->phy_sel_compat; + const struct cpsw_driver_data *drv_data = + (const struct cpsw_driver_data *)dev_get_driver_data(priv->dev); + + if (drv_data && drv_data->gmii_sel) { + drv_data->gmii_sel(priv, phy_mode); + return; + } + if (!strcmp(compat, "ti,am3352-cpsw-phy-sel")) cpsw_gmii_sel_am3352(priv, phy_mode); if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel")) @@ -1084,8 +1097,7 @@ static int cpsw_eth_probe(struct udevice *dev) priv->data = pdata->priv_pdata; ti_cm_get_macid(dev, priv->data, pdata->enetaddr); /* Select phy interface in control module */ - cpsw_phy_sel(priv, priv->data->phy_sel_compat, - pdata->phy_interface); + cpsw_phy_sel(priv, pdata->phy_interface); return _cpsw_register(priv); } @@ -1122,33 +1134,13 @@ static void cpsw_eth_of_parse_slave(struct cpsw_platform_data *data, "max-speed", 0); } -static int cpsw_eth_of_to_plat(struct udevice *dev) +static int cpsw_eth_of_to_plat_legacy(struct udevice *dev, + struct cpsw_platform_data *data) { - struct eth_pdata *pdata = dev_get_plat(dev); - struct cpsw_platform_data *data; - struct gpio_desc *mode_gpios; int slave_index = 0; - int num_mode_gpios; ofnode subnode; int ret; - data = calloc(1, sizeof(struct cpsw_platform_data)); - if (!data) - return -ENOMEM; - - pdata->priv_pdata = data; - pdata->iobase = dev_read_addr(dev); - data->version = CPSW_CTRL_VERSION_2; - data->bd_ram_ofs = CPSW_BD_OFFSET; - data->ale_reg_ofs = CPSW_ALE_OFFSET; - data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET; - data->mdio_div = CPSW_MDIO_DIV; - data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, - - pdata->phy_interface = -1; - - data->cpsw_base = pdata->iobase; - ret = dev_read_s32(dev, "cpdma_channels", &data->channels); if (ret) { printf("error: cpdma_channels not found in dt\n"); @@ -1177,21 +1169,10 @@ static int cpsw_eth_of_to_plat(struct udevice *dev) ret = dev_read_u32(dev, "mac_control", &data->mac_control); if (ret) { - printf("error: ale_entries not found in dt\n"); + printf("error: mac_control not found in dt\n"); return ret; } - num_mode_gpios = gpio_get_list_count(dev, "mode-gpios"); - if (num_mode_gpios > 0) { - mode_gpios = malloc(sizeof(struct gpio_desc) * - num_mode_gpios); - gpio_request_list_by_name(dev, "mode-gpios", mode_gpios, - num_mode_gpios, GPIOD_IS_OUT); - free(mode_gpios); - } - - data->active_slave = dev_read_u32_default(dev, "active_slave", 0); - ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { const char *name; @@ -1222,16 +1203,118 @@ static int cpsw_eth_of_to_plat(struct udevice *dev) if (ofnode_read_bool(subnode, "rmii-clock-ext")) data->rmii_clock_external = true; + } + } - data->phy_sel_compat = ofnode_read_string(subnode, - "compatible"); - if (!data->phy_sel_compat) { - pr_err("Not able to get gmii_sel compatible\n"); - return -ENOENT; - } + return 0; +} + +static int cpsw_eth_of_to_plat_switch(struct udevice *dev, + struct cpsw_platform_data *data) +{ + ofnode eth_ports_node, subnode; + int ret; + + data->channels = 8; + data->ale_entries = 1024; + data->mac_control = GMII_EN; + + eth_ports_node = ofnode_find_subnode(dev_ofnode(dev), "ethernet-ports"); + data->slaves = ofnode_get_child_count(eth_ports_node); + if (!data->slaves) { + pr_err("cpsw: No ethernet-ports defined\n"); + return -EINVAL; + } + + data->slave_data = malloc(sizeof(struct cpsw_slave_data) * data->slaves); + if (!data->slave_data) + return -ENOMEM; + + ofnode_for_each_subnode(subnode, eth_ports_node) { + struct ofnode_phandle_args args; + u32 port_id; + + ret = ofnode_read_u32(subnode, "reg", &port_id); + if (ret || !port_id || port_id > data->slaves) { + pr_err("cpsw: invalid or missing reg in port node\n"); + return -EINVAL; + } + + cpsw_eth_of_parse_slave(data, port_id - 1, subnode); + + if (!data->gmii_sel) { + ret = ofnode_parse_phandle_with_args(subnode, "phys", "#phy-cells", + 0, 0, &args); + if (!ret) + data->gmii_sel = ofnode_get_addr(args.node); + } + } + + if (!data->gmii_sel) { + pr_err("No port specified phys correctly\n"); + return -ENOENT; + } + + ofnode_for_each_subnode(subnode, dev_ofnode(dev)) { + const char *name = ofnode_get_name(subnode); + + if (strncmp(name, "mdio", 4)) + continue; + + data->mdio_base = ofnode_get_addr(subnode); + if (data->mdio_base == FDT_ADDR_T_NONE) { + pr_err("Not able to get MDIO address space\n"); + return -ENOENT; } } + return 0; +} + +static int cpsw_eth_of_to_plat(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct cpsw_platform_data *data; + struct gpio_desc *mode_gpios; + int num_mode_gpios; + int ret; + bool switch_dt_bindings = + ofnode_valid(ofnode_find_subnode(dev_ofnode(dev), "ethernet-ports")); + + data = calloc(1, sizeof(struct cpsw_platform_data)); + if (!data) + return -ENOMEM; + + pdata->priv_pdata = data; + pdata->iobase = dev_read_addr(dev); + data->version = CPSW_CTRL_VERSION_2; + data->bd_ram_ofs = CPSW_BD_OFFSET; + data->ale_reg_ofs = CPSW_ALE_OFFSET; + data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET; + data->mdio_div = CPSW_MDIO_DIV; + data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET; + + pdata->phy_interface = -1; + + data->cpsw_base = pdata->iobase; + + num_mode_gpios = gpio_get_list_count(dev, "mode-gpios"); + if (num_mode_gpios > 0) { + mode_gpios = malloc(sizeof(struct gpio_desc) * num_mode_gpios); + gpio_request_list_by_name(dev, "mode-gpios", mode_gpios, + num_mode_gpios, GPIOD_IS_OUT); + free(mode_gpios); + } + + data->active_slave = dev_read_u32_default(dev, "active_slave", 0); + + if (switch_dt_bindings) + ret = cpsw_eth_of_to_plat_switch(dev, data); + else + ret = cpsw_eth_of_to_plat_legacy(dev, data); + if (ret) + return ret; + data->slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET; data->slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET; @@ -1253,9 +1336,22 @@ static int cpsw_eth_of_to_plat(struct udevice *dev) return 0; } +static const struct cpsw_driver_data cpsw_data_am3352 = { + .gmii_sel = cpsw_gmii_sel_am3352, +}; + +static const struct cpsw_driver_data cpsw_data_dra7xx = { + .gmii_sel = cpsw_gmii_sel_dra7xx, +}; + static const struct udevice_id cpsw_eth_ids[] = { - { .compatible = "ti,cpsw" }, - { .compatible = "ti,am335x-cpsw" }, + { .compatible = "ti,cpsw", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,am335x-cpsw", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,am4372-cpsw", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,dra7-cpsw", .data = (ulong)&cpsw_data_dra7xx }, + { .compatible = "ti,am335x-cpsw-switch", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,am4372-cpsw-switch", .data = (ulong)&cpsw_data_am3352 }, + { .compatible = "ti,dra7-cpsw-switch", .data = (ulong)&cpsw_data_dra7xx }, { } }; #endif diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index e9cc5db52d2..1ea81fe1830 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -28,6 +28,10 @@ #define XAE_EMMC_LINKSPD_100 0x40000000 /* Link Speed mask for 100 Mbit */ #define XAE_EMMC_LINKSPD_1000 0x80000000 /* Link Speed mask for 1000 Mbit */ +/* Reset and Address Filter (RAF) Register bit definitions */ +#define XAE_RAF_MCSTREJ_MASK 0x00000002 /* Reject rx multicast dst addr */ +#define XAE_RAF_BCSTREJ_MASK 0x00000004 /* Reject rx broadcast dst addr */ + /* Interrupt Status/Enable/Mask Registers bit definitions */ #define XAE_INT_RXRJECT_MASK 0x00000008 /* Rx frame rejected */ #define XAE_INT_MGTRDY_MASK 0x00000080 /* MGT clock Lock */ @@ -153,7 +157,8 @@ static struct axidma_bd tx_bd __attribute((aligned(DMAALIGN))); static struct axidma_bd rx_bd __attribute((aligned(DMAALIGN))); struct axi_regs { - u32 reserved[3]; + u32 raf; /* 0x0: Reset and Address Filter */ + u32 reserved[2]; u32 is; /* 0xC: Interrupt status */ u32 reserved2; u32 ie; /* 0x14: Interrupt enable */ @@ -528,6 +533,19 @@ static int axi_ethernet_init(struct axidma_priv *priv) /* Set default MDIO divisor */ writel(XAE_MDIO_DIV_DFT | XAE_MDIO_MC_MDIOEN_MASK, ®s->mdio_mc); + /* + * Reject broadcast and multicast frames at MAC level to reduce + * unnecessary traffic processing. Multicast rejection is only + * enabled when IPv6 is not configured because IPv6 Neighbor + * Discovery and DHCPv6 rely on multicast. + */ + if (!IS_ENABLED(CONFIG_IPV6)) + writel(readl(®s->raf) | XAE_RAF_MCSTREJ_MASK | + XAE_RAF_BCSTREJ_MASK, ®s->raf); + else + writel(readl(®s->raf) | XAE_RAF_BCSTREJ_MASK, + ®s->raf); + debug("axiemac: InitHw done\n"); return 0; } diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index a50d5aee03f..f570ae9ee73 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -69,10 +69,13 @@ #define ZYNQ_GEM_NWCFG_SGMII_ENBL 0x08000000 /* SGMII Enable */ #define ZYNQ_GEM_NWCFG_PCS_SEL 0x00000800 /* PCS select */ +#define ZYNQ_GEM_DBUS_WIDTH_MASK (3 << 21) /* bits 22:21 */ #ifdef CONFIG_ARM64 # define ZYNQ_GEM_DBUS_WIDTH (1 << 21) /* 64 bit bus */ +# define ZYNQ_GEM_DBUS_WIDTH_128 (2 << 21) /* 128 bit bus */ #else # define ZYNQ_GEM_DBUS_WIDTH (0 << 21) /* 32 bit bus */ +# define ZYNQ_GEM_DBUS_WIDTH_128 (0 << 21) /* 32 bit bus */ #endif #define ZYNQ_GEM_NWCFG_INIT (ZYNQ_GEM_DBUS_WIDTH | \ @@ -134,6 +137,7 @@ #define ZYNQ_GEM_FREQUENCY_10 2500000UL #define ZYNQ_GEM_FREQUENCY_100 25000000UL #define ZYNQ_GEM_FREQUENCY_1000 125000000UL +#define ZYNQ_GEM_FREQUENCY_10000 150000000UL #define RXCLK_EN BIT(0) @@ -470,28 +474,6 @@ static int zynq_gem_init(struct udevice *dev) for (i = 0; i < STAT_SIZE; i++) readl(®s->stat[i]); - /* Setup RxBD space */ - memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd)); - - for (i = 0; i < RX_BUF; i++) { - priv->rx_bd[i].status = 0xF0000000; - priv->rx_bd[i].addr = - (lower_32_bits((ulong)(priv->rxbuffers) - + (i * PKTSIZE_ALIGN))); -#if defined(CONFIG_PHYS_64BIT) - priv->rx_bd[i].addr_hi = - (upper_32_bits((ulong)(priv->rxbuffers) - + (i * PKTSIZE_ALIGN))); -#endif - } - /* WRAP bit to last BD */ - priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; - /* Write RxBDs to IP */ - writel(lower_32_bits((ulong)priv->rx_bd), ®s->rxqbase); -#if defined(CONFIG_PHYS_64BIT) - writel(upper_32_bits((ulong)priv->rx_bd), ®s->upper_rxqbase); -#endif - /* Setup for DMA Configuration register */ writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); @@ -520,6 +502,35 @@ static int zynq_gem_init(struct udevice *dev) priv->init++; } + /* + * Reinitialize RX BDs on every init. The 10GBE USX block asserts + * RX_SYNC_RESET during setup which resets the GEM RX DMA pointer + * back to rxqbase, so BDs and rxqbase must be refreshed each time + * to keep the hardware and driver ring indices in sync. + */ + priv->rxbd_current = 0; + priv->rx_first_buf = 0; + memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd)); + for (i = 0; i < RX_BUF; i++) { + priv->rx_bd[i].status = 0xF0000000; + priv->rx_bd[i].addr = + (lower_32_bits((ulong)(priv->rxbuffers) + + (i * PKTSIZE_ALIGN))); +#if defined(CONFIG_PHYS_64BIT) + priv->rx_bd[i].addr_hi = + (upper_32_bits((ulong)(priv->rxbuffers) + + (i * PKTSIZE_ALIGN))); +#endif + } + /* WRAP bit to last BD */ + priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; + + /* Write RxBDs to IP */ + writel(lower_32_bits((ulong)priv->rx_bd), ®s->rxqbase); +#if defined(CONFIG_PHYS_64BIT) + writel(upper_32_bits((ulong)priv->rx_bd), ®s->upper_rxqbase); +#endif + ret = phy_startup(priv->phydev); if (ret) return ret; @@ -532,6 +543,8 @@ static int zynq_gem_init(struct udevice *dev) nwconfig = ZYNQ_GEM_NWCFG_INIT; if (device_is_compatible(dev, "amd,versal2-10gbe")) { + nwconfig &= ~ZYNQ_GEM_DBUS_WIDTH_MASK; + nwconfig |= ZYNQ_GEM_DBUS_WIDTH_128; if (priv->interface == PHY_INTERFACE_MODE_10GBASER) { ctrl = readl(®s->nwcfg); ctrl |= PCSSEL; @@ -602,6 +615,9 @@ static int zynq_gem_init(struct udevice *dev) } switch (priv->phydev->speed) { + case SPEED_10000: + clk_rate = ZYNQ_GEM_FREQUENCY_10000; + break; case SPEED_1000: nwconfig |= ZYNQ_GEM_NWCFG_SPEED1000; clk_rate = ZYNQ_GEM_FREQUENCY_1000; @@ -615,6 +631,7 @@ static int zynq_gem_init(struct udevice *dev) break; } nwcfg = readl(®s->nwcfg); + nwcfg &= ~(ZYNQ_GEM_NWCFG_SPEED100 | ZYNQ_GEM_NWCFG_SPEED1000); nwcfg |= nwconfig; if (nwcfg) writel(nwcfg, ®s->nwcfg); |
