diff options
| author | Tom Rini <[email protected]> | 2026-03-13 09:00:54 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-03-13 10:52:03 -0600 |
| commit | 6dc75d440dbdd3e2ac24ae5bb0ed51123bee8c33 (patch) | |
| tree | 854cbd24bc2ee6852e0efed6b029c755c7c26a3e /drivers | |
| parent | 9f1059bc735ec2a8d78c1f3e4fcab1fa3f428317 (diff) | |
| parent | a5fcbd5a83553b3803df28422410c9fd22adaec6 (diff) | |
Merge tag 'net-20260312' of https://source.denx.de/u-boot/custodians/u-boot-net into next
Pull request net-20260312.
net:
- Move network PHY under NETDEVICES
- s/DM_CLK/CLK/ in HIFEMAC_{ETH,MDIO}
- Add support for Airoha AN8811HB PHY
- airoha: PCS and MDIO support for Airoha AN7581 SoC
net-lwip:
- Fix issue when TFTP blocksize is >8192
- Adjust PBUF_POOL_SIZE/IP_REASS_MAX_PBUFS for better performance and
resource usage.
- Enable mii command for NET_LWIP
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/net/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/net/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/airoha/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/net/airoha/Makefile | 4 | ||||
| -rw-r--r-- | drivers/net/airoha/pcs-airoha-common.c | 827 | ||||
| -rw-r--r-- | drivers/net/airoha/pcs-airoha.h | 1220 | ||||
| -rw-r--r-- | drivers/net/airoha/pcs-an7581.c | 1375 | ||||
| -rw-r--r-- | drivers/net/airoha_eth.c | 321 | ||||
| -rw-r--r-- | drivers/net/phy/airoha/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/net/phy/airoha/air_en8811.c | 689 |
10 files changed, 4379 insertions, 88 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d3ef050d1a1..cd07b117a5f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1,7 +1,3 @@ -source "drivers/net/phy/Kconfig" -source "drivers/net/pfe_eth/Kconfig" -source "drivers/net/fsl-mc/Kconfig" - config ETH def_bool y @@ -121,11 +117,15 @@ config AG7XXX This driver supports the Atheros AG7xxx Ethernet MAC. This MAC is present in the Atheros AR7xxx, AR9xxx and QCA9xxx MIPS chips. +source "drivers/net/airoha/Kconfig" + config AIROHA_ETH bool "Airoha Ethernet QDMA Driver" depends on ARCH_AIROHA + select MISC select PHYLIB select DEVRES + select DM_ETH_PHY select DM_RESET select MDIO_MT7531_MMIO help @@ -979,7 +979,7 @@ source "drivers/net/mtk_eth/Kconfig" config HIFEMAC_ETH bool "HiSilicon Fast Ethernet Controller" - select DM_CLK + select CLK select DM_RESET select PHYLIB help @@ -989,7 +989,7 @@ config HIFEMAC_ETH config HIFEMAC_MDIO bool "HiSilicon Fast Ethernet Controller MDIO interface" depends on DM_MDIO - select DM_CLK + select CLK help This driver supports the internal MDIO interface of HIFEMAC Ethernet controller. @@ -1098,4 +1098,8 @@ config MDIO_MUX_MESON_GXL This driver is used for the MDIO mux found on the Amlogic GXL & compatible SoCs. +source "drivers/net/phy/Kconfig" +source "drivers/net/pfe_eth/Kconfig" +source "drivers/net/fsl-mc/Kconfig" + endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 5bb40480d88..5e90183d090 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_AG7XXX) += ag7xxx.o +obj-y += airoha/ obj-$(CONFIG_AIROHA_ETH) += airoha_eth.o obj-$(CONFIG_ALTERA_TSE) += altera_tse.o obj-$(CONFIG_ASPEED_MDIO) += aspeed_mdio.o diff --git a/drivers/net/airoha/Kconfig b/drivers/net/airoha/Kconfig new file mode 100644 index 00000000000..8c2d6db92fa --- /dev/null +++ b/drivers/net/airoha/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config PCS_AIROHA + bool + select MISC + +config PCS_AIROHA_AN7581 + bool "Airoha AN7581 PCS driver" + select PCS_AIROHA + help + This module provides helper to phylink for managing the Airoha + AN7581 PCS for SoC Ethernet and PON SERDES. diff --git a/drivers/net/airoha/Makefile b/drivers/net/airoha/Makefile new file mode 100644 index 00000000000..81fd26cf813 --- /dev/null +++ b/drivers/net/airoha/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_PCS_AIROHA) += pcs-airoha-common.o +obj-$(CONFIG_PCS_AIROHA_AN7581) += pcs-an7581.o diff --git a/drivers/net/airoha/pcs-airoha-common.c b/drivers/net/airoha/pcs-airoha-common.c new file mode 100644 index 00000000000..2e5cb085498 --- /dev/null +++ b/drivers/net/airoha/pcs-airoha-common.c @@ -0,0 +1,827 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 AIROHA Inc + * Author: Christian Marangi <[email protected]> + */ + +#include <dm.h> +#include <dm/devres.h> +#include <linux/ethtool.h> +#include <net.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> + +#include "pcs-airoha.h" + +static void airoha_pcs_setup_scu_eth(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 xsi_sel; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + xsi_sel = AIROHA_SCU_ETH_XSI_HSGMII; + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + default: + xsi_sel = AIROHA_SCU_ETH_XSI_USXGMII; + } + + regmap_update_bits(priv->scu, AIROHA_SCU_SSR3, + AIROHA_SCU_ETH_XSI_SEL, + xsi_sel); +} + +static void airoha_pcs_setup_scu_pon(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 xsi_sel, wan_sel; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + wan_sel = AIROHA_SCU_WAN_SEL_SGMII; + xsi_sel = AIROHA_SCU_PON_XSI_HSGMII; + break; + case PHY_INTERFACE_MODE_2500BASEX: + wan_sel = AIROHA_SCU_WAN_SEL_HSGMII; + xsi_sel = AIROHA_SCU_PON_XSI_HSGMII; + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + default: + wan_sel = AIROHA_SCU_WAN_SEL_USXGMII; + xsi_sel = AIROHA_SCU_PON_XSI_USXGMII; + } + + regmap_update_bits(priv->scu, AIROHA_SCU_SSTR, + AIROHA_SCU_PON_XSI_SEL, + xsi_sel); + + regmap_update_bits(priv->scu, AIROHA_SCU_WAN_CONF, + AIROHA_SCU_WAN_SEL, + wan_sel); +} + +static int airoha_pcs_setup_scu(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + const struct airoha_pcs_match_data *data = priv->data; + int ret; + + if (priv->xfi_rst) { + ret = reset_assert(priv->xfi_rst); + if (ret) + return ret; + } + + switch (data->port_type) { + case AIROHA_PCS_ETH: + airoha_pcs_setup_scu_eth(priv, interface); + break; + case AIROHA_PCS_PON: + airoha_pcs_setup_scu_pon(priv, interface); + break; + } + + if (priv->xfi_rst) { + ret = reset_deassert(priv->xfi_rst); + if (ret) + return ret; + } + + /* TODO better handle reset from MAC */ + ret = reset_assert_bulk(&priv->rsts); + if (ret) + return ret; + + ret = reset_deassert_bulk(&priv->rsts); + if (ret) + return ret; + + return 0; +} + +static void airoha_pcs_init_usxgmii(struct airoha_pcs_priv *priv) +{ + const struct airoha_pcs_match_data *data = priv->data; + + regmap_set_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, + AIROHA_PCS_HSGMII_XFI_SEL); + + /* Disable Hibernation */ + if (data->hibernation_workaround) + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1, + AIROHA_PCS_USXGMII_SPEED_SEL_H); + + /* FIXME: wait Airoha */ + /* Avoid PCS sending garbage to MAC in some HW revision (E0) */ + if (data->usxgmii_ber_time_fixup) + regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0); + + if (data->usxgmii_rx_gb_out_vld_tweak) + regmap_clear_bits(priv->usxgmii_pcs, AN7583_PCS_USXGMII_RTL_MODIFIED, + AIROHA_PCS_USXGMII_MODIFIED_RX_GB_OUT_VLD); +} + +static void airoha_pcs_init_hsgmii(struct airoha_pcs_priv *priv) +{ + regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, + AIROHA_PCS_HSGMII_XFI_SEL); + + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, + AIROHA_PCS_TBI_10B_MODE); +} + +static void airoha_pcs_init_sgmii(struct airoha_pcs_priv *priv) +{ + regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, + AIROHA_PCS_HSGMII_XFI_SEL); + + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, + AIROHA_PCS_TBI_10B_MODE); + + regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_6, + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L, + FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L, 0x07070707)); + + regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_8, + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C, + FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C, 0xff)); +} + +static void airoha_pcs_init(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + airoha_pcs_init_sgmii(priv); + break; + case PHY_INTERFACE_MODE_2500BASEX: + airoha_pcs_init_hsgmii(priv); + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + airoha_pcs_init_usxgmii(priv); + break; + default: + return; + } +} + +static void airoha_pcs_interrupt_init_sgmii(struct airoha_pcs_priv *priv) +{ + /* Disable every interrupt */ + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, + AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT | + AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT | + AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT | + AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT | + AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT); + + /* Clear interrupt */ + regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, + AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR); + + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, + AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR | + AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR); +} + +static void airoha_pcs_interrupt_init_usxgmii(struct airoha_pcs_priv *priv) +{ + /* Disable every Interrupt */ + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_0, + AIROHA_PCS_USXGMII_T_TYPE_T_INT_EN | + AIROHA_PCS_USXGMII_T_TYPE_D_INT_EN | + AIROHA_PCS_USXGMII_T_TYPE_C_INT_EN | + AIROHA_PCS_USXGMII_T_TYPE_S_INT_EN); + + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_1, + AIROHA_PCS_USXGMII_R_TYPE_C_INT_EN | + AIROHA_PCS_USXGMII_R_TYPE_S_INT_EN | + AIROHA_PCS_USXGMII_TXPCS_FSM_ENC_ERR_INT_EN | + AIROHA_PCS_USXGMII_T_TYPE_E_INT_EN); + + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_2, + AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT_EN | + AIROHA_PCS_USXGMII_R_TYPE_E_INT_EN | + AIROHA_PCS_USXGMII_R_TYPE_T_INT_EN | + AIROHA_PCS_USXGMII_R_TYPE_D_INT_EN); + + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_3, + AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT_EN | + AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT_EN | + AIROHA_PCS_USXGMII_LINK_UP_ST_INT_EN | + AIROHA_PCS_USXGMII_HI_BER_ST_INT_EN); + + regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_4, + AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT_EN); + + /* Clear any pending interrupt */ + regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_2, + AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT | + AIROHA_PCS_USXGMII_R_TYPE_E_INT | + AIROHA_PCS_USXGMII_R_TYPE_T_INT | + AIROHA_PCS_USXGMII_R_TYPE_D_INT); + + regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_3, + AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT | + AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT | + AIROHA_PCS_USXGMII_LINK_UP_ST_INT | + AIROHA_PCS_USXGMII_HI_BER_ST_INT); + + regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_4, + AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT); + + /* Interrupt saddly seems to be not weel supported for Link Down. + * PCS Poll is a must to correctly read and react on Cable Deatch + * as only cable attach interrupt are fired and Link Down interrupt + * are fired only in special case like AN restart. + */ +} + +static void airoha_pcs_interrupt_init(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + return airoha_pcs_interrupt_init_sgmii(priv); + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + return airoha_pcs_interrupt_init_usxgmii(priv); + default: + return; + } +} + +int airoha_pcs_config(struct udevice *dev, bool neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + struct airoha_pcs_priv *priv = dev_get_priv(dev); + const struct airoha_pcs_match_data *data; + u32 rate_adapt; + int ret; + + priv->interface = interface; + data = priv->data; + + /* Apply Analog and Digital configuration for PCS */ + if (data->bringup) { + ret = data->bringup(priv, interface); + if (ret) + return ret; + } + + /* Set final configuration for various modes */ + airoha_pcs_init(priv, interface); + + /* Configure Interrupt for various modes */ + airoha_pcs_interrupt_init(priv, interface); + + rate_adapt = AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN | + AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN; + + if (interface == PHY_INTERFACE_MODE_SGMII) + rate_adapt |= AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS | + AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS; + + /* AN Auto Settings (Rate Adaptation) */ + regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_0, + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS | + AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS | + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN | + AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN, rate_adapt); + + /* FIXME: With an attached Aeonsemi PHY, AN is needed + * even with no inband. + */ + if (interface == PHY_INTERFACE_MODE_USXGMII || + interface == PHY_INTERFACE_MODE_10GBASER) { + if (interface == PHY_INTERFACE_MODE_USXGMII) + regmap_set_bits(priv->usxgmii_pcs, + AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, + AIROHA_PCS_USXGMII_AN_ENABLE); + else + regmap_clear_bits(priv->usxgmii_pcs, + AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, + AIROHA_PCS_USXGMII_AN_ENABLE); + + if (data->usxgmii_xfi_mode_sel && neg_mode) + regmap_set_bits(priv->usxgmii_pcs, + AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7, + AIROHA_PCS_USXGMII_XFI_MODE_TX_SEL | + AIROHA_PCS_USXGMII_XFI_MODE_RX_SEL); + } + + /* Clear any force bit that my be set by bootloader */ + if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX || + interface == PHY_INTERFACE_MODE_2500BASEX) { + regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0, + AIROHA_PCS_LINK_MODE_P0 | + AIROHA_PCS_FORCE_SPD_MODE_P0 | + AIROHA_PCS_FORCE_LINKDOWN_P0 | + AIROHA_PCS_FORCE_LINKUP_P0); + } + + /* Toggle Rate Adaption for SGMII/HSGMII mode */ /* TODO */ + if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX || + interface == PHY_INTERFACE_MODE_2500BASEX) { + if (neg_mode) + regmap_clear_bits(priv->hsgmii_rate_adp, + AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0, + AIROHA_PCS_HSGMII_P0_DIS_MII_MODE); + else + regmap_set_bits(priv->hsgmii_rate_adp, + AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0, + AIROHA_PCS_HSGMII_P0_DIS_MII_MODE); + } + + /* Setup SGMII AN and advertisement in DEV_ABILITY */ /* TODO */ + if (interface == PHY_INTERFACE_MODE_SGMII) { + if (neg_mode) { + int advertise = 0x1; + + regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_4, + AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY, + FIELD_PREP(AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY, + advertise)); + + regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, + AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); + } else { + regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, + AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); + } + } + + if (interface == PHY_INTERFACE_MODE_2500BASEX) { + regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, + AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); + + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, + AIROHA_PCS_HSGMII_PCS_TX_ENABLE); + } + + if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX) { + u32 if_mode = AIROHA_PCS_HSGMII_AN_SIDEBAND_EN; + + /* Toggle SGMII or 1000base-x mode */ + if (interface == PHY_INTERFACE_MODE_SGMII) + if_mode |= AIROHA_PCS_HSGMII_AN_SGMII_EN; + + if (neg_mode) + regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, + AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS); + else + regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, + AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS); + + if (neg_mode) { + /* Clear force speed bits and MAC mode */ + regmap_clear_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, + AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 | + AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 | + AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 | + AIROHA_PCS_HSGMII_PCS_MAC_MODE | + AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL | + AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT); + } else { + /* Enable compatibility with MAC PCS Layer */ + if_mode |= AIROHA_PCS_HSGMII_AN_SGMII_COMPAT_EN; + + /* AN off force rate adaption, speed is set later in Link Up */ + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, + AIROHA_PCS_HSGMII_PCS_MAC_MODE | + AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT); + } + + regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, + AIROHA_PCS_HSGMII_AN_SGMII_IF_MODE_5_0, if_mode); + + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, + AIROHA_PCS_HSGMII_PCS_TX_ENABLE | + AIROHA_PCS_HSGMII_PCS_MODE2_EN); + } + + if (interface == PHY_INTERFACE_MODE_1000BASEX && + !neg_mode) { + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, + AIROHA_PCS_SGMII_SEND_AN_ERR_EN); + + regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37, + AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE); + } + + /* Configure Flow Control on XFI */ + regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_TX_FC_EN | AIROHA_PCS_XFI_RX_FC_EN, + permit_pause_to_mac ? + AIROHA_PCS_XFI_TX_FC_EN | AIROHA_PCS_XFI_RX_FC_EN : + 0); + + return 0; +} + +void airoha_pcs_link_up(struct udevice *dev, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex) +{ + struct airoha_pcs_priv *priv = dev_get_priv(dev); + const struct airoha_pcs_match_data *data; + + data = priv->data; + + if (neg_mode) { + if (interface == PHY_INTERFACE_MODE_SGMII) { + regmap_update_bits(priv->hsgmii_rate_adp, + AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1, + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR | + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, + FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR, 0x0) | + FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, 0x0)); + udelay(1); + regmap_update_bits(priv->hsgmii_rate_adp, + AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1, + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR | + AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, + FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR, 0xf) | + FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, 0x5)); + } + } else { + if (interface == PHY_INTERFACE_MODE_USXGMII || + interface == PHY_INTERFACE_MODE_10GBASER) { + u32 mode; + u32 rate_adapt; + + switch (speed) { + case SPEED_10000: + rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_10000; + mode = AIROHA_PCS_USXGMII_MODE_10000; + break; + /* case SPEED_5000: not supported in U-Boot + rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_5000; + mode = AIROHA_PCS_USXGMII_MODE_5000; + break; */ + case SPEED_2500: + rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_2500; + mode = AIROHA_PCS_USXGMII_MODE_2500; + break; + case SPEED_1000: + rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_1000; + mode = AIROHA_PCS_USXGMII_MODE_1000; + break; + case SPEED_100: + rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_100; + mode = AIROHA_PCS_USXGMII_MODE_100; + break; + } + + /* Trigger USXGMII change mode and force selected speed */ + regmap_update_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7, + AIROHA_PCS_USXGMII_RATE_UPDATE_MODE | + AIROHA_PCS_USXGMII_MODE, + AIROHA_PCS_USXGMII_RATE_UPDATE_MODE | mode); + + regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_11, + AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN | + AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, + AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN | + rate_adapt); + } + + if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX) { + u32 force_speed; + u32 rate_adapt; + + switch (speed) { + case SPEED_1000: + force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000; + rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_1000; + break; + case SPEED_100: + force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100; + rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_100; + break; + case SPEED_10: + force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10; + rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_10; + break; + } + + regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, + AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 | + AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 | + AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 | + AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, + force_speed | rate_adapt); + } + + if (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_2500BASEX) { + u32 ck_gen_mode; + u32 speed_reg; + u32 if_mode; + + switch (speed) { + case SPEED_2500: + speed_reg = AIROHA_PCS_LINK_MODE_P0_2_5G; + break; + case SPEED_1000: + speed_reg = AIROHA_PCS_LINK_MODE_P0_1G; + if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_1000; + ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_1000; + break; + case SPEED_100: + speed_reg = AIROHA_PCS_LINK_MODE_P0_100M; + if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_100; + ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_100; + break; + case SPEED_10: + speed_reg = AIROHA_PCS_LINK_MODE_P0_100M; + if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_10; + ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_10; + break; + } + + if (interface == PHY_INTERFACE_MODE_SGMII) { + regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, + AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, + if_mode); + + regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_AN_SGMII_MODE_FORCE, + AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE | + AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL, + ck_gen_mode | + AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL); + } + + regmap_update_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0, + AIROHA_PCS_LINK_MODE_P0 | + AIROHA_PCS_FORCE_SPD_MODE_P0, + speed_reg | + AIROHA_PCS_FORCE_SPD_MODE_P0); + } + } + + if (data->link_up) + data->link_up(priv); + + /* BPI BMI enable */ + regmap_clear_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_RXMPI_STOP | + AIROHA_PCS_XFI_RXMBI_STOP | + AIROHA_PCS_XFI_TXMPI_STOP | + AIROHA_PCS_XFI_TXMBI_STOP); +} + +void airoha_pcs_link_down(struct udevice *dev) +{ + struct airoha_pcs_priv *priv = dev_get_priv(dev); + + /* MPI MBI disable */ + regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_RXMPI_STOP | + AIROHA_PCS_XFI_RXMBI_STOP | + AIROHA_PCS_XFI_TXMPI_STOP | + AIROHA_PCS_XFI_TXMBI_STOP); +} + +void airoha_pcs_pre_config(struct udevice *dev, phy_interface_t interface) +{ + struct airoha_pcs_priv *priv = dev_get_priv(dev); + + /* Select HSGMII or USXGMII in SCU regs */ + airoha_pcs_setup_scu(priv, interface); + + /* MPI MBI disable */ + regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_RXMPI_STOP | + AIROHA_PCS_XFI_RXMBI_STOP | + AIROHA_PCS_XFI_TXMPI_STOP | + AIROHA_PCS_XFI_TXMBI_STOP); + + /* Write 1 to trigger reset and clear */ + regmap_clear_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_LOGIC_RST, + AIROHA_PCS_XFI_MAC_LOGIC_RST); + regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_LOGIC_RST, + AIROHA_PCS_XFI_MAC_LOGIC_RST); + + udelay(1000); + + /* Clear XFI MAC counter */ + regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_CNT_CLR, + AIROHA_PCS_XFI_GLB_CNT_CLR); +} + +int airoha_pcs_post_config(struct udevice *dev, phy_interface_t interface) +{ + struct airoha_pcs_priv *priv = dev_get_priv(dev); + + /* Frag disable */ + regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_RX_FRAG_LEN, + FIELD_PREP(AIROHA_PCS_XFI_RX_FRAG_LEN, 31)); + regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_TX_FRAG_LEN, + FIELD_PREP(AIROHA_PCS_XFI_TX_FRAG_LEN, 31)); + + /* IPG NUM */ + regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_IPG_NUM, + FIELD_PREP(AIROHA_PCS_XFI_IPG_NUM, 10)); + + /* Enable TX/RX flow control */ + regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_TX_FC_EN); + regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, + AIROHA_PCS_XFI_RX_FC_EN); + + return 0; +} + +static const struct regmap_config airoha_pcs_regmap_config = { + .width = REGMAP_SIZE_32, +}; + +static int airoha_pcs_probe(struct udevice *dev) +{ + struct regmap_config syscon_config = airoha_pcs_regmap_config; + struct airoha_pcs_priv *priv = dev_get_priv(dev); + fdt_addr_t base; + fdt_size_t size; + int ret; + + priv->dev = dev; + priv->data = (void *)dev_get_driver_data(dev); + + base = dev_read_addr_size_name(dev, "xfi_mac", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->xfi_mac = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->xfi_mac)) + return PTR_ERR(priv->xfi_mac); + + base = dev_read_addr_size_name(dev, "hsgmii_an", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->hsgmii_an = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->hsgmii_an)) + return PTR_ERR(priv->hsgmii_an); + + base = dev_read_addr_size_name(dev, "hsgmii_pcs", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->hsgmii_pcs = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->hsgmii_pcs)) + return PTR_ERR(priv->hsgmii_pcs); + + base = dev_read_addr_size_name(dev, "hsgmii_rate_adp", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->hsgmii_rate_adp = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->hsgmii_rate_adp)) + return PTR_ERR(priv->hsgmii_rate_adp); + + base = dev_read_addr_size_name(dev, "multi_sgmii", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->multi_sgmii = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->multi_sgmii)) + return PTR_ERR(priv->multi_sgmii); + + base = dev_read_addr_size_name(dev, "usxgmii", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->usxgmii_pcs = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->usxgmii_pcs)) + return PTR_ERR(priv->usxgmii_pcs); + + base = dev_read_addr_size_name(dev, "xfi_pma", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->xfi_pma = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->xfi_pma)) + return PTR_ERR(priv->xfi_pma); + + base = dev_read_addr_size_name(dev, "xfi_ana", &size); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + syscon_config.r_start = base; + syscon_config.r_size = size; + priv->xfi_ana = devm_regmap_init(dev, NULL, NULL, &syscon_config); + if (IS_ERR(priv->xfi_ana)) + return PTR_ERR(priv->xfi_ana); + + /* SCU is used to toggle XFI or HSGMII in global SoC registers */ + priv->scu = syscon_regmap_lookup_by_phandle(dev, "airoha,scu"); + if (IS_ERR(priv->scu)) + return PTR_ERR(priv->scu); + + priv->rsts.resets = devm_kcalloc(dev, AIROHA_PCS_MAX_NUM_RSTS, + sizeof(struct reset_ctl), GFP_KERNEL); + if (!priv->rsts.resets) + return -ENOMEM; + priv->rsts.count = AIROHA_PCS_MAX_NUM_RSTS; + + ret = reset_get_by_name(dev, "mac", &priv->rsts.resets[0]); + if (ret) + return ret; + + ret = reset_get_by_name(dev, "phy", &priv->rsts.resets[1]); + if (ret) + return ret; + + priv->xfi_rst = devm_reset_control_get_optional(dev, "xfi"); + + /* For Ethernet PCS, read the AN7581 SoC revision to check if + * manual rx calibration is needed. This is only limited to + * any SoC revision before E2. + */ + if (device_is_compatible(dev, "airoha,an7581-pcs-eth") && + priv->data->port_type == AIROHA_PCS_ETH) { + u32 val; + + ret = regmap_read(priv->scu, AIROHA_SCU_PDIDR, &val); + if (ret) + return ret; + + if (FIELD_GET(AIROHA_SCU_PRODUCT_ID, val) < 0x2) + priv->manual_rx_calib = true; + } + + return 0; +} + +static const struct airoha_pcs_match_data an7581_pcs_eth = { + .port_type = AIROHA_PCS_ETH, + .hibernation_workaround = true, + .usxgmii_ber_time_fixup = true, + .bringup = an7581_pcs_bringup, + .link_up = an7581_pcs_phya_link_up, +}; + +static const struct airoha_pcs_match_data an7581_pcs_pon = { + .port_type = AIROHA_PCS_PON, + .hibernation_workaround = true, + .usxgmii_ber_time_fixup = true, + .bringup = an7581_pcs_bringup, + .link_up = an7581_pcs_phya_link_up, +}; + +static const struct udevice_id airoha_pcs_of_table[] = { + { .compatible = "airoha,an7581-pcs-eth", + .data = (ulong)&an7581_pcs_eth }, + { .compatible = "airoha,an7581-pcs-pon", + .data = (ulong)&an7581_pcs_pon }, + { }, +}; + +U_BOOT_DRIVER(airoha_pcs) = { + .name = "airoha-pcs", + .id = UCLASS_MISC, + .of_match = airoha_pcs_of_table, + .probe = airoha_pcs_probe, + .priv_auto = sizeof(struct airoha_pcs_priv), +}; diff --git a/drivers/net/airoha/pcs-airoha.h b/drivers/net/airoha/pcs-airoha.h new file mode 100644 index 00000000000..714d2ebe520 --- /dev/null +++ b/drivers/net/airoha/pcs-airoha.h @@ -0,0 +1,1220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 AIROHA Inc + * Author: Christian Marangi <[email protected]> + */ + +#include <linux/bitfield.h> +#include <regmap.h> +#include <reset.h> + +/* SCU*/ +#define AIROHA_SCU_PDIDR 0x5c +#define AIROHA_SCU_PRODUCT_ID GENMASK(15, 0) +#define AIROHA_SCU_WAN_CONF 0x70 +#define AIROHA_SCU_ETH_MAC_SEL BIT(24) +#define AIROHA_SCU_ETH_MAC_SEL_XFI FIELD_PREP_CONST(AIROHA_SCU_ETH_MAC_SEL, 0x0) +#define AIROHA_SCU_ETH_MAC_SEL_PON FIELD_PREP_CONST(AIROHA_SCU_ETH_MAC_SEL, 0x1) +#define AIROHA_SCU_WAN_SEL GENMASK(7, 0) +#define AIROHA_SCU_WAN_SEL_SGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x10) +#define AIROHA_SCU_WAN_SEL_HSGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x11) +#define AIROHA_SCU_WAN_SEL_USXGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x12) +#define AIROHA_SCU_SSR3 0x94 +#define AIROHA_SCU_ETH_XSI_SEL GENMASK(14, 13) +#define AIROHA_SCU_ETH_XSI_USXGMII FIELD_PREP_CONST(AIROHA_SCU_ETH_XSI_SEL, 0x1) +#define AIROHA_SCU_ETH_XSI_HSGMII FIELD_PREP_CONST(AIROHA_SCU_ETH_XSI_SEL, 0x2) +#define AIROHA_SCU_SSTR 0x9c +#define AIROHA_SCU_PON_XSI_SEL GENMASK(10, 9) +#define AIROHA_SCU_PON_XSI_USXGMII FIELD_PREP_CONST(AIROHA_SCU_PON_XSI_SEL, 0x1) +#define AIROHA_SCU_PON_XSI_HSGMII FIELD_PREP_CONST(AIROHA_SCU_PON_XSI_SEL, 0x2) + +/* XFI_MAC */ +#define AIROHA_PCS_XFI_MAC_XFI_GIB_CFG 0x0 +#define AIROHA_PCS_XFI_RX_FRAG_LEN GENMASK(26, 22) +#define AIROHA_PCS_XFI_TX_FRAG_LEN GENMASK(21, 17) +#define AIROHA_PCS_XFI_IPG_NUM GENMASK(15, 10) +#define AIROHA_PCS_XFI_TX_FC_EN BIT(5) +#define AIROHA_PCS_XFI_RX_FC_EN BIT(4) +#define AIROHA_PCS_XFI_RXMPI_STOP BIT(3) +#define AIROHA_PCS_XFI_RXMBI_STOP BIT(2) +#define AIROHA_PCS_XFI_TXMPI_STOP BIT(1) +#define AIROHA_PCS_XFI_TXMBI_STOP BIT(0) +#define AIROHA_PCS_XFI_MAC_XFI_LOGIC_RST 0x10 +#define AIROHA_PCS_XFI_MAC_LOGIC_RST BIT(0) +#define AIROHA_PCS_XFI_MAC_XFI_MACADDRH 0x60 +#define AIROHA_PCS_XFI_MAC_MACADDRH GENMASK(15, 0) +#define AIROHA_PCS_XFI_MAC_XFI_MACADDRL 0x64 +#define AIROHA_PCS_XFI_MAC_MACADDRL GENMASK(31, 0) +#define AIROHA_PCS_XFI_MAC_XFI_CNT_CLR 0x100 +#define AIROHA_PCS_XFI_GLB_CNT_CLR BIT(0) + +/* HSGMII_AN */ +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0 0x0 +#define AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE BIT(12) +#define AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART BIT(9) +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1 0x4 /* BMSR */ +#define AIROHA_PCS_HSGMII_AN_SGMII_UNIDIR_ABILITY BIT(6) +#define AIROHA_PCS_HSGMII_AN_SGMII_AN_COMPLETE BIT(5) +#define AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT BIT(4) +#define AIROHA_PCS_HSGMII_AN_SGMII_AN_ABILITY BIT(3) +#define AIROHA_PCS_HSGMII_AN_SGMII_LINK_STATUS BIT(2) +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_4 0x10 +#define AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY GENMASK(15, 0) +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_5 0x14 /* LPA */ +#define AIROHA_PCS_HSGMII_AN_SGMII_PARTNER_ABILITY GENMASK(15, 0) +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_11 0x2c +#define AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER GENMASK(19, 0) +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13 0x34 +#define AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS BIT(8) +#define AIROHA_PCS_HSGMII_AN_SGMII_IF_MODE_5_0 GENMASK(5, 0) +#define AIROHA_PCS_HSGMII_AN_SGMII_COMPAT_EN BIT(5) +#define AIROHA_PCS_HSGMII_AN_DUPLEX_FORCE_MODE BIT(4) +#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE GENMASK(3, 2) +#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x2) +#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x1) +#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x0) +#define AIROHA_PCS_HSGMII_AN_SIDEBAND_EN BIT(1) +#define AIROHA_PCS_HSGMII_AN_SGMII_EN BIT(0) +#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37 0x60 +#define AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE BIT(0) + +/* HSGMII_PCS */ +#define AIROHA_PCS_HSGMII_PCS_CTROL_1 0x0 +#define AIROHA_PCS_TBI_10B_MODE BIT(30) +#define AIROHA_PCS_SGMII_SEND_AN_ERR_EN BIT(24) +#define AIROHA_PCS_REMOTE_FAULT_DIS BIT(12) +#define AIROHA_PCS_HSGMII_PCS_CTROL_3 0x8 +#define AIROHA_PCS_HSGMII_PCS_LINK_STSTIME GENMASK(19, 0) +#define AIROHA_PCS_HSGMII_PCS_CTROL_6 0x14 +#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 BIT(14) +#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 BIT(13) +#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 BIT(12) +#define AIROHA_PCS_HSGMII_PCS_MAC_MODE BIT(8) +#define AIROHA_PCS_HSGMII_PCS_TX_ENABLE BIT(4) +#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL GENMASK(3, 2) +#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x0) +#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x1) +#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x2) +#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT BIT(1) +#define AIROHA_PCS_HSGMII_PCS_MODE2_EN BIT(0) +#define AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT 0x20 +#define AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR BIT(11) +#define AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT BIT(10) +#define AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR BIT(9) +#define AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT BIT(8) +#define AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR BIT(5) +#define AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT BIT(4) +#define AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR BIT(3) +#define AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR BIT(2) +#define AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT BIT(1) +#define AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT BIT(0) +#define AIROHA_PCS_HSGMII_PCS_AN_SGMII_MODE_FORCE 0x24 +#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE GENMASK(5, 4) +#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x0) +#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x1) +#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x2) +#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL BIT(0) +#define ARIOHA_PCS_HSGMII_PCS_STATE_2 0x104 +#define AIROHA_PCS_HSGMII_PCS_RX_SYNC BIT(5) +#define AIROHA_PCS_HSGMII_PCS_AN_DONE BIT(0) +#define AIROHA_PCS_HSGMII_PCS_INT_STATE 0x15c +#define AIROHA_PCS_HSGMII_PCS_MODE2_REMOTE_FAULT_OCCUR_INT BIT(4) +#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_MLS BIT(3) +#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_CL37_TIMERDONE_INT BIT(2) +#define AIROHA_PCS_HSGMII_PCS_MODE2_RX_SYNC BIT(1) +#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_DONE BIT(0) + +/* MULTI_SGMII */ +#define AIROHA_PCS_MULTI_SGMII_INTERRUPT_EN_0 0x14 +#define AIROHA_PCS_MULTI_SGMII_PCS_INT_EN_0 BIT(0) +#define AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0 0x18 +#define AIROHA_PCS_LINK_MODE_P0 GENMASK(5, 4) +#define AIROHA_PCS_LINK_MODE_P0_2_5G FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x3) +#define AIROHA_PCS_LINK_MODE_P0_1G FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x2) +#define AIROHA_PCS_LINK_MODE_P0_100M FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x1) +#define AIROHA_PCS_LINK_MODE_P0_10M FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x0) +#define AIROHA_PCS_FORCE_SPD_MODE_P0 BIT(2) +#define AIROHA_PCS_FORCE_LINKDOWN_P0 BIT(1) +#define AIROHA_PCS_FORCE_LINKUP_P0 BIT(0) +#define AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0 0x100 +#define AIROHA_PCS_HSGMII_XFI_SEL BIT(28) +#define AIROHA_PCS_MULTI_SGMII_INTERRUPT_SEL 0x14c +#define AIROHA_PCS_HSGMII_PCS_INT BIT(0) +#define AIROHA_PCS_MULTI_SGMII_MSG_RX_STS_15 0x43c +#define AIROHA_PCS_LINK_STS_P0 BIT(3) +#define AIROHA_PCS_SPEED_STS_P0 GENMASK(2, 0) +#define AIROHA_PCS_SPEED_STS_P0_1G FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x2) +#define AIROHA_PCS_SPEED_STS_P0_100M FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x1) +#define AIROHA_PCS_SPEED_STS_P0_10M FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x0) +#define AIROHA_PCS_MULTI_SGMII_MSG_RX_STS_18 0x448 +#define AIROHA_PCS_P0_SGMII_IS_10 BIT(2) +#define AIROHA_PCS_P0_SGMII_IS_100 BIT(1) +#define AIROHA_PCS_P0_SGMII_IS_1000 BIT(0) + +/* HSGMII_RATE_ADP */ +#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_0 0x0 +#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS BIT(27) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS BIT(26) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN BIT(4) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN BIT(0) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1 0x4 +#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR GENMASK(20, 16) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR GENMASK(28, 24) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_6 0x18 +#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L GENMASK(31, 0) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_8 0x20 +#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C GENMASK(7, 0) +#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_11 0x2c +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN BIT(8) +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE GENMASK(15, 12) +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_10000 \ + FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x0) +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_5000 \ + FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x1) +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_2500 \ + FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x2) +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_1000 \ + FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x4) +#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_100 \ + FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x6) +#define AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0 0x100 +#define AIROHA_PCS_HSGMII_P0_DIS_MII_MODE BIT(31) + +/* USXGMII */ +#define AIROHA_PCS_USXGMII_PCS_CTROL_1 0x0 +#define AIROHA_PCS_USXGMII_SPEED_SEL_H BIT(13) +#define AIROHA_PCS_USXGMII_PCS_STUS_1 0x30 +#define AIROHA_PCS_USXGMII_RX_LINK_STUS BIT(12) +#define AIROHA_PCS_USXGMII_PRBS9_PATT_TST_ABILITY BIT(3) +#define AIROHA_PCS_USXGMII_PRBS31_PATT_TST_ABILITY BIT(2) +#define AIROHA_PCS_USXGMII_PCS_BLK_LK BIT(0) +#define AIROHA_PCS_USGMII_VENDOR_DEFINE_116 0x22c +#define AIROHA_PCS_USXGMII_PCS_CTRL_0 0x2c0 +#define AIROHA_PCS_USXGMII_T_TYPE_T_INT_EN BIT(24) +#define AIROHA_PCS_USXGMII_T_TYPE_D_INT_EN BIT(16) +#define AIROHA_PCS_USXGMII_T_TYPE_C_INT_EN BIT(8) +#define AIROHA_PCS_USXGMII_T_TYPE_S_INT_EN BIT(0) +#define AIROHA_PCS_USXGMII_PCS_CTRL_1 0x2c4 +#define AIROHA_PCS_USXGMII_R_TYPE_C_INT_EN BIT(24) +#define AIROHA_PCS_USXGMII_R_TYPE_S_INT_EN BIT(16) +#define AIROHA_PCS_USXGMII_TXPCS_FSM_ENC_ERR_INT_EN BIT(8) +#define AIROHA_PCS_USXGMII_T_TYPE_E_INT_EN BIT(0) +#define AIROHA_PCS_USXGMII_PCS_CTRL_2 0x2c8 +#define AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT_EN BIT(24) +#define AIROHA_PCS_USXGMII_R_TYPE_E_INT_EN BIT(16) +#define AIROHA_PCS_USXGMII_R_TYPE_T_INT_EN BIT(8) +#define AIROHA_PCS_USXGMII_R_TYPE_D_INT_EN BIT(0) +#define AIROHA_PCS_USXGMII_PCS_CTRL_3 0x2cc +#define AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT_EN BIT(24) +#define AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT_EN BIT(16) +#define AIROHA_PCS_USXGMII_LINK_UP_ST_INT_EN BIT(8) +#define AIROHA_PCS_USXGMII_HI_BER_ST_INT_EN BIT(0) +#define AIROHA_PCS_USXGMII_PCS_INT_STA_2 0x2d8 +#define AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT BIT(24) +#define AIROHA_PCS_USXGMII_R_TYPE_E_INT BIT(16) +#define AIROHA_PCS_USXGMII_R_TYPE_T_INT BIT(8) +#define AIROHA_PCS_USXGMII_R_TYPE_D_INT BIT(0) +#define AIROHA_PCS_USXGMII_PCS_INT_STA_3 0x2dc +#define AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT BIT(24) +#define AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT BIT(16) +#define AIROHA_PCS_USXGMII_LINK_UP_ST_INT BIT(8) +#define AIROHA_PCS_USXGMII_HI_BER_ST_INT BIT(0) +#define AIROHA_PCS_USXGMII_PCS_CTRL_4 0x2e0 +#define AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT_EN BIT(0) +#define AIROHA_PCS_USXGMII_PCS_INT_STA_4 0x2e4 +#define AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT BIT(0) +#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0 0x2f8 +#define AIROHA_PCS_USXGMII_AN_RESTART BIT(8) +#define AIROHA_PCS_USXGMII_AN_ENABLE BIT(0) +#define AIROHA_PCS_USXGMII_PCS_AN_STATS_0 0x310 +#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE GENMASK(30, 28) +#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_10G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x0) +#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_5G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x1) +#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_2_5G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x2) +#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_1G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x3) +#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_100M FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x4) +#define AIROHA_PCS_USXGMII_PARTNER_ABILITY GENMASK(15, 0) +#define AIROHA_PCS_USXGMII_PCS_AN_STATS_2 0x318 +#define AIROHA_PCS_USXGMII_PCS_AN_COMPLETE BIT(24) +#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6 0x31c +#define AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS BIT(0) +#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7 0x320 +#define AIROHA_PCS_USXGMII_XFI_MODE_TX_SEL BIT(20) +#define AIROHA_PCS_USXGMII_XFI_MODE_RX_SEL BIT(16) +#define AIROHA_PCS_USXGMII_RATE_UPDATE_MODE BIT(12) +#define AIROHA_PCS_USXGMII_MODE GENMASK(10, 8) +#define AIROHA_PCS_USXGMII_MODE_10000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x0) +#define AIROHA_PCS_USXGMII_MODE_5000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x1) +#define AIROHA_PCS_USXGMII_MODE_2500 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x2) +#define AIROHA_PCS_USXGMII_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x3) +#define AIROHA_PCS_USXGMII_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x4) +#define AN7583_PCS_USXGMII_RTL_MODIFIED 0x334 +#define AIROHA_PCS_USXGMII_MODIFIED_RX_GB_OUT_VLD BIT(25) + +/* PMA_PHYA */ +#define AIROHA_PCS_ANA_PXP_CMN_EN 0x0 +#define AIROHA_PCS_ANA_CMN_VREFSEL GENMASK(18, 16) +#define AIROHA_PCS_ANA_CMN_VREFSEL_8V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x0) +#define AIROHA_PCS_ANA_CMN_VREFSEL_8_25V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x1) +#define AIROHA_PCS_ANA_CMN_VREFSEL_8_5V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x2) +#define AIROHA_PCS_ANA_CMN_VREFSEL_8_75V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x3) +#define AIROHA_PCS_ANA_CMN_VREFSEL_9V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x4) +#define AIROHA_PCS_ANA_CMN_VREFSEL_9_25V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x5) +#define AIROHA_PCS_ANA_CMN_VREFSEL_9_5V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x6) +#define AIROHA_PCS_ANA_CMN_VREFSEL_9_75V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x7) +#define AIROHA_PCS_ANA_CMN_VREFSEL GENMASK(18, 16) +/* GENMASK(2, 0) input selection from 0 to 7 + * BIT(3) OPAMP and path EN + * BIT(4) Current path measurement + * BIT(5) voltage/current path to PAD + */ +#define AIROHA_PCS_ANA_CMN_MPXSELTOP_DC GENMASK(13, 8) +#define AIROHA_PCS_ANA_CMN_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN 0x4 +#define AIROHA_PCS_ANA_JCPLL_CHP_IOFST GENMASK(29, 24) +#define AIROHA_PCS_ANA_JCPLL_CHP_IBIAS GENMASK(21, 16) +#define AIROHA_PCS_ANA_JCPLL_LPF_SHCK_EN BIT(8) +#define AIROHA_PCS_ANA_PXP_JCPLL_LPF_BR 0x8 +#define AIROHA_PCS_ANA_JCPLL_LPF_BWR GENMASK(28, 24) +#define AIROHA_PCS_ANA_JCPLL_LPF_BP GENMASK(20, 16) +#define AIROHA_PCS_ANA_JCPLL_LPF_BC GENMASK(12, 8) +#define AIROHA_PCS_ANA_JCPLL_LPF_BR GENMASK(4, 0) +#define AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC 0xc +#define AIROHA_PCS_ANA_JCPLL_KBAND_DIV GENMASK(26, 24) +#define AIROHA_PCS_ANA_JCPLL_KBAND_CODE GENMASK(23, 16) +#define AIROHA_PCS_ANA_JCPLL_KBAND_OPTION BIT(8) +#define AIROHA_PCS_ANA_JCPLL_LPF_BWC GENMASK(4, 0) +#define AIROHA_PCS_ANA_PXP_JCPLL_KBAND_KFC 0x10 +#define AIROHA_PCS_ANA_JCPLL_KBAND_KS GENMASK(17, 16) +#define AIROHA_PCS_ANA_JCPLL_KBAND_KF GENMASK(9, 8) +#define AIROHA_PCS_ANA_JCPLL_KBAND_KFC GENMASK(1, 0) +#define AIROHA_PCS_ANA_PXP_JCPLL_MMD_PREDIV_MODE 0x14 +#define AIROHA_PCS_ANA_JCPLL_POSTDIV_D5 BIT(24) +#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE GENMASK(1, 0) +#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x0) +#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x1) +#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x2) +#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x3) +#define AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY 0x1c +#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS GENMASK(25, 24) +#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_23 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x0) +#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_21 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x1) +#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_19 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x2) +#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_15 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x3) +#define AIROHA_PCS_ANA_JCPLL_SDM_DI_EN BIT(16) +#define AIROHA_PCS_ANA_JCPLL_PLL_RSTB BIT(8) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY GENMASK(2, 0) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY_20_25 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x1) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY_40_50 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x2) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY_80_100 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x3) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY_150_200 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x4) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY_300_400 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x5) +#define AIROHA_PCS_ANA_JCPLL_RST_DLY_600_800 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x6) +#define AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM 0x20 +#define AIROHA_PCS_ANA_JCPLL_SDM_OUT BIT(24) +#define AIROHA_PCS_ANA_JCPLL_SDM_ORD GENMASK(17, 16) +#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_INT FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x0) +#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_1SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x1) +#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_2SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x2) +#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_3SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x3) +#define AIROHA_PCS_ANA_JCPLL_SDM_MODE GENMASK(9, 8) +#define AIROHA_PCS_ANA_JCPLL_SDM_IFM BIT(0) +#define AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN 0x24 +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF GENMASK(28, 24) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN GENMASK(18, 16) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x0) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x1) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_6 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x2) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x3) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_10 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x4) +#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN BIT(8) +#define AIROHA_PCS_ANA_JCPLL_SDM_HREN BIT(0) +#define AIROHA_PCS_ANA_PXP_JCPLL_TCL_CMP_EN 0x28 +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW GENMASK(26, 24) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_0_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x0) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x1) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x2) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x3) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x4) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_16 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x6) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN BIT(16) +#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW GENMASK(26, 24) +#define AIROHA_PCS_ANA_PXP_JCPLL_VCODIV 0x2c +#define AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR GENMASK(26, 24) +#define AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN BIT(16) +#define AIROHA_PCS_ANA_JCPLL_VCO_CFIX GENMASK(9, 8) +#define AIROHA_PCS_ANA_JCPLL_VCODIV GENMASK(1, 0) +#define AIROHA_PCS_ANA_JCPLL_VCODIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_VCODIV, 0x0) +#define AIROHA_PCS_ANA_JCPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_VCODIV, 0x1) +#define AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR 0x30 +#define AIROHA_PCS_ANA_JCPLL_SSC_PHASE_INI BIT(17) +#define AIROHA_PCS_ANA_JCPLL_SSC_EN BIT(16) +#define AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L GENMASK(10, 8) +#define AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H GENMASK(5, 3) +#define AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR GENMASK(2, 0) +#define AIROHA_PCS_ANA_PXP_JCPLL_SSC_TRI_EN 0x34 +#define AIROHA_PCS_ANA_JCPLL_SSC_DELTA1 GENMASK(23, 8) +#define AIROHA_PCS_ANA_JCPLL_SSC_TRI_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_JCPLL_SSC_DELTA 0x38 +#define AIROHA_PCS_ANA_JCPLL_SSC_PERIOD GENMASK(31, 16) +#define AIROHA_PCS_ANA_JCPLL_SSC_DELTA GENMASK(15, 0) +#define AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H 0x48 +#define AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF GENMASK(20, 16) +#define AIROHA_PCS_ANA_JCPLL_SPARE_L GENMASK(15, 8) +#define AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SPARE_L, BIT(5)) +#define AIROHA_PCS_ANA_PXP_JCPLL_FREQ_MEAS_EN 0x4c +#define AIROHA_PCS_ANA_TXPLL_IB_EXT_EN BIT(24) +#define AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS 0x50 +#define AIROHA_PCS_ANA_TXPLL_LPF_BC GENMASK(28, 24) +#define AIROHA_PCS_ANA_TXPLL_LPF_BR GENMASK(20, 16) +#define AIROHA_PCS_ANA_TXPLL_CHP_IOFST GENMASK(13, 8) +#define AIROHA_PCS_ANA_TXPLL_CHP_IBIAS GENMASK(5, 0) +#define AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP 0x54 +#define AIROHA_PCS_ANA_TXPLL_KBAND_OPTION BIT(24) +#define AIROHA_PCS_ANA_TXPLL_LPF_BWC GENMASK(20, 16) +#define AIROHA_PCS_ANA_TXPLL_LPF_BWR GENMASK(12, 8) +#define AIROHA_PCS_ANA_TXPLL_LPF_BP GENMASK(4, 0) +#define AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE 0x58 +#define AIROHA_PCS_ANA_TXPLL_KBAND_KF GENMASK(25, 24) +#define AIROHA_PCS_ANA_TXPLL_KBAND_KFC GENMASK(17, 16) +#define AIROHA_PCS_ANA_TXPLL_KBAND_DIV GENMASK(10, 8) +#define AIROHA_PCS_ANA_TXPLL_KBAND_CODE GENMASK(7, 0) +#define AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS 0x5c +#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE GENMASK(17, 16) +#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x0) +#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x1) +#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x2) +#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x3) +#define AIROHA_PCS_ANA_TXPLL_POSTDIV_EN BIT(8) +#define AIROHA_PCS_ANA_TXPLL_KBAND_KS GENMASK(1, 0) +#define AIROHA_PCS_ANA_PXP_TXPLL_PHY_CK1_EN 0x60 +#define AIROHA_PCS_ANA_TXPLL_PHY_CK2_EN BIT(8) +#define AIROHA_PCS_ANA_TXPLL_PHY_CK1_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL 0x64 +#define AIROHA_PCS_ANA_TXPLL_PLL_RSTB BIT(24) +#define AIROHA_PCS_ANA_TXPLL_RST_DLY GENMASK(18, 16) +#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV GENMASK(9, 8) +#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x0) +#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x1) +#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x2) +#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x3) +#define AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN 0x68 +#define AIROHA_PCS_ANA_TXPLL_SDM_MODE GENMASK(25, 24) +#define AIROHA_PCS_ANA_TXPLL_SDM_IFM BIT(16) +#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS GENMASK(9, 8) +#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x0) +#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_21 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x1) +#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_19 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x2) +#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_15 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x3) +#define AIROHA_PCS_ANA_TXPLL_SDM_DI_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD 0x6c +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN BIT(24) +#define AIROHA_PCS_ANA_TXPLL_SDM_HREN BIT(16) +#define AIROHA_PCS_ANA_TXPLL_SDM_OUT BIT(8) +#define AIROHA_PCS_ANA_TXPLL_SDM_ORD GENMASK(1, 0) +#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_INT FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x0) +#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_1SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x1) +#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_2SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x2) +#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x3) +#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN 0x70 +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF GENMASK(12, 8) +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN GENMASK(2, 0) +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x0) +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_2_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x1) +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x2) +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x3) +#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_6 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x4) +#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN 0x74 +#define AIROHA_PCS_ANA_TXPLL_VCO_CFIX GENMASK(25, 24) +#define AIROHA_PCS_ANA_TXPLL_VCODIV GENMASK(17, 16) +#define AIROHA_PCS_ANA_TXPLL_VCODIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x0) +#define AIROHA_PCS_ANA_TXPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x1) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW GENMASK(10, 8) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x0) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x1) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x2) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x3) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x4) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_16 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x6) +#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN 0x78 +#define AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L GENMASK(29, 27) +#define AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H GENMASK(26, 24) +#define AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR GENMASK(18, 16) +#define AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR GENMASK(10, 8) +#define AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN 0x7c +#define AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN BIT(16) +#define AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI BIT(8) +#define AIROHA_PCS_ANA_TXPLL_SSC_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1 0x80 +#define AIROHA_PCS_ANA_TXPLL_SSC_DELTA GENMASK(31, 16) +#define AIROHA_PCS_ANA_TXPLL_SSC_DELTA1 GENMASK(15, 0) +#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD 0x84 +#define AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT GENMASK(25, 24) +#define AIROHA_PCS_ANA_TXPLL_LDO_OUT GENMASK(17, 16) +#define AIROHA_PCS_ANA_TXPLL_SSC_PERIOD GENMASK(15, 0) +#define AIROHA_PCS_ANA_PXP_TXPLL_VTP_EN 0x88 +#define AIROHA_PCS_ANA_TXPLL_VTP GENMASK(10, 8) +#define AIROHA_PCS_ANA_TXPLL_VTP_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF 0x94 +#define AIROHA_PCS_ANA_TXPLL_POSTDIV_D256_EN BIT(25) /* 0: 128 1: 256 */ +#define AIROHA_PCS_ANA_TXPLL_VCO_KBAND_MEAS_EN BIT(24) +#define AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN BIT(16) +#define AIROHA_PCS_ANA_TXPLL_VREF_SEL BIT(8) +#define AIROHA_PCS_ANA_TXPLL_VREF_SEL_VBG FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VREF_SEL, 0x0) +#define AIROHA_PCS_ANA_TXPLL_VREF_SEL_AVDD FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VREF_SEL, 0x1) +#define AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF GENMASK(4, 0) +#define AN7583_PCS_ANA_PXP_TXPLL_CHP_DOUBLE_EN 0x98 +#define AIROHA_PCS_ANA_TXPLL_SPARE_L BIT(0) /* ICHP_DOUBLE */ +#define AIROHA_PCS_ANA_PXP_PLL_MONCLK_SEL 0xa0 +#define AIROHA_PCS_ANA_TDC_AUTOEN BIT(24) +#define AIROHA_PCS_ANA_PXP_TDC_SYNC_CK_SEL 0xa8 +#define AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL GENMASK(17, 16) +#define AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN BIT(8) +#define AIROHA_PCS_ANA_PXP_TX_TXLBRC_EN 0xc0 +#define AIROHA_PCS_ANA_TX_TERMCAL_VREF_L GENMASK(26, 24) +#define AIROHA_PCS_ANA_TX_TERMCAL_VREF_H GENMASK(18, 16) +#define AIROHA_PCS_ANA_PXP_TX_CKLDO_EN 0xc4 +#define AIROHA_PCS_ANA_TX_DMEDGEGEN_EN BIT(24) +#define AIROHA_PCS_ANA_TX_CKLDO_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_TX_TERMCAL_SELPN 0xc8 +#define AIROHA_PCS_ANA_TX_TDC_CK_SEL GENMASK(17, 16) +#define AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL 0xcc +#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE BIT(24) +#define AIROHA_PCS_ANA_RX_PHY_CK_SEL BIT(16) +#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_PR FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x0) +#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_DES FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x1) +#define AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE BIT(8) +#define AIROHA_PCS_ANA_RX_BUSBIT_SEL BIT(0) +#define AIROHA_PCS_ANA_RX_BUSBIT_SEL_8BIT FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_BUSBIT_SEL, 0x0) +#define AIROHA_PCS_ANA_RX_BUSBIT_SEL_16BIT FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_BUSBIT_SEL, 0x1) +#define AIROHA_PCS_ANA_PXP_RX_REV_0 0xd4 +#define AIROHA_PCS_ANA_RX_REV_1 GENMASK(31, 16) +#define AIROHA_PCS_ANA_REV_1_FE_EQ_BIAS_CTRL GENMASK(30, 28) +#define AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL GENMASK(26, 24) +#define AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL GENMASK(22, 20) +#define AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK GENMASK(19, 18) +#define AIROHA_PCS_ANA_REV_1_FECUR_PWDB BIT(16) +#define AIROHA_PCS_ANA_RX_REV_0 GENMASK(15, 0) +#define AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE GENMASK(13, 12) +#define AIROHA_PCS_ANA_REV_0_OSCAL_FE_MODE_SET_SEL BIT(11) +#define AIROHA_PCS_ANA_REV_0_FE_EQ_GAIN_MODE_TRAINING BIT(10) +#define AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_TRAINING GENMASK(9, 8) +#define AIROHA_PCS_ANA_REV_0_FE_EQ_GAIN_MODE_NORMAL BIT(6) +#define AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL GENMASK(5, 4) +#define AIROHA_PCS_ANA_REV_0_VOS_PNINV GENMASK(3, 2) +#define AIROHA_PCS_ANA_REV_0_PLEYEBD4 BIT(1) +#define AIROHA_PCS_ANA_REV_0_PLEYE_XOR_MON_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV 0xd8 +#define AIROHA_PCS_ANA_RX_TDC_CK_SEL BIT(24) +#define AIROHA_PCS_ANA_RX_PHYCK_RSTB BIT(16) +#define AIROHA_PCS_ANA_RX_PHYCK_SEL GENMASK(9, 8) +#define AIROHA_PCS_ANA_RX_PHYCK_DIV GENMASK(7, 0) +#define AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV 0xdc +#define AIROHA_PCS_ANA_CDR_PD_EDGE_DIS BIT(8) +#define AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV BIT(0) +#define AIROHA_PCS_ANA_PXP_CDR_LPF_BOT_LIM 0xe0 +#define AIROHA_PCS_ANA_CDR_LPF_BOT_LIM GENMASK(18, 0) +#define AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO 0xe8 +#define AIROHA_PCS_ANA_CDR_LPF_TOP_LIM GENMASK(26, 8) +#define AIROHA_PCS_ANA_CDR_LPF_RATIO GENMASK(1, 0) +#define AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE 0xf4 +#define AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF BIT(24) +#define AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC 0xf8 +#define AIROHA_PCS_ANA_CDR_PR_KBAND_DIV GENMASK(26, 24) +#define AIROHA_PCS_ANA_CDR_PR_BETA_SEL GENMASK(19, 16) +#define AIROHA_PCS_ANA_CDR_PR_VCOADC_OS GENMASK(11, 8) +#define AIROHA_PCS_ANA_CDR_PR_BETA_DAC GENMASK(6, 0) +#define AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL 0xfc +#define AIROHA_PCS_ANA_CDR_PR_FBKSEL GENMASK(25, 24) +#define AIROHA_PCS_ANA_CDR_PR_DAC_BAND GENMASK(20, 16) +#define AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL GENMASK(10, 8) +#define AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL GENMASK(2, 0) +#define AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV 0x100 +#define AIROHA_PCS_ANA_CDR_PR_RSTB_BYPASS BIT(16) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV GENMASK(1, 0) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x0) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x1) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x2) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_X FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x3) +#define AIROHA_PCS_ANA_PXP_CDR_PR_TDC_REF_SEL 0x108 +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1 GENMASK(25, 24) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x0) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x1) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x2) +#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_X FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x3) +#define AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN 0x10c +#define AIROHA_PCS_ANA_RX_DAC_MON GENMASK(28, 24) +#define AIROHA_PCS_ANA_CDR_PR_CAP_EN BIT(19) +#define AIROHA_PCS_ANA_CDR_BUF_IN_SR GENMASK(18, 16) +#define AIROHA_PCS_ANA_CDR_PR_XFICK_EN BIT(2) +#define AIROHA_PCS_ANA_CDR_PR_MONDPI_EN BIT(1) +#define AIROHA_PCS_ANA_CDR_PR_MONDPR_EN BIT(0) +#define AIROHA_PCS_ANA_PXP_RX_DAC_RANGE 0x110 +#define AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL GENMASK(25, 24) +#define AIROHA_PCS_ANA_RX_DAC_RANGE_EYE GENMASK(9, 8) +#define AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH 0x114 +#define AIROHA_PCS_ANA_RX_FE_50OHMS_SEL GENMASK(25, 24) +#define AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL GENMASK(20, 16) +#define AIROHA_PCS_ANA_RX_SIGDET_PEAK GENMASK(9, 8) +#define AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN 0x118 +#define AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN BIT(24) +#define AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN BIT(16) +#define AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN BIT(8) +#define AIROHA_PCS_ANA_RX_FE_EQ_HZEN BIT(0) +#define AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB 0x11c +#define AIROHA_PCS_ANA_FE_VCM_GEN_PWDB BIT(0) +#define AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW 0x120 +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE GENMASK(17, 8) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(0)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(1)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(2)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(3)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(4)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(5)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(6)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(7)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(8)) +#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(9)) +#define AIROHA_PCS_ANA_PXP_AEQ_CFORCE 0x13c +#define AIROHA_PCS_ANA_AEQ_OFORCE GENMASK(19, 8) +#define AIROHA_PCS_ANA_AEQ_OFORCE_SAOS FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(0)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP1 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(1)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP2 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(2)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP3 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(3)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP4 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(4)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP5 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(5)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP6 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(6)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP7 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(7)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_VGA FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(8)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_CTLE FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(9)) +#define AIROHA_PCS_ANA_AEQ_OFORCE_ATT FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(10)) +#define AIROHA_PCS_ANA_PXP_RX_FE_PEAKING_CTRL_MSB 0x144 +#define AIROHA_PCS_ANA_RX_DAC_D0_BYPASS_AEQ BIT(24) +#define AIROHA_PCS_ANA_PXP_RX_DAC_D1_BYPASS_AEQ 0x148 +#define AIROHA_PCS_ANA_RX_DAC_EYE_BYPASS_AEQ BIT(24) +#define AIROHA_PCS_ANA_RX_DAC_E1_BYPASS_AEQ BIT(16) +#define AIROHA_PCS_ANA_RX_DAC_E0_BYPASS_AEQ BIT(8) +#define AIROHA_PCS_ANA_RX_DAC_D1_BYPASS_AEQ BIT(0) + +/* PMA_PHYD */ +#define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0 0x0 +#define AIROHA_PCS_PMA_SW_LCPLL_EN BIT(24) +#define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1 0x4 +#define AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER GENMASK(31, 24) +#define AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER GENMASK(23, 16) +#define AIROHA_PCS_PMA_LCPLL_EN_TIMER GENMASK(15, 8) +#define AIROHA_PCS_PMA_LCPLL_MAN_PWDB BIT(0) +#define AIROHA_PCS_PMA_LCPLL_TDC_PW_0 0x10 +#define AIROHA_PCS_PMA_LCPLL_TDC_DIG_PWDB BIT(0) +#define AIROHA_PCS_PMA_LCPLL_TDC_PW_5 0x24 +#define AIROHA_PCS_PMA_LCPLL_TDC_SYNC_IN_MODE BIT(24) +#define AIROHA_PCS_PMA_LCPLL_AUTOK_TDC BIT(16) +#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_0 0x28 +#define AIROHA_PCS_PMA_LCPLL_KI GENMASK(10, 8) +#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC GENMASK(1, 0) +#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_32 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x0) +#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_16 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x1) +#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x2) +#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x3) +#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_1 0x2c +#define AIROHA_PCS_PMA_LCPLL_A_TDC GENMASK(11, 8) +#define AIROHA_PCS_PMA_LCPLL_GPON_SEL BIT(0) +#define AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_EPON FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_GPON_SEL, 0x0) +#define AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_GPON FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_GPON_SEL, 0x1) +#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_3 0x34 +#define AIROHA_PCS_PMA_LCPLL_NCPO_LOAD BIT(8) +#define AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT GENMASK(1, 0) +#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_5 0x3c +#define AIROHA_PCS_PMA_LCPLL_TDC_AUTOPW_NCPO BIT(16) +#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_6 0x40 +#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY GENMASK(9, 8) +#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x0) +#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D1 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x1) +#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D2 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x2) +#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D3 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x3) +#define AIROHA_PCS_PMA_LCPLL_TDC_PCW_1 0x48 +#define AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0) +#define AIROHA_PCS_PMA_LCPLL_TDC_PCW_2 0x4c +#define AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON GENMASK(30, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0 0x68 +#define AIROHA_PCS_PMA_X_MAX GENMASK(26, 16) +#define AIROHA_PCS_PMA_X_MIN GENMASK(10, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1 0x6c +#define AIROHA_PCS_PMA_INDEX_MODE BIT(16) +#define AIROHA_PCS_PMA_Y_MAX GENMASK(14, 8) +#define AIROHA_PCS_PMA_Y_MIN GENMASK(6, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2 0x70 +#define AIROHA_PCS_PMA_EYEDUR GENMASK(19, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3 0x74 +#define AIROHA_PCS_PMA_EYE_NEXTPTS BIT(16) +#define AIROHA_PCS_PMA_EYE_NEXTPTS_TOGGLE BIT(8) +#define AIROHA_PCS_PMA_EYE_NEXTPTS_SEL BIT(0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0 0x78 +#define AIROHA_PCS_PMA_EYECNT_VTH GENMASK(15, 8) +#define AIROHA_PCS_PMA_EYECNT_HTH GENMASK(7, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1 0x7c +#define AIROHA_PCS_PMA_EO_VTH GENMASK(23, 16) +#define AIROHA_PCS_PMA_EO_HTH GENMASK(10, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0 0x80 +#define AIROHA_PCS_PMA_EYE_MASK GENMASK(31, 24) +#define AIROHA_PCS_PMA_CNTFOREVER BIT(16) +#define AIROHA_PCS_PMA_CNTLEN GENMASK(9, 0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1 0x84 +#define AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B BIT(24) +#define AIROHA_PCS_PMA_FORCE_EYEDUR_EN BIT(16) +#define AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B BIT(8) +#define AIROHA_PCS_PMA_DISB_EYEDUR_EN BIT(0) +#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2 0x88 +#define AIROHA_PCS_PMA_DATA_SHIFT BIT(8) +#define AIROHA_PCS_PMA_EYECNT_FAST BIT(0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0 0x8c +#define AIROHA_PCS_PMA_RX_OS_START GENMASK(23, 8) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT GENMASK(2, 0) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_05 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x0) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x1) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x2) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x3) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x4) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_1_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x5) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_3_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x6) +#define AIROHA_PCS_PMA_OSC_SPEED_OPT_6_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x7) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1 0x90 +#define AIROHA_PCS_PMA_RX_PICAL_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_RX_PICAL_START GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2 0x94 +#define AIROHA_PCS_PMA_RX_PDOS_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_RX_PDOS_START GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3 0x98 +#define AIROHA_PCS_PMA_RX_FEOS_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_RX_FEOS_START GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4 0x9c +#define AIROHA_PCS_PMA_RX_SDCAL_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_RX_SDCAL_START GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5 0x100 +#define AIROHA_PCS_PMA_RX_RDY GENMASK(31, 16) +#define AIROHA_PCS_PMA_RX_BLWC_RDY_EN GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6 0x104 +#define AIROHA_PCS_PMA_RX_OS_END GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0 0x108 +#define AIROHA_PCS_PMA_DISB_RX_FEOS_EN BIT(24) +#define AIROHA_PCS_PMA_DISB_RX_PDOS_EN BIT(16) +#define AIROHA_PCS_PMA_DISB_RX_PICAL_EN BIT(8) +#define AIROHA_PCS_PMA_DISB_RX_OS_EN BIT(0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1 0x10c +#define AIROHA_PCS_PMA_DISB_RX_RDY BIT(24) +#define AIROHA_PCS_PMA_DISB_RX_BLWC_EN BIT(16) +#define AIROHA_PCS_PMA_DISB_RX_OS_RDY BIT(8) +#define AIROHA_PCS_PMA_DISB_RX_SDCAL_EN BIT(0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0 0x110 +#define AIROHA_PCS_PMA_FORCE_RX_FEOS_EN BIT(24) +#define AIROHA_PCS_PMA_FORCE_RX_PDOS_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_RX_PICAL_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_RX_OS_EN BIT(0) +#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1 0x114 +#define AIROHA_PCS_PMA_FORCE_RX_RDY BIT(24) +#define AIROHA_PCS_PMA_FORCE_RX_BLWC_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_RX_OS_RDY BIT(8) +#define AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN BIT(0) +#define AIROHA_PCS_PMA_PHY_EQ_CTRL_0 0x118 +#define AIROHA_PCS_PMA_VEO_MASK GENMASK(31, 24) +#define AIROHA_PCS_PMA_HEO_MASK GENMASK(18, 8) +#define AIROHA_PCS_PMA_EQ_EN_DELAY GENMASK(7, 0) +#define AIROHA_PCS_PMA_PHY_EQ_CTRL_1 0x11c +#define AIROHA_PCS_PMA_B_ZERO_SEL BIT(24) +#define AIROHA_PCS_PMA_HEO_EMPHASIS BIT(16) +#define AIROHA_PCS_PMA_A_MGAIN BIT(8) +#define AIROHA_PCS_PMA_A_LGAIN BIT(0) +#define AIROHA_PCS_PMA_PHY_EQ_CTRL_2 0x120 +#define AIROHA_PCS_PMA_EQ_DEBUG_SEL GENMASK(17, 16) +#define AIROHA_PCS_PMA_FOM_NUM_ORDER GENMASK(12, 8) +#define AIROHA_PCS_PMA_A_SEL GENMASK(1, 0) +#define AIROHA_PCS_PMA_SS_RX_FEOS 0x144 +#define AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE BIT(8) +#define AIROHA_PCS_PMA_LFSEL GENMASK(7, 0) +#define AIROHA_PCS_PMA_SS_RX_BLWC 0x148 +#define AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM GENMASK(29, 23) +#define AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM GENMASK(22, 16) +#define AIROHA_PCS_PMA_EQ_BLWC_GAIN GENMASK(11, 8) +#define AIROHA_PCS_PMA_EQ_BLWC_POL BIT(0) +#define AIROHA_PCS_PMA_EQ_BLWC_POL_NORMAL FIELD_PREP_CONST(AIROHA_PCS_PMA_EQ_BLWC_POL, 0x0) +#define AIROHA_PCS_PMA_EQ_BLWC_POL_INVERSION FIELD_PREP_CONST(AIROHA_PCS_PMA_EQ_BLWC_POL, 0x1) +#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_1 0x14c +#define AIROHA_PCS_PMA_UNLOCK_CYCLECNT GENMASK(31, 16) +#define AIROHA_PCS_PMA_LOCK_CYCLECNT GENMASK(15, 0) +#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_2 0x150 +#define AIROHA_PCS_PMA_LOCK_TARGET_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_LOCK_TARGET_BEG GENMASK(15, 0) +#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_3 0x154 +#define AIROHA_PCS_PMA_UNLOCK_TARGET_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_UNLOCK_TARGET_BEG GENMASK(15, 0) +#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_4 0x158 +#define AIROHA_PCS_PMA_LOCK_UNLOCKTH GENMASK(15, 12) +#define AIROHA_PCS_PMA_LOCK_LOCKTH GENMASK(11, 8) +#define AIROHA_PCS_PMA_FREQLOCK_DET_EN GENMASK(2, 0) +#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x0) +#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x1) +#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_WAIT FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x2) +#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x3) +#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_RX_STATE FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x7) +#define AIROHA_PCS_PMA_RX_PI_CAL 0x15c +#define AIROHA_PCS_PMA_KPGAIN GENMASK(10, 8) +#define AIROHA_PCS_PMA_RX_CAL1 0x160 +#define AIROHA_PCS_PMA_CAL_CYC GENMASK(25, 24) +#define AIROHA_PCS_PMA_CAL_CYC_63 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x0) +#define AIROHA_PCS_PMA_CAL_CYC_15 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x1) +#define AIROHA_PCS_PMA_CAL_CYC_31 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x2) +#define AIROHA_PCS_PMA_CAL_CYC_127 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x3) +#define AIROHA_PCS_PMA_CAL_STB GENMASK(17, 16) +#define AIROHA_PCS_PMA_CAL_STB_5US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x0) +#define AIROHA_PCS_PMA_CAL_STB_8US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x1) +#define AIROHA_PCS_PMA_CAL_STB_16US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x2) +#define AIROHA_PCS_PMA_CAL_STB_32US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x3) +#define AIROHA_PCS_PMA_CAL_1US_SET GENMASK(15, 8) +#define AIROHA_PCS_PMA_SIM_FAST_EN BIT(0) +#define AIROHA_PCS_PMA_RX_CAL2 0x164 +#define AIROHA_PCS_PMA_CAL_CYC_TIME GENMASK(17, 16) +#define AIROHA_PCS_PMA_CAL_OUT_OS GENMASK(11, 8) +#define AIROHA_PCS_PMA_CAL_OS_PULSE BIT(0) +#define AIROHA_PCS_PMA_SS_RX_SIGDET_1 0x16c +#define AIROHA_PCS_PMA_SIGDET_EN BIT(0) +#define AIROHA_PCS_PMA_RX_FLL_0 0x170 +#define AIROHA_PCS_PMA_KBAND_KFC GENMASK(25, 24) +#define AIROHA_PCS_PMA_KBAND_KFC_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x0) +#define AIROHA_PCS_PMA_KBAND_KFC_16 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x1) +#define AIROHA_PCS_PMA_KBAND_KFC_32 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x2) +#define AIROHA_PCS_PMA_KBAND_KFC_64 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x3) +#define AIROHA_PCS_PMA_FPKDIV GENMASK(18, 8) +#define AIROHA_PCS_PMA_KBAND_PREDIV GENMASK(2, 0) +#define AIROHA_PCS_PMA_KBAND_PREDIV_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x0) +#define AIROHA_PCS_PMA_KBAND_PREDIV_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x1) +#define AIROHA_PCS_PMA_KBAND_PREDIV_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x2) +#define AIROHA_PCS_PMA_KBAND_PREDIV_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x3) +#define AIROHA_PCS_PMA_RX_FLL_1 0x174 +#define AIROHA_PCS_PMA_SYMBOL_WD GENMASK(26, 24) +#define AIROHA_PCS_PMA_SETTLE_TIME_SEL GENMASK(18, 16) +#define AIROHA_PCS_PMA_LPATH_IDAC GENMASK(10, 0) +#define AIROHA_PCS_PMA_RX_FLL_2 0x178 +#define AIROHA_PCS_PMA_CK_RATE GENMASK(18, 16) +#define AIROHA_PCS_PMA_CK_RATE_20 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x0) +#define AIROHA_PCS_PMA_CK_RATE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x1) +#define AIROHA_PCS_PMA_CK_RATE_5 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x2) +#define AIROHA_PCS_PMA_AMP GENMASK(10, 8) +#define AIROHA_PCS_PMA_PRBS_SEL GENMASK(2, 0) +#define AIROHA_PCS_PMA_RX_FLL_5 0x184 +#define AIROHA_PCS_PMA_FLL_IDAC_MIN GENMASK(26, 16) +#define AIROHA_PCS_PMA_FLL_IDAC_MAX GENMASK(10, 0) +#define AIROHA_PCS_PMA_RX_FLL_6 0x188 +#define AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN BIT(24) +#define AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN BIT(16) +#define AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN BIT(8) +#define AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN BIT(0) +#define AIROHA_PCS_PMA_RX_FLL_B 0x19c +#define AIROHA_PCS_PMA_LOAD_EN BIT(0) +#define AIROHA_PCS_PMA_RX_PDOS_CTRL_0 0x200 +#define AIROHA_PCS_PMA_SAP_SEL GENMASK(18, 16) +#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x0) +#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_7 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x1) +#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x2) +#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_9 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x3) +#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x4) +#define AIROHA_PCS_PMA_EYE_BLWC_ADD BIT(8) +#define AIROHA_PCS_PMA_DATA_BLWC_ADD BIT(0) +#define AIROHA_PCS_PMA_RX_RESET_0 0x204 +#define AIROHA_PCS_PMA_CAL_RST_B BIT(24) +#define AIROHA_PCS_PMA_EQ_PI_CAL_RST_B BIT(16) +#define AIROHA_PCS_PMA_FEOS_RST_B BIT(8) +#define AIROHA_PCS_PMA_RX_RESET_1 0x208 +#define AIROHA_PCS_PMA_SIGDET_RST_B BIT(8) +#define AIROHA_PCS_PMA_PDOS_RST_B BIT(0) +#define AIROHA_PCS_PMA_RX_DEBUG_0 0x20c +#define AIROHA_PCS_PMA_RO_TOGGLE BIT(24) +#define AIROHA_PCS_PMA_BISTCTL_CONTROL 0x210 +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL GENMASK(4, 0) +/* AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x0) */ +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS7 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x1) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS9 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x2) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS15 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x3) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS23 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x4) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS31 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x5) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_HFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x6) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_MFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x7) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x8) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_5_LFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x9) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xa) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_7 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xb) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_8_LFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xc) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_9 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xd) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xe) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_11 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xf) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PROG_80 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x10) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x11) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x12) +#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS11 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x13) +#define AIROHA_PCS_PMA_BISTCTL_ALIGN_PAT 0x214 +#define AIROHA_PCS_PMA_BISTCTL_POLLUTION 0x220 +#define AIROHA_PCS_PMA_BIST_TX_DATA_POLLUTION_LATCH BIT(16) +#define AIROHA_PCS_PMA_BISTCTL_PRBS_INITIAL_SEED 0x224 +#define AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD 0x230 +#define AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK GENMASK(15, 0) +#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_2 0x23c +#define AIROHA_PCS_PMA_PI_CAL_DATA_OUT GENMASK(22, 16) +#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_5 0x248 +#define AIROHA_PCS_PMA_VEO_RDY BIT(24) +#define AIROHA_PCS_PMA_HEO_RDY BIT(16) +#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_9 0x258 +#define AIROHA_PCS_PMA_EO_Y_DONE BIT(24) +#define AIROHA_PCS_PMA_EO_X_DONE BIT(16) +#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_10 0x25c +#define AIROHA_PCS_PMA_EYE_EL GENMASK(26, 16) +#define AIROHA_PCS_PMA_EYE_ER GENMASK(10, 0) +#define AIROHA_PCS_PMA_TX_RST_B 0x260 +#define AIROHA_PCS_PMA_TXCALIB_RST_B BIT(8) +#define AIROHA_PCS_PMA_TX_TOP_RST_B BIT(0) +#define AIROHA_PCS_PMA_TX_CALIB_0 0x264 +#define AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL GENMASK(25, 24) +#define AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN BIT(16) +#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_11 0x290 +#define AIROHA_PCS_PMA_EYE_EB GENMASK(14, 8) +#define AIROHA_PCS_PMA_EYE_EU GENMASK(6, 0) +#define AIROHA_PCS_PMA_RX_FORCE_MODE_0 0x294 +#define AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL GENMASK(1, 0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_0 0x300 +#define AIROHA_PCS_PMA_DISB_DA_XPON_CDR_LPF_RSTB BIT(24) +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_GAIN_CTRL BIT(0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_1 0x304 +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E0 BIT(24) +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D1 BIT(16) +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D0 BIT(8) +#define AIROHA_PCS_PMA_RX_DISB_MODE_2 0x308 +#define AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE BIT(24) +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_VOS BIT(16) +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE BIT(8) +#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E1 BIT(0) +#define AIROHA_PCS_PMA_RX_FORCE_MODE_3 0x30c +#define AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY BIT(0) +#define AIROHA_PCS_PMA_RX_FORCE_MODE_6 0x318 +#define AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_EYECNT_RDY BIT(0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_3 0x31c +#define AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY BIT(0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_4 0x320 +#define AIROHA_PCS_PMA_DISB_BLWC_OFFSET BIT(24) +#define AIROHA_PCS_PMA_RX_DISB_MODE_5 0x324 +#define AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN BIT(24) +#define AIROHA_PCS_PMA_DISB_EYECNT_RDY BIT(16) +#define AIROHA_PCS_PMA_RX_FORCE_MODE_7 0x328 +#define AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B BIT(16) +#define AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB BIT(8) +#define AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB BIT(0) +#define AIROHA_PCS_PMA_RX_FORCE_MODE_8 0x32c +#define AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B BIT(24) +#define AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B BIT(16) +#define AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B BIT(8) +#define AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B BIT(0) +#define AIROHA_PCS_PMA_RX_FORCE_MODE_9 0x330 +#define AIROHA_PCS_PMA_FORCE_EYE_TOP_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O BIT(8) +#define AIROHA_PCS_PMA_FORCE_FBCK_LOCK BIT(0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_6 0x334 +#define AIROHA_PCS_PMA_DISB_PDOS_RX_RST_B BIT(16) +#define AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB BIT(8) +#define AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB BIT(0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_7 0x338 +#define AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B BIT(24) +#define AIROHA_PCS_PMA_DISB_FEOS_RX_RST_B BIT(16) +#define AIROHA_PCS_PMA_DISB_SDCAL_REF_RST_B BIT(8) +#define AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B BIT(0) +#define AIROHA_PCS_PMA_RX_DISB_MODE_8 0x33c +#define AIROHA_PCS_PMA_DISB_EYE_TOP_EN BIT(16) +#define AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O BIT(8) +#define AIROHA_PCS_PMA_DISB_FBCK_LOCK BIT(0) +#define AIROHA_PCS_PMA_SS_BIST_1 0x344 +#define AIROHA_PCS_PMA_LNX_BISTCTL_BIT_ERROR_RST_SEL BIT(24) +#define AIROHA_PCS_PMA_ANLT_PX_LNX_LT_LOS BIT(0) +#define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0 0x34c +#define AIROHA_PCS_PMA_XPON_CDR_PD_PWDB BIT(24) +#define AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB BIT(16) +#define AIROHA_PCS_PMA_XPON_CDR_PW_PWDB BIT(8) +#define AIROHA_PCS_PMA_XPON_RX_FE_PWDB BIT(0) +#define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1 0x350 +#define AIROHA_PCS_PMA_RX_SIDGET_PWDB BIT(0) +#define AIROHA_PCS_PMA_DIG_RESERVE_0 0x360 +#define AIROHA_PCS_PMA_XPON_RX_RESERVED_1 0x374 +#define AIROHA_PCS_PMA_XPON_RX_RATE_CTRL GENMASK(1, 0) +#define AIROHA_PCS_PMA_RX_SYS_EN_SEL_0 0x38c +#define AIROHA_PCS_PMA_RX_SYS_EN_SEL GENMASK(1, 0) +#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_0 0x390 +#define AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT GENMASK(15, 0) +#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_1 0x394 +#define AIROHA_PCS_PMA_PLL_LOCK_TARGET_END GENMASK(31, 16) +#define AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG GENMASK(15, 0) +#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_3 0x39c +#define AIROHA_PCS_PMA_PLL_LOCK_LOCKTH GENMASK(11, 8) +#define AIROHA_PCS_PMA_ADD_CLKPATH_RST_0 0x410 +#define AIROHA_PCS_PMA_CLKPATH_RSTB_CK BIT(8) +#define AIROHA_PCS_PMA_CLKPATH_RST_EN BIT(0) +#define AIROHA_PCS_PMA_ADD_XPON_MODE_1 0x414 +#define AIROHA_PCS_PMA_TX_BIST_GEN_EN BIT(16) +#define AIROHA_PCS_PMA_R2T_MODE BIT(8) +#define AIROHA_PCS_PMA_ADD_RX2ANA_1 0x424 +#define AIROHA_PCS_PMA_RX_DAC_E0 GENMASK(30, 24) +#define AIROHA_PCS_PMA_RX_DAC_D1 GENMASK(22, 16) +#define AIROHA_PCS_PMA_RX_DAC_D0 GENMASK(14, 8) +#define AIROHA_PCS_PMA_RX_DAC_EYE GENMASK(6, 0) +#define AIROHA_PCS_PMA_ADD_RX2ANA_2 0x428 +#define AIROHA_PCS_PMA_RX_FEOS_OUT GENMASK(13, 8) +#define AIROHA_PCS_PMA_RX_DAC_E1 GENMASK(6, 0) +#define AIROHA_PCS_PMA_PON_TX_COUNTER_0 0x440 +#define AIROHA_PCS_PMA_TXCALIB_5US GENMASK(31, 16) +#define AIROHA_PCS_PMA_TXCALIB_50US GENMASK(15, 0) +#define AIROHA_PCS_PMA_PON_TX_COUNTER_1 0x444 +#define AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT GENMASK(31, 16) +#define AIROHA_PCS_PMA_TX_CK_EN_WAIT GENMASK(15, 0) +#define AIROHA_PCS_PMA_PON_TX_COUNTER_2 0x448 +#define AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT GENMASK(31, 16) +#define AIROHA_PCS_PMA_TX_POWER_ON_WAIT GENMASK(15, 0) +#define AIROHA_PCS_PMA_SW_RST_SET 0x460 +#define AIROHA_PCS_PMA_SW_XFI_RXMAC_RST_N BIT(17) +#define AIROHA_PCS_PMA_SW_XFI_TXMAC_RST_N BIT(16) +#define AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N BIT(11) +#define AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N BIT(10) +#define AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N BIT(9) +#define AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N BIT(8) +#define AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N BIT(7) +#define AIROHA_PCS_PMA_SW_TX_FIFO_RST_N BIT(6) +#define AIROHA_PCS_PMA_SW_REF_RST_N BIT(5) +#define AIROHA_PCS_PMA_SW_ALLPCS_RST_N BIT(4) +#define AIROHA_PCS_PMA_SW_PMA_RST_N BIT(3) +#define AIROHA_PCS_PMA_SW_TX_RST_N BIT(2) +#define AIROHA_PCS_PMA_SW_RX_RST_N BIT(1) +#define AIROHA_PCS_PMA_SW_RX_FIFO_RST_N BIT(0) +#define AIROHA_PCS_PMA_TX_DLY_CTRL 0x468 +#define AIROHA_PCS_PMA_OUTBEN_DATA_MODE GENMASK(30, 28) +#define AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE GENMASK(23, 16) +#define AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE GENMASK(14, 8) +#define AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE GENMASK(6, 0) +#define AIROHA_PCS_PMA_XPON_INT_EN_3 0x474 +#define AIROHA_PCS_PMA_RX_SIGDET_INT_EN BIT(16) +#define AIROHA_PCS_PMA_XPON_INT_STA_3 0x47c +#define AIROHA_PCS_PMA_RX_SIGDET_INT BIT(16) +#define AIROHA_PCS_PMA_RX_EXTRAL_CTRL 0x48c +/* 4ref_ck step: + * - 0x1 4ref_ck + * - 0x2 8ref_ck + * - 0x3 12ref_ck + * ... + */ +#define AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME GENMASK(15, 8) +#define AIROHA_PCS_PMA_OS_RDY_LATCH BIT(1) +#define AIROHA_PCS_PMA_DISB_LEQ BIT(0) +#define AIROHA_PCS_PMA_RX_FREQDET 0x530 +#define AIROHA_PCS_PMA_FL_OUT GENMASK(31, 16) +#define AIROHA_PCS_PMA_FBCK_LOCK BIT(0) +#define AIROHA_PCS_PMA_XPON_TX_RATE_CTRL 0x580 +#define AIROHA_PCS_PMA_PON_TX_RATE_CTRL GENMASK(1, 0) +#define AIROHA_PCS_PMA_MD32_MEM_CLK_CTRL 0x60c +#define AIROHA_PCS_PMA_MD32PM_CK_SEL GENMASK(31, 0) +#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN 0x768 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL GENMASK(19, 16) +#define AIROHA_PCS_PMA_PXP_AEQ_SPEED 0x76c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_OSR_SEL GENMASK(17, 16) +#define AIROHA_PCS_PMA_PXP_TX_FIR_C0B 0x778 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 GENMASK(20, 16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B GENMASK(5, 0) +#define AIROHA_PCS_PMA_PXP_TX_TERM_SEL 0x77c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR GENMASK(19, 16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_TERM_SEL BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL GENMASK(2, 0) +#define AIROHA_PCS_PMA_PXP_TX_FIR_C1 0x780 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 GENMASK(20, 16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1 GENMASK(5, 0) +#define AIROHA_PCS_PMA_PXP_TX_RATE_CTRL 0x784 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE GENMASK(22, 16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL GENMASK(1, 0) +#define AIROHA_PCS_PMA_PXP_CDR_PR_FLL_COR 0x790 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_DAC_EYE BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE GENMASK(22, 16) +#define AIROHA_PCS_PMA_PXP_CDR_PR_IDAC 0x794 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW BIT(24) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC BIT(16) +#define AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC GENMASK(10, 0) +#define AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR GENMASK(10, 8) +#define AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW 0x798 +#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW GENMASK(30, 0) +#define AIROHA_PCS_PMA_PXP_RX_FE_VOS 0x79c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_SDM_PCW BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_FE_VOS GENMASK(5, 0) +#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_PCW 0x800 +#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW GENMASK(30, 0) +#define AIROHA_PCS_PMA_PXP_AEQ_BYPASS 0x80c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_AEQ_CKON BIT(16) +#define AIROHA_PCS_PMA_PXP_AEQ_RSTB 0x814 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL BIT(16) +#define AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA 0x818 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA BIT(0) +#define AIROHA_PCS_PMA_PXP_CDR_PD_PWDB 0x81c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB BIT(0) +#define AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN 0x820 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_C_EN BIT(0) +#define AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB 0x824 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB BIT(0) +#define AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN 0x828 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN BIT(0) +#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB 0x83c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON BIT(16) +#define AIROHA_PCS_PMA_PXP_RX_OSCAL_EN 0x840 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN BIT(0) +#define AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B 0x84c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B BIT(0) +#define AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN 0x854 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN BIT(0) +#define AIROHA_PCS_PMA_PXP_TXPLL_KBAND_LOAD_EN 0x858 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_KBAND_LOAD_EN BIT(0) +#define AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG 0x864 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW_CHG BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG BIT(0) +#define AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN 0x874 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL BIT(16) +#define AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL 0x88c +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL GENMASK(1, 0) +#define AIROHA_PCS_PMA_PXP_RX_FE_PWDB 0x894 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN BIT(24) +#define AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN BIT(16) +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB BIT(0) +#define AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN 0x898 +#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN BIT(8) +#define AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN BIT(0) +#define AIROHA_PCS_PMA_DIG_RESERVE_12 0x8b8 +#define AIROHA_PCS_PMA_RESERVE_12_FEOS_0 BIT(0) +#define AIROHA_PCS_PMA_DIG_RESERVE_24 0x8fc +#define AIROHA_PCS_PMA_FORCE_RX_GEARBOX BIT(12) +#define AIROHA_PCS_PMA_FORCE_SEL_RX_GEARBOX BIT(8) + +#define AIROHA_PCS_MAX_CALIBRATION_TRY 50 +#define AIROHA_PCS_MAX_NUM_RSTS 2 + +enum pon_eo_buf_vals { + EYE_EU, + EYE_EB, + DAC_D0, + DAC_D1, + DAC_E0, + DAC_E1, + DAC_EYE, + FEOS, + + EO_BUF_MAX, +}; + +enum xfi_port_type { + AIROHA_PCS_ETH, + AIROHA_PCS_PON, +}; + +struct airoha_pcs_priv { + struct udevice *dev; + const struct airoha_pcs_match_data *data; + phy_interface_t interface; + + struct regmap *scu; + + struct regmap *xfi_mac; + struct regmap *hsgmii_an; + struct regmap *hsgmii_pcs; + struct regmap *hsgmii_rate_adp; + struct regmap *multi_sgmii; + struct regmap *usxgmii_pcs; + + struct regmap *xfi_pma; + struct regmap *xfi_ana; + + struct reset_ctl *xfi_rst; + struct reset_ctl_bulk rsts; + + bool manual_rx_calib; +}; + +struct airoha_pcs_match_data { + enum xfi_port_type port_type; + + bool hibernation_workaround; + bool usxgmii_ber_time_fixup; + bool usxgmii_rx_gb_out_vld_tweak; + bool usxgmii_xfi_mode_sel; + + int (*bringup)(struct airoha_pcs_priv *priv, + phy_interface_t interface); + void (*link_up)(struct airoha_pcs_priv *priv); +}; + +void airoha_pcs_pre_config(struct udevice *dev, phy_interface_t interface); +int airoha_pcs_post_config(struct udevice *dev, phy_interface_t interface); +int airoha_pcs_config(struct udevice *dev, bool neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac); +void airoha_pcs_link_up(struct udevice *dev, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex); +void airoha_pcs_link_down(struct udevice *dev); + +#ifdef CONFIG_PCS_AIROHA_AN7581 +int an7581_pcs_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface); + +void an7581_pcs_phya_link_up(struct airoha_pcs_priv *priv); +#else +static inline int an7581_pcs_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + return -EOPNOTSUPP; +} + +static inline void an7581_pcs_phya_link_up(struct airoha_pcs_priv *priv) +{ +} +#endif diff --git a/drivers/net/airoha/pcs-an7581.c b/drivers/net/airoha/pcs-an7581.c new file mode 100644 index 00000000000..746ff55d72f --- /dev/null +++ b/drivers/net/airoha/pcs-an7581.c @@ -0,0 +1,1375 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 AIROHA Inc + * Author: Christian Marangi <[email protected]> + */ +#include <dm.h> +#include <dm/device_compat.h> +#include <regmap.h> + +#include "pcs-airoha.h" + +static void an7581_pcs_jcpll_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 kband_vref; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + kband_vref = 0x10; + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + kband_vref = 0xf; + break; + default: + return; + } + + /* Setup LDO */ + udelay(200); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H, + AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO); + + /* Setup RSTB */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, + AIROHA_PCS_ANA_JCPLL_RST_DLY, + AIROHA_PCS_ANA_JCPLL_RST_DLY_150_200); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, + AIROHA_PCS_ANA_JCPLL_PLL_RSTB); + + /* Enable PLL force selection and Force Disable */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN | + AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN); + + /* Setup SDM */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, + AIROHA_PCS_ANA_JCPLL_SDM_DI_LS | + AIROHA_PCS_ANA_JCPLL_SDM_DI_EN, + AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_23); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, + AIROHA_PCS_ANA_JCPLL_SDM_OUT | + AIROHA_PCS_ANA_JCPLL_SDM_ORD | + AIROHA_PCS_ANA_JCPLL_SDM_MODE | + AIROHA_PCS_ANA_JCPLL_SDM_IFM, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x0) | + AIROHA_PCS_ANA_JCPLL_SDM_ORD_3SDM | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SDM_MODE, 0x0)); + + regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN, + AIROHA_PCS_ANA_JCPLL_SDM_HREN); + + /* Setup SSC */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SSC_DELTA, + AIROHA_PCS_ANA_JCPLL_SSC_PERIOD | + AIROHA_PCS_ANA_JCPLL_SSC_DELTA, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_PERIOD, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_DELTA, 0x0)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SSC_TRI_EN, + AIROHA_PCS_ANA_JCPLL_SSC_DELTA1 | + AIROHA_PCS_ANA_JCPLL_SSC_TRI_EN, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_DELTA1, 0x0)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR, + AIROHA_PCS_ANA_JCPLL_SSC_PHASE_INI | + AIROHA_PCS_ANA_JCPLL_SSC_EN | + AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L | + AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, 0x0)); + + /* Setup LPF */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN, + AIROHA_PCS_ANA_JCPLL_CHP_IOFST | + AIROHA_PCS_ANA_JCPLL_CHP_IBIAS | + AIROHA_PCS_ANA_JCPLL_LPF_SHCK_EN, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_CHP_IOFST, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_CHP_IBIAS, 0x18)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BR, + AIROHA_PCS_ANA_JCPLL_LPF_BWR | + AIROHA_PCS_ANA_JCPLL_LPF_BP | + AIROHA_PCS_ANA_JCPLL_LPF_BC | + AIROHA_PCS_ANA_JCPLL_LPF_BR, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BWR, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BP, 0x10) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BC, 0x1f) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BR, BIT(3) | BIT(1))); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC, + AIROHA_PCS_ANA_JCPLL_LPF_BWC, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BWC, 0x0)); + + /* Setup VCO */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCODIV, + AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR | + AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN | + AIROHA_PCS_ANA_JCPLL_VCO_CFIX, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR, 0x4) | + AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_CFIX, 0x1)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR, + AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L | + AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H | + AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H, 0x3) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, 0x3)); + + /* Setup PCW */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_PCW, + AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW, + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW, 0x25800000)); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_VOS, + AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_SDM_PCW); + + /* Setup DIV */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_MMD_PREDIV_MODE, + AIROHA_PCS_ANA_JCPLL_POSTDIV_D5 | + AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, + AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_2); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCODIV, + AIROHA_PCS_ANA_JCPLL_VCODIV, + AIROHA_PCS_ANA_JCPLL_VCODIV_1); + + /* Setup KBand */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_KBAND_KFC, + AIROHA_PCS_ANA_JCPLL_KBAND_KS | + AIROHA_PCS_ANA_JCPLL_KBAND_KF | + AIROHA_PCS_ANA_JCPLL_KBAND_KFC, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KS, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KF, 0x3) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KFC, 0x0)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC, + AIROHA_PCS_ANA_JCPLL_KBAND_DIV | + AIROHA_PCS_ANA_JCPLL_KBAND_CODE | + AIROHA_PCS_ANA_JCPLL_KBAND_OPTION, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_DIV, 0x2) | + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_CODE, 0xe4)); + + /* Setup TCL */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H, + AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF, kband_vref)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN, + AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF | + AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN | + AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN, + FIELD_PREP(AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF, 0x5) | + AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_4 | + AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_TCL_CMP_EN, + AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW | + AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN, + AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_1 | + AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN); + + /* Enable PLL */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, + AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN); + + /* Enale PLL Output */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN | + AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN); +} + +static void an7581_pcs_txpll_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 lpf_chp_ibias, lpf_bp, lpf_bwr, lpf_bwc; + u32 vco_cfix; + u32 pcw; + u32 tcl_amp_vref; + bool sdm_hren; + bool vcodiv; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + lpf_chp_ibias = 0xf; + lpf_bp = BIT(1); + lpf_bwr = BIT(3) | BIT(1) | BIT(0); + lpf_bwc = BIT(4) | BIT(3); + vco_cfix = BIT(1) | BIT(0); + pcw = BIT(27); + tcl_amp_vref = BIT(3) | BIT(1) | BIT(0); + vcodiv = false; + sdm_hren = false; + break; + case PHY_INTERFACE_MODE_2500BASEX: + lpf_chp_ibias = 0xa; + lpf_bp = BIT(2) | BIT(0); + lpf_bwr = 0; + lpf_bwc = 0; + vco_cfix = 0; + pcw = BIT(27) | BIT(25); + tcl_amp_vref = BIT(3) | BIT(2) | BIT(0); + vcodiv = true; + sdm_hren = false; + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + lpf_chp_ibias = 0xf; + lpf_bp = BIT(1); + lpf_bwr = BIT(3) | BIT(1) | BIT(0); + lpf_bwc = BIT(4) | BIT(3); + vco_cfix = BIT(0); + pcw = BIT(27) | BIT(22); + tcl_amp_vref = BIT(3) | BIT(1) | BIT(0); + vcodiv = false; + sdm_hren = true; + break; + default: + return; + } + + /* Setup VCO LDO Output */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, + AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT | + AIROHA_PCS_ANA_TXPLL_LDO_OUT, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT, 0x1) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_OUT, 0x1)); + + /* Setup RSTB */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL, + AIROHA_PCS_ANA_TXPLL_PLL_RSTB | + AIROHA_PCS_ANA_TXPLL_RST_DLY | + AIROHA_PCS_ANA_TXPLL_REFIN_DIV | + AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL, + AIROHA_PCS_ANA_TXPLL_PLL_RSTB | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_RST_DLY, 0x4) | + AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1 | + AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL); + + /* Enable PLL force selection and Force Disable */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN | + AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN); + + /* Setup SDM */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN, + AIROHA_PCS_ANA_TXPLL_SDM_MODE | + AIROHA_PCS_ANA_TXPLL_SDM_IFM | + AIROHA_PCS_ANA_TXPLL_SDM_DI_LS | + AIROHA_PCS_ANA_TXPLL_SDM_DI_EN, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SDM_MODE, 0) | + AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, + AIROHA_PCS_ANA_TXPLL_SDM_HREN | + AIROHA_PCS_ANA_TXPLL_SDM_OUT | + AIROHA_PCS_ANA_TXPLL_SDM_ORD, + (sdm_hren ? AIROHA_PCS_ANA_TXPLL_SDM_HREN : 0) | + AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM); + + /* Setup SSC */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1, + AIROHA_PCS_ANA_TXPLL_SSC_DELTA | + AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, 0x0)); + + regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN, + AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN | + AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI | + AIROHA_PCS_ANA_TXPLL_SSC_EN); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, + AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, 0x0)); + + /* Setup LPF */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS, + AIROHA_PCS_ANA_TXPLL_LPF_BC | + AIROHA_PCS_ANA_TXPLL_LPF_BR | + AIROHA_PCS_ANA_TXPLL_CHP_IOFST | + AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BC, 0x1f) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BR, 0x5) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IOFST, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, lpf_chp_ibias)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, + AIROHA_PCS_ANA_TXPLL_LPF_BWC | + AIROHA_PCS_ANA_TXPLL_LPF_BWR | + AIROHA_PCS_ANA_TXPLL_LPF_BP, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWC, lpf_bwc) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWR, lpf_bwr) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BP, lpf_bp)); + + /* Setup VCO */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, + AIROHA_PCS_ANA_TXPLL_VCO_CFIX, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_CFIX, vco_cfix)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN, + AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L | + AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H | + AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR | + AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR | + AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H, 0x4) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR, 0x4) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR, 0x7) | + AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN); + + /* Setup PCW */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW, + AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW, pcw); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, + AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW); + + /* Setup KBand */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE, + AIROHA_PCS_ANA_TXPLL_KBAND_KF | + AIROHA_PCS_ANA_TXPLL_KBAND_KFC | + AIROHA_PCS_ANA_TXPLL_KBAND_DIV | + AIROHA_PCS_ANA_TXPLL_KBAND_CODE, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KF, 0x3) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KFC, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_DIV, 0x4) | + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_CODE, 0xe4)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, + AIROHA_PCS_ANA_TXPLL_KBAND_KS, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KS, 0x1)); + + regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, + AIROHA_PCS_ANA_TXPLL_KBAND_OPTION); + + /* Setup DIV */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, + AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE | + AIROHA_PCS_ANA_TXPLL_POSTDIV_EN, + AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, + AIROHA_PCS_ANA_TXPLL_VCODIV, + vcodiv ? AIROHA_PCS_ANA_TXPLL_VCODIV_2 : + AIROHA_PCS_ANA_TXPLL_VCODIV_1); + + /* Setup TCL */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, + AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, 0xf)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN, + AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF | + AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, + FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF, tcl_amp_vref) | + AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, + AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW | + AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN, + AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 | + AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, + AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN); + + /* Enable PLL */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, + AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN); + + /* Enale PLL Output */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN | + AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN); +} + +static void an7581_pcs_tx_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 tx_rate_ctrl; + u32 ckin_divisor; + u32 fir_cn1, fir_c0b, fir_c1; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + ckin_divisor = BIT(1); + tx_rate_ctrl = BIT(0); + fir_cn1 = 0; + fir_c0b = 12; + fir_c1 = 0; + break; + case PHY_INTERFACE_MODE_2500BASEX: + ckin_divisor = BIT(2); + tx_rate_ctrl = BIT(0); + fir_cn1 = 0; + fir_c0b = 11; + fir_c1 = 1; + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + ckin_divisor = BIT(2) | BIT(0); + tx_rate_ctrl = BIT(1); + fir_cn1 = 1; + fir_c0b = 1; + fir_c1 = 11; + break; + default: + return; + } + + /* Set TX rate ctrl */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_TX_RATE_CTRL, + AIROHA_PCS_PMA_PON_TX_RATE_CTRL, + FIELD_PREP(AIROHA_PCS_PMA_PON_TX_RATE_CTRL, + tx_rate_ctrl)); + + /* Setup TX Config */ + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_CKLDO_EN, + AIROHA_PCS_ANA_TX_DMEDGEGEN_EN | + AIROHA_PCS_ANA_TX_CKLDO_EN); + + udelay(1); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL | + AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL); + + /* FIXME: Ask Airoha TX term is OK to reset? */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_TERM_SEL, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | + AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR | + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_TERM_SEL | + AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR, + ckin_divisor) | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL, 0x0)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | + AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, + tx_rate_ctrl)); + + /* Setup TX FIR Load Parameters (Reference 660mV) */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C0B, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | + AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 | + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | + AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1, fir_cn1) | + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, fir_c0b)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C1, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 | + AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 | + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | + AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, + AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, fir_c1)); + + /* Reset TX Bar */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B, + AIROHA_PCS_PMA_TXCALIB_RST_B | AIROHA_PCS_PMA_TX_TOP_RST_B); +} + +static void an7581_pcs_rx_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 rx_rate_ctrl; + u32 osr; + u32 pr_cdr_beta_dac; + u32 cdr_pr_buf_in_sr; + bool cdr_pr_cap_en; + u32 sigdet_vth_sel; + u32 phyck_div, phyck_sel; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + osr = BIT(1) | BIT(0); /* 1.25G */ + pr_cdr_beta_dac = BIT(3); + rx_rate_ctrl = 0; + cdr_pr_cap_en = false; + cdr_pr_buf_in_sr = BIT(2) | BIT(1) | BIT(0); + sigdet_vth_sel = BIT(2) | BIT(1); + phyck_div = BIT(5) | BIT(3) | BIT(0); + phyck_sel = BIT(0); + break; + case PHY_INTERFACE_MODE_2500BASEX: + osr = BIT(0); /* 2.5G */ + pr_cdr_beta_dac = BIT(2) | BIT(1); + rx_rate_ctrl = 0; + cdr_pr_cap_en = true; + cdr_pr_buf_in_sr = BIT(2) | BIT(1); + sigdet_vth_sel = BIT(2) | BIT(1); + phyck_div = BIT(3) | BIT(1) | BIT(0); + phyck_sel = BIT(0); + break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + osr = 0; /* 10G */ + cdr_pr_cap_en = false; + pr_cdr_beta_dac = BIT(3); + rx_rate_ctrl = BIT(1); + cdr_pr_buf_in_sr = BIT(2) | BIT(1) | BIT(0); + sigdet_vth_sel = BIT(1); + phyck_div = BIT(6) | BIT(1); + phyck_sel = BIT(1); + break; + default: + return; + } + + /* Set RX rate ctrl */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_2, + AIROHA_PCS_PMA_CK_RATE, + AIROHA_PCS_PMA_CK_RATE_10); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_RX_RESERVED_1, + AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, + FIELD_PREP(AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, rx_rate_ctrl)); + + /* Setup RX Path */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_5, + AIROHA_PCS_PMA_FLL_IDAC_MIN | + AIROHA_PCS_PMA_FLL_IDAC_MAX, + FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MIN, 0x400) | + FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MAX, 0x3ff)); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_D1_BYPASS_AEQ, + AIROHA_PCS_ANA_RX_DAC_EYE_BYPASS_AEQ | + AIROHA_PCS_ANA_RX_DAC_E1_BYPASS_AEQ | + AIROHA_PCS_ANA_RX_DAC_E0_BYPASS_AEQ | + AIROHA_PCS_ANA_RX_DAC_D1_BYPASS_AEQ); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_PEAKING_CTRL_MSB, + AIROHA_PCS_ANA_RX_DAC_D0_BYPASS_AEQ); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB, + AIROHA_PCS_ANA_FE_VCM_GEN_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1, + AIROHA_PCS_PMA_LCPLL_MAN_PWDB); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_AEQ_CFORCE, + AIROHA_PCS_ANA_AEQ_OFORCE, + AIROHA_PCS_ANA_AEQ_OFORCE_CTLE); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW, + AIROHA_PCS_ANA_RX_OSCAL_FORCE, + AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH | + AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_4, + AIROHA_PCS_PMA_DISB_BLWC_OFFSET); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EXTRAL_CTRL, + AIROHA_PCS_PMA_DISB_LEQ); + + regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, + AIROHA_PCS_ANA_CDR_PD_EDGE_DIS | + AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_BYPASS, + AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON | + AIROHA_PCS_PMA_FORCE_DA_AEQ_CKON, + AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_RSTB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL | + AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, + AIROHA_PCS_ANA_RX_DAC_MON | + AIROHA_PCS_ANA_CDR_PR_XFICK_EN | + AIROHA_PCS_ANA_CDR_PR_MONDPI_EN | + AIROHA_PCS_ANA_CDR_PR_MONDPR_EN, + FIELD_PREP(AIROHA_PCS_ANA_RX_DAC_MON, 0x0) | + AIROHA_PCS_ANA_CDR_PR_XFICK_EN); + + /* Setup FE Gain and FE Peacking */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL | + AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, 0x0)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN, + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL | + AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, 0x0)); + + /* Setup FE VOS */ + if (interface != PHY_INTERFACE_MODE_USXGMII && + interface != PHY_INTERFACE_MODE_10GBASER) + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_VOS, + AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS | + AIROHA_PCS_PMA_FORCE_DA_FE_VOS, + AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_FE_VOS, 0x0)); + + /* Setup FLL PR FMeter (no bypass mode)*/ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_0, + AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT, + FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT, 0x1)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_1, + AIROHA_PCS_PMA_PLL_LOCK_TARGET_END | + AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG, + FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_TARGET_END, 0xffff) | + FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG, 0x0)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_3, + AIROHA_PCS_PMA_PLL_LOCK_LOCKTH, + FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_LOCKTH, 0x1)); + + /* FIXME: Warn and Ask Airoha about typo in air_eth_xsgmii.c line 1391 */ + /* AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL is set 0x0 in SDK but seems a typo */ + /* Setup REV */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0, + AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL | + AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL | + AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, + FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL, BIT(2)) | + FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL, BIT(2)) | + FIELD_PREP(AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, 0x0)); + + /* Setup Rdy Timeout */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5, + AIROHA_PCS_PMA_RX_RDY | + AIROHA_PCS_PMA_RX_BLWC_RDY_EN, + FIELD_PREP(AIROHA_PCS_PMA_RX_RDY, 0xa) | + FIELD_PREP(AIROHA_PCS_PMA_RX_BLWC_RDY_EN, 0x5)); + + /* Setup CaBoundry Init */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0, + AIROHA_PCS_PMA_RX_OS_START | + AIROHA_PCS_PMA_OSC_SPEED_OPT, + FIELD_PREP(AIROHA_PCS_PMA_RX_OS_START, 0x1) | + AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6, + AIROHA_PCS_PMA_RX_OS_END, + FIELD_PREP(AIROHA_PCS_PMA_RX_OS_END, 0x2)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1, + AIROHA_PCS_PMA_RX_PICAL_END | + AIROHA_PCS_PMA_RX_PICAL_START, + FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_END, 0x32) | + FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_START, 0x2)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4, + AIROHA_PCS_PMA_RX_SDCAL_END | + AIROHA_PCS_PMA_RX_SDCAL_START, + FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_END, 0x32) | + FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_START, 0x2)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2, + AIROHA_PCS_PMA_RX_PDOS_END | + AIROHA_PCS_PMA_RX_PDOS_START, + FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_END, 0x32) | + FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_START, 0x2)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3, + AIROHA_PCS_PMA_RX_FEOS_END | + AIROHA_PCS_PMA_RX_FEOS_START, + FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_END, 0x32) | + FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_START, 0x2)); + + /* Setup By Serdes*/ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_SPEED, + AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | + AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, + AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | + FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, osr)); + + /* Setup RX OSR */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, + AIROHA_PCS_ANA_CDR_PD_EDGE_DIS, + osr ? AIROHA_PCS_ANA_CDR_PD_EDGE_DIS : 0); + + /* Setup CDR LPF Ratio */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO, + AIROHA_PCS_ANA_CDR_LPF_TOP_LIM | + AIROHA_PCS_ANA_CDR_LPF_RATIO, + FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_TOP_LIM, 0x20000) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO, osr)); + + /* Setup CDR PR */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC, + AIROHA_PCS_ANA_CDR_PR_KBAND_DIV | + AIROHA_PCS_ANA_CDR_PR_BETA_SEL | + AIROHA_PCS_ANA_CDR_PR_VCOADC_OS | + AIROHA_PCS_ANA_CDR_PR_BETA_DAC, + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_KBAND_DIV, 0x4) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_SEL, 0x1) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VCOADC_OS, 0x8) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_DAC, pr_cdr_beta_dac)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL, + AIROHA_PCS_ANA_CDR_PR_FBKSEL | + AIROHA_PCS_ANA_CDR_PR_DAC_BAND | + AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL | + AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_FBKSEL, 0x0) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_DAC_BAND, pr_cdr_beta_dac) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL, 0x6) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, 0x6)); + + /* Setup Eye Mon */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_2, + AIROHA_PCS_PMA_EQ_DEBUG_SEL | + AIROHA_PCS_PMA_FOM_NUM_ORDER | + AIROHA_PCS_PMA_A_SEL, + FIELD_PREP(AIROHA_PCS_PMA_EQ_DEBUG_SEL, 0x0) | + FIELD_PREP(AIROHA_PCS_PMA_FOM_NUM_ORDER, 0x1) | + FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x3)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2, + AIROHA_PCS_PMA_DATA_SHIFT | + AIROHA_PCS_PMA_EYECNT_FAST, + AIROHA_PCS_PMA_EYECNT_FAST); + + /* Calibration Start */ + + /* Enable SYS */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_SYS_EN_SEL_0, + AIROHA_PCS_PMA_RX_SYS_EN_SEL, + FIELD_PREP(AIROHA_PCS_PMA_RX_SYS_EN_SEL, 0x1)); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0, + AIROHA_PCS_PMA_SW_LCPLL_EN); + + udelay(500); + + /* Setup FLL PR FMeter (bypass mode)*/ + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, + AIROHA_PCS_PMA_DISB_FBCK_LOCK); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, + AIROHA_PCS_PMA_FORCE_FBCK_LOCK); + + /* Enable CMLEQ */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN, + AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | + AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | + AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN | + AIROHA_PCS_ANA_RX_FE_EQ_HZEN, + AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | + AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | + AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN); + + /* Setup CDR PR */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, + AIROHA_PCS_ANA_CDR_PR_CAP_EN | + AIROHA_PCS_ANA_CDR_BUF_IN_SR, + (cdr_pr_cap_en ? AIROHA_PCS_ANA_CDR_PR_CAP_EN : 0) | + FIELD_PREP(AIROHA_PCS_ANA_CDR_BUF_IN_SR, cdr_pr_buf_in_sr)); + + /* Setup CDR xxx Pwdb, set force and disable */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB | + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB | + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN | + AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN | + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB | + AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB | + AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB | + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B | + AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B, + AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, + AIROHA_PCS_PMA_XPON_CDR_PD_PWDB | + AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | + AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | + AIROHA_PCS_PMA_XPON_RX_FE_PWDB); + + /* FIXME: Ask Airoha WHY it's cleared? */ + /* regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, + * AIROHA_PCS_ANA_RX_FE_50OHMS_SEL); + */ + + /* Setup SigDet */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, + AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL | + AIROHA_PCS_ANA_RX_SIGDET_PEAK, + FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL, sigdet_vth_sel) | + FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_PEAK, BIT(1))); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE, + AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, + FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, BIT(1) | BIT(0))); + + /* Disable SigDet Pwdb */ + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, + AIROHA_PCS_PMA_RX_SIDGET_PWDB); + + /* Setup PHYCK */ + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV, + AIROHA_PCS_ANA_RX_TDC_CK_SEL | + AIROHA_PCS_ANA_RX_PHYCK_RSTB | + AIROHA_PCS_ANA_RX_PHYCK_SEL | + AIROHA_PCS_ANA_RX_PHYCK_DIV, + AIROHA_PCS_ANA_RX_PHYCK_RSTB | + FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_SEL, phyck_sel) | + FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_DIV, phyck_div)); + + regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL, + AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE | + AIROHA_PCS_ANA_RX_PHY_CK_SEL, + AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE); + + udelay(100); + + /* Enable CDR xxx Pwdb */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, + AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, + AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, + AIROHA_PCS_PMA_XPON_CDR_PD_PWDB | + AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | + AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | + AIROHA_PCS_PMA_XPON_RX_FE_PWDB); + + /* Enable SigDet Pwdb */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, + AIROHA_PCS_PMA_RX_SIDGET_PWDB); +} + +static unsigned int an7581_pcs_apply_cdr_pr_idac(struct airoha_pcs_priv *priv, + u32 cdr_pr_idac) +{ + u32 val; + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, + AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC, + FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC, + cdr_pr_idac)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, + AIROHA_PCS_PMA_FREQLOCK_DET_EN, + AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_0); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, + AIROHA_PCS_PMA_FREQLOCK_DET_EN, + AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL); + + udelay(5000); + + regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_FREQDET, &val); + + return FIELD_GET(AIROHA_PCS_PMA_FL_OUT, val); +} + +static u32 an7581_pcs_rx_prcal_idac_major(struct airoha_pcs_priv *priv, + u32 target_fl_out) +{ + unsigned int fl_out_diff = UINT_MAX; + unsigned int prcal_search; + u32 cdr_pr_idac = 0; + + for (prcal_search = 0; prcal_search < 8 ; prcal_search++) { + unsigned int fl_out_diff_new; + unsigned int fl_out; + u32 cdr_pr_idac_tmp; + + /* try to find the upper value by setting the last 3 bit */ + cdr_pr_idac_tmp = FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, + prcal_search); + fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); + + /* Use absolute values to find the closest one to target */ + fl_out_diff_new = abs(fl_out - target_fl_out); + dev_dbg(priv->dev, "Tested CDR Pr Idac: %x Fl Out: %x Diff: %u\n", + cdr_pr_idac_tmp, fl_out, fl_out_diff_new); + if (fl_out_diff_new < fl_out_diff) { + cdr_pr_idac = cdr_pr_idac_tmp; + fl_out_diff = fl_out_diff_new; + } + } + + return cdr_pr_idac; +} + +static u32 an7581_pcs_rx_prcal_idac_minor(struct airoha_pcs_priv *priv, u32 target_fl_out, + u32 cdr_pr_idac_major) +{ + unsigned int remaining_prcal_search_bits = 0; + u32 cdr_pr_idac = cdr_pr_idac_major; + unsigned int fl_out, fl_out_diff; + int best_prcal_search_bit = -1; + int prcal_search_bit; + + fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac); + fl_out_diff = abs(fl_out - target_fl_out); + + /* Deadline search part. + * We start from top bits to bottom as we progressively decrease the + * signal. + */ + for (prcal_search_bit = 7; prcal_search_bit >= 0; prcal_search_bit--) { + unsigned int fl_out_diff_new; + u32 cdr_pr_idac_tmp; + + cdr_pr_idac_tmp = cdr_pr_idac | BIT(prcal_search_bit); + fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); + + /* Use absolute values to find the closest one to target */ + fl_out_diff_new = abs(fl_out - target_fl_out); + dev_dbg(priv->dev, "Tested CDR Pr Idac: %x Fl Out: %x Diff: %u\n", + cdr_pr_idac_tmp, fl_out, fl_out_diff_new); + if (fl_out_diff_new < fl_out_diff) { + best_prcal_search_bit = prcal_search_bit; + fl_out_diff = fl_out_diff_new; + } + } + + /* Set the idac with the best value we found and + * reset the search bit to start from bottom to top. + */ + if (best_prcal_search_bit >= 0) { + cdr_pr_idac |= BIT(best_prcal_search_bit); + remaining_prcal_search_bits = best_prcal_search_bit; + prcal_search_bit = 0; + } + + /* Fine tune part. + * Test remaining bits to find an even closer signal level to target + * by increasing the signal. + */ + while (remaining_prcal_search_bits) { + unsigned int fl_out_diff_new; + u32 cdr_pr_idac_tmp; + + cdr_pr_idac_tmp = cdr_pr_idac | BIT(prcal_search_bit); + fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); + + /* Use absolute values to find the closest one to target */ + fl_out_diff_new = abs(fl_out - target_fl_out); + /* Assume we found the deadline when the new absolue signal difference + * from target is greater than the previous and the difference is at + * least 10% greater between the old and new value. + * This is to account for signal detection level tollerance making + * sure we are actually over a deadline (AKA we are getting farther + * from target) + */ + dev_dbg(priv->dev, "Tested CDR Pr Idac: %x Fl Out: %x Diff: %u\n", + cdr_pr_idac_tmp, fl_out, fl_out_diff_new); + if (fl_out_diff_new > fl_out_diff && + (abs(fl_out_diff_new - fl_out_diff) * 100) / fl_out_diff > 10) { + /* Exit early if we are already at the deadline */ + if (prcal_search_bit == 0) + break; + + /* We found the deadline, set the value to the previous + * bit, and reset the loop to fine tune with the + * remaining values. + */ + cdr_pr_idac |= BIT(prcal_search_bit - 1); + remaining_prcal_search_bits = prcal_search_bit - 1; + prcal_search_bit = 0; + } else { + /* Update the signal level diff and try the next bit */ + fl_out_diff = fl_out_diff_new; + + /* If we didn't found the deadline, set the last bit + * and reset the loop to fine tune with the remainig + * values. + */ + if (prcal_search_bit == remaining_prcal_search_bits - 1) { + cdr_pr_idac |= BIT(prcal_search_bit); + remaining_prcal_search_bits = prcal_search_bit; + prcal_search_bit = 0; + } else { + prcal_search_bit++; + } + } + } + + return cdr_pr_idac; +} + +static void an7581_pcs_rx_prcal(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + u32 cdr_pr_idac_major, cdr_pr_idac; + unsigned int fl_out, fl_out_diff; + + u32 target_fl_out; + u32 cyclecnt; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: /* DS_1.25G / US_1.25G */ + case PHY_INTERFACE_MODE_1000BASEX: + target_fl_out = 0xa3d6; + cyclecnt = 32767; + break; + case PHY_INTERFACE_MODE_2500BASEX: /* DS_9.95328G / US_9.95328G */ + target_fl_out = 0xa000; + cyclecnt = 20000; + break; + case PHY_INTERFACE_MODE_USXGMII: /* DS_10.3125G / US_1.25G */ + case PHY_INTERFACE_MODE_10GBASER: + target_fl_out = 0x9edf; + cyclecnt = 32767; + break; + default: + return; + } + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, + AIROHA_PCS_PMA_SW_REF_RST_N); + + udelay(100); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_2, + AIROHA_PCS_PMA_LOCK_TARGET_END | + AIROHA_PCS_PMA_LOCK_TARGET_BEG, + FIELD_PREP(AIROHA_PCS_PMA_LOCK_TARGET_END, target_fl_out + 100) | + FIELD_PREP(AIROHA_PCS_PMA_LOCK_TARGET_BEG, target_fl_out - 100)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_1, + AIROHA_PCS_PMA_UNLOCK_CYCLECNT | + AIROHA_PCS_PMA_LOCK_CYCLECNT, + FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_CYCLECNT, cyclecnt) | + FIELD_PREP(AIROHA_PCS_PMA_LOCK_CYCLECNT, cyclecnt)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, + AIROHA_PCS_PMA_LOCK_UNLOCKTH | + AIROHA_PCS_PMA_LOCK_LOCKTH, + FIELD_PREP(AIROHA_PCS_PMA_LOCK_UNLOCKTH, 3) | + FIELD_PREP(AIROHA_PCS_PMA_LOCK_LOCKTH, 3)); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_3, + AIROHA_PCS_PMA_UNLOCK_TARGET_END | + AIROHA_PCS_PMA_UNLOCK_TARGET_BEG, + FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_TARGET_END, target_fl_out + 100) | + FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_TARGET_BEG, target_fl_out - 100)); + + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE, + AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN | + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_C_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN | + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN | + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); + + /* Calibration logic: + * First check the major value by looping with every + * value in the last 3 bit of CDR_PR_IDAC. + * Get the signal level and save the value that is closer to + * the target. + * + * Then check each remaining 7 bits in search of the deadline + * where the signal gets farther than signal target. + * + * Finally fine tune for the remaining bits to find the one that + * produce the closest signal level. + */ + cdr_pr_idac_major = an7581_pcs_rx_prcal_idac_major(priv, target_fl_out); + + cdr_pr_idac = an7581_pcs_rx_prcal_idac_minor(priv, target_fl_out, cdr_pr_idac_major); + + fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac); + fl_out_diff = abs(fl_out - target_fl_out); + if (fl_out_diff > 100) { + u32 pr_idac_major = FIELD_GET(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, + cdr_pr_idac_major); + unsigned int fl_out_tmp, fl_out_diff_tmp; + u32 cdr_pr_idac_tmp; + + if (pr_idac_major > 0) { + cdr_pr_idac_tmp = FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, + pr_idac_major - 1); + + dev_dbg(priv->dev, "Fl Out is %d far from target %d with Pr Idac %x. Trying with Pr Idac %x.\n", + fl_out_diff, target_fl_out, cdr_pr_idac_major, cdr_pr_idac_tmp); + + cdr_pr_idac_tmp = an7581_pcs_rx_prcal_idac_minor(priv, target_fl_out, + cdr_pr_idac_tmp); + + fl_out_tmp = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); + fl_out_diff_tmp = abs(fl_out_tmp - target_fl_out); + if (fl_out_diff_tmp < fl_out_diff) { + fl_out = fl_out_tmp; + fl_out_diff = fl_out_diff_tmp; + cdr_pr_idac = cdr_pr_idac_tmp; + } + } + } + dev_dbg(priv->dev, "Selected CDR Pr Idac: %x Fl Out: %x\n", cdr_pr_idac, fl_out); + if (fl_out_diff > 100) + dev_dbg(priv->dev, "Fl Out is %d far from target %d on intermediate calibration.\n", + fl_out_diff, target_fl_out); + + + /* Setup Load Band */ + regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE, + AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF); + + /* Disable force of LPF C previously enabled */ + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_B, + AIROHA_PCS_PMA_LOAD_EN); + + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_1, + AIROHA_PCS_PMA_LPATH_IDAC, + FIELD_PREP(AIROHA_PCS_PMA_LPATH_IDAC, cdr_pr_idac)); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB); + + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, + AIROHA_PCS_PMA_SW_REF_RST_N); + + udelay(100); +} + +/* This is used to both calibrate and lock to signal (after a previous + * calibration) after a global reset. + */ +static void an7581_pcs_cdr_reset(struct airoha_pcs_priv *priv, + phy_interface_t interface, bool calibrate) +{ + /* Setup LPF L2D force and disable */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | + AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); + + /* Calibrate IDAC and setup Load Band */ + if (calibrate) + an7581_pcs_rx_prcal(priv, interface); + + /* Setup LPF RSTB force and disable */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | + AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); + + udelay(700); + + /* Force Enable LPF RSTB */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, + AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); + + udelay(100); + + /* Force Enable LPF L2D */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, + AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA); + + /* Disable LPF RSTB force bit */ + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); + + /* Disable LPF L2D force bit */ + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, + AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); +} + +static int an7581_pcs_phya_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + int calibration_try = 0; + u32 val; + + an7581_pcs_tx_bringup(priv, interface); + an7581_pcs_rx_bringup(priv, interface); + + udelay(100); + +retry_calibration: + an7581_pcs_cdr_reset(priv, interface, priv->manual_rx_calib); + + /* Global reset clear */ + regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, + AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | + AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N | + AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N | + AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | + AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N | + AIROHA_PCS_PMA_SW_TX_FIFO_RST_N | + AIROHA_PCS_PMA_SW_REF_RST_N | + AIROHA_PCS_PMA_SW_ALLPCS_RST_N | + AIROHA_PCS_PMA_SW_PMA_RST_N | + AIROHA_PCS_PMA_SW_TX_RST_N | + AIROHA_PCS_PMA_SW_RX_RST_N | + AIROHA_PCS_PMA_SW_RX_FIFO_RST_N, + AIROHA_PCS_PMA_SW_REF_RST_N); + + udelay(100); + + /* Global reset */ + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, + AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | + AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N | + AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N | + AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | + AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N | + AIROHA_PCS_PMA_SW_TX_FIFO_RST_N | + AIROHA_PCS_PMA_SW_REF_RST_N | + AIROHA_PCS_PMA_SW_ALLPCS_RST_N | + AIROHA_PCS_PMA_SW_PMA_RST_N | + AIROHA_PCS_PMA_SW_TX_RST_N | + AIROHA_PCS_PMA_SW_RX_RST_N | + AIROHA_PCS_PMA_SW_RX_FIFO_RST_N); + + udelay(5000); + + an7581_pcs_cdr_reset(priv, interface, false); + + /* Manual RX calibration is required only for SoC before E2 + * revision. E2+ SoC autocalibrate RX and only CDR reset is needed. + */ + if (!priv->manual_rx_calib) + return 0; + + /* It was discovered that after a global reset and auto mode gets + * actually enabled, the fl_out from calibration might change and + * might deviates a lot from the expected value it was calibrated for. + * To correctly work, the PCS FreqDet module needs to Lock to the fl_out + * (frequency level output) or no signal can correctly be transmitted. + * This is detected by checking the FreqDet module Lock bit. + * + * If it's detected that the FreqDet module is not locked, retry + * calibration. From observation on real hardware with a 10g SFP module, + * it required a maximum of an additional calibration to actually make + * the FreqDet module to lock. Try 10 times before failing to handle + * really strange case. + */ + regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_FREQDET, &val); + if (!(val & AIROHA_PCS_PMA_FBCK_LOCK)) { + if (calibration_try > AIROHA_PCS_MAX_CALIBRATION_TRY) { + dev_err(priv->dev, "No FBCK Lock from FreqDet module after %d calibration try. PCS won't work.\n", + AIROHA_PCS_MAX_CALIBRATION_TRY); + return -EIO; + } + + calibration_try++; + + dev_dbg(priv->dev, "No FBCK Lock from FreqDet module, retry calibration.\n"); + goto retry_calibration; + } + + return 0; +} + +static void an7581_pcs_pll_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + an7581_pcs_jcpll_bringup(priv, interface); + + udelay(200); + + an7581_pcs_txpll_bringup(priv, interface); + + udelay(200); +} + +int an7581_pcs_bringup(struct airoha_pcs_priv *priv, + phy_interface_t interface) +{ + /* Enable Analog Common Lane */ + regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CMN_EN, + AIROHA_PCS_ANA_CMN_EN); + + /* Setup PLL */ + an7581_pcs_pll_bringup(priv, interface); + + /* Setup PHYA */ + return an7581_pcs_phya_bringup(priv, interface); +} + +void an7581_pcs_phya_link_up(struct airoha_pcs_priv *priv) +{ + /* Reset TXPCS on link up */ + regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, + AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); + + udelay(100); + + regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, + AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); +} diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c index 3a0ac7ce368..f60405392b6 100644 --- a/drivers/net/airoha_eth.c +++ b/drivers/net/airoha_eth.c @@ -9,9 +9,12 @@ */ #include <dm.h> +#include <dm/device-internal.h> #include <dm/devres.h> #include <dm/lists.h> +#include <eth_phy.h> #include <mapmem.h> +#include <miiphy.h> #include <net.h> #include <regmap.h> #include <reset.h> @@ -19,12 +22,15 @@ #include <linux/bitfield.h> #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/ethtool.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/time.h> #include <asm/arch/scu-regmap.h> -#define AIROHA_MAX_NUM_GDM_PORTS 1 +#include "airoha/pcs-airoha.h" + +#define AIROHA_MAX_NUM_GDM_PORTS 4 #define AIROHA_MAX_NUM_QDMA 1 #define AIROHA_MAX_NUM_RSTS 3 #define AIROHA_MAX_NUM_XSI_RSTS 4 @@ -38,6 +44,8 @@ #define TX_DSCP_NUM 16 #define RX_DSCP_NUM PKTBUFSRX +#define AIROHA_GDM_PORT_STRING_LEN sizeof("airoha-gdmX") + /* SCU */ #define SCU_SHARE_FEMEM_SEL 0x958 @@ -246,6 +254,21 @@ #define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) #define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) +enum { + FE_PSE_PORT_CDM1, + FE_PSE_PORT_GDM1, + FE_PSE_PORT_GDM2, + FE_PSE_PORT_GDM3, + FE_PSE_PORT_PPE1, + FE_PSE_PORT_CDM2, + FE_PSE_PORT_CDM3, + FE_PSE_PORT_CDM4, + FE_PSE_PORT_PPE2, + FE_PSE_PORT_GDM4, + FE_PSE_PORT_CDM5, + FE_PSE_PORT_DROP = 0xf, +}; + struct airoha_qdma_desc { __le32 rsv; __le32 ctrl; @@ -301,20 +324,30 @@ struct airoha_qdma { struct airoha_gdm_port { struct airoha_qdma *qdma; int id; + + struct udevice *pcs_dev; + phy_interface_t mode; + bool neg_mode; + + struct phy_device *phydev; }; struct airoha_eth { void __iomem *fe_regs; void __iomem *switch_regs; + struct udevice *switch_mdio_dev; struct reset_ctl_bulk rsts; struct reset_ctl_bulk xsi_rsts; + struct airoha_eth_soc_data *soc; + struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA]; - struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS]; + char gdm_port_str[AIROHA_MAX_NUM_GDM_PORTS + 1][AIROHA_GDM_PORT_STRING_LEN]; }; struct airoha_eth_soc_data { + u32 version; int num_xsi_rsts; const char * const *xsi_rsts_names; const char *switch_compatible; @@ -397,22 +430,33 @@ static inline void dma_unmap_unaligned(dma_addr_t addr, size_t len, dma_unmap_single(start, end - start, dir); } -static void airoha_fe_maccr_init(struct airoha_eth *eth) +static int airoha_get_fe_port(struct airoha_gdm_port *port) { - int p; - - for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) { - /* - * Disable any kind of CRC drop or offload. - * Enable padding of short TX packets to 60 bytes. - */ - airoha_fe_wr(eth, REG_GDM_FWD_CFG(p), GDM_PAD_EN); + struct airoha_qdma *qdma = port->qdma; + struct airoha_eth *eth = qdma->eth; + + switch (eth->soc->version) { + case 0x7523: + /* FIXME: GDM1 is the only supported port */ + return FE_PSE_PORT_GDM1; + case 0x7581: + default: + return port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; } } -static int airoha_fe_init(struct airoha_eth *eth) +static void airoha_fe_maccr_init(struct airoha_gdm_port *port) +{ + /* + * Disable any kind of CRC drop or offload. + * Enable padding of short TX packets to 60 bytes. + */ + airoha_fe_wr(port->qdma->eth, REG_GDM_FWD_CFG(port->id), GDM_PAD_EN); +} + +static int airoha_fe_init(struct airoha_gdm_port *port) { - airoha_fe_maccr_init(eth); + airoha_fe_maccr_init(port); return 0; } @@ -662,6 +706,36 @@ static int airoha_qdma_init(struct udevice *dev, return airoha_qdma_hw_init(qdma); } +#if defined(CONFIG_PCS_AIROHA) +static int airoha_pcs_init(struct udevice *dev) +{ + struct airoha_gdm_port *port = dev_get_priv(dev); + struct udevice *pcs_dev; + const char *managed; + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, "pcs", + &pcs_dev); + if (ret || !pcs_dev) + return ret; + + port->pcs_dev = pcs_dev; + port->mode = dev_read_phy_mode(dev); + managed = dev_read_string(dev, "managed"); + port->neg_mode = !strncmp(managed, "in-band-status", + sizeof("in-band-status")); + + airoha_pcs_pre_config(pcs_dev, port->mode); + + ret = airoha_pcs_post_config(pcs_dev, port->mode); + if (ret) + return ret; + + return airoha_pcs_config(pcs_dev, port->neg_mode, + port->mode, NULL, true); +} +#endif + static int airoha_hw_init(struct udevice *dev, struct airoha_eth *eth) { @@ -682,12 +756,12 @@ static int airoha_hw_init(struct udevice *dev, if (ret) return ret; - mdelay(20); - - ret = airoha_fe_init(eth); + ret = reset_deassert_bulk(ð->xsi_rsts); if (ret) return ret; + mdelay(20); + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { ret = airoha_qdma_init(dev, eth, ð->qdma[i]); if (ret) @@ -739,11 +813,45 @@ static int airoha_switch_init(struct udevice *dev, struct airoha_eth *eth) return 0; } +static int airoha_alloc_gdm_port(struct udevice *dev, ofnode node) +{ + struct airoha_eth *eth = dev_get_priv(dev); + struct udevice *gdm_dev; + struct driver *gdm_drv; + char *str; + int ret; + u32 id; + + gdm_drv = lists_driver_lookup_name("airoha-eth-port"); + if (!gdm_drv) + return -ENOENT; + + ret = ofnode_read_u32(node, "reg", &id); + if (ret) + return ret; + + if (id > AIROHA_MAX_NUM_GDM_PORTS) + return -EINVAL; + +#if !defined(CONFIG_PCS_AIROHA) + if (id != 1) + return -ENOTSUPP; +#endif + + str = eth->gdm_port_str[id]; + snprintf(str, AIROHA_GDM_PORT_STRING_LEN, + "airoha-gdm%d", id); + + return device_bind_with_driver_data(dev, gdm_drv, str, + (ulong)eth, node, &gdm_dev); +} + static int airoha_eth_probe(struct udevice *dev) { struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev); struct airoha_eth *eth = dev_get_priv(dev); struct regmap *scu_regmap; + ofnode node; int i, ret; scu_regmap = airoha_get_scu_regmap(); @@ -756,6 +864,8 @@ static int airoha_eth_probe(struct udevice *dev) */ regmap_write(scu_regmap, SCU_SHARE_FEMEM_SEL, 0x0); + eth->soc = data; + eth->fe_regs = dev_remap_addr_name(dev, "fe"); if (!eth->fe_regs) return -ENOMEM; @@ -795,13 +905,79 @@ static int airoha_eth_probe(struct udevice *dev) if (ret) return ret; - return airoha_switch_init(dev, eth); + ret = airoha_switch_init(dev, eth); + if (ret) + return ret; + + ofnode_for_each_subnode(node, dev_ofnode(dev)) { + if (!ofnode_device_is_compatible(node, "airoha,eth-mac")) + continue; + + if (!ofnode_is_enabled(node)) + continue; + + ret = airoha_alloc_gdm_port(dev, node); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static int airoha_eth_port_of_to_plat(struct udevice *dev) +{ + struct airoha_gdm_port *port = dev_get_priv(dev); + + return dev_read_u32(dev, "reg", &port->id); +} + +static int airoha_eth_port_probe(struct udevice *dev) +{ + struct airoha_eth *eth = (void *)dev_get_driver_data(dev); + struct airoha_gdm_port *port = dev_get_priv(dev); + struct mdio_perdev_priv *pdata; + struct mii_dev *mdio_bus; + int ret; + + port->qdma = ð->qdma[0]; + + ret = airoha_fe_init(port); + if (ret) + return ret; + + mdio_bus = NULL; + if (port->id > 1) { +#if defined(CONFIG_PCS_AIROHA) + ret = airoha_pcs_init(dev); + if (ret) + return ret; + + port->phydev = dm_eth_phy_connect(dev); + if (port->phydev) + mdio_bus = port->phydev->bus; +#else + return -EINVAL; +#endif + } else { + if (eth->switch_mdio_dev && + !device_probe(eth->switch_mdio_dev)) { + pdata = dev_get_uclass_priv(eth->switch_mdio_dev); + mdio_bus = pdata->mii_bus; + } + } + +#ifdef CONFIG_DM_ETH_PHY + if (!IS_ERR_OR_NULL(mdio_bus)) + eth_phy_set_mdio_bus(dev, mdio_bus); +#endif + + return 0; } static int airoha_eth_init(struct udevice *dev) { - struct airoha_eth *eth = dev_get_priv(dev); - struct airoha_qdma *qdma = ð->qdma[0]; + struct airoha_gdm_port *port = dev_get_priv(dev); + struct airoha_qdma *qdma = port->qdma; struct airoha_queue *q; int qid; @@ -814,13 +990,65 @@ static int airoha_eth_init(struct udevice *dev) GLOBAL_CFG_TX_DMA_EN_MASK | GLOBAL_CFG_RX_DMA_EN_MASK); +#if defined(CONFIG_PCS_AIROHA) + if (port->id > 1) { + struct phy_device *phydev = port->phydev; + int speed, duplex; + int ret; + + if (phydev) { + ret = phy_config(phydev); + if (ret) + return ret; + + ret = phy_startup(phydev); + if (ret) + return ret; + + speed = phydev->speed; + duplex = phydev->duplex; + } else { + duplex = DUPLEX_FULL; + + /* Hardcode speed for linkup */ + switch (port->mode) { + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + speed = SPEED_10000; + break; + case PHY_INTERFACE_MODE_2500BASEX: + speed = SPEED_2500; + break; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + speed = SPEED_1000; + break; + default: + return -EINVAL; + } + } + + airoha_pcs_link_up(port->pcs_dev, port->neg_mode, port->mode, + speed, duplex); + } +#endif + return 0; } static void airoha_eth_stop(struct udevice *dev) { - struct airoha_eth *eth = dev_get_priv(dev); - struct airoha_qdma *qdma = ð->qdma[0]; + struct airoha_gdm_port *port = dev_get_priv(dev); + struct airoha_qdma *qdma = port->qdma; + +#if defined(CONFIG_PCS_AIROHA) + if (port->id > 1) { + if (port->phydev) + phy_shutdown(port->phydev); + + airoha_pcs_link_down(port->pcs_dev); + } +#endif airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK | @@ -829,8 +1057,8 @@ static void airoha_eth_stop(struct udevice *dev) static int airoha_eth_send(struct udevice *dev, void *packet, int length) { - struct airoha_eth *eth = dev_get_priv(dev); - struct airoha_qdma *qdma = ð->qdma[0]; + struct airoha_gdm_port *port = dev_get_priv(dev); + struct airoha_qdma *qdma = port->qdma; struct airoha_qdma_desc *desc; struct airoha_queue *q; dma_addr_t dma_addr; @@ -852,7 +1080,7 @@ static int airoha_eth_send(struct udevice *dev, void *packet, int length) desc = &q->desc[q->head]; index = (q->head + 1) % q->ndesc; - fport = 1; + fport = airoha_get_fe_port(port); msg0 = 0; msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | @@ -894,8 +1122,8 @@ static int airoha_eth_send(struct udevice *dev, void *packet, int length) static int airoha_eth_recv(struct udevice *dev, int flags, uchar **packetp) { - struct airoha_eth *eth = dev_get_priv(dev); - struct airoha_qdma *qdma = ð->qdma[0]; + struct airoha_gdm_port *port = dev_get_priv(dev); + struct airoha_qdma *qdma = port->qdma; struct airoha_qdma_desc *desc; struct airoha_queue *q; u16 length; @@ -922,8 +1150,8 @@ static int airoha_eth_recv(struct udevice *dev, int flags, uchar **packetp) static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length) { - struct airoha_eth *eth = dev_get_priv(dev); - struct airoha_qdma *qdma = ð->qdma[0]; + struct airoha_gdm_port *port = dev_get_priv(dev); + struct airoha_qdma *qdma = port->qdma; struct airoha_queue *q; int qid; @@ -964,8 +1192,9 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length) static int arht_eth_write_hwaddr(struct udevice *dev) { + struct airoha_gdm_port *port = dev_get_priv(dev); struct eth_pdata *pdata = dev_get_plat(dev); - struct airoha_eth *eth = dev_get_priv(dev); + struct airoha_qdma *qdma = port->qdma; unsigned char *mac = pdata->enetaddr; u32 macaddr_lsb, macaddr_msb; @@ -977,8 +1206,8 @@ static int arht_eth_write_hwaddr(struct udevice *dev) FIELD_PREP(SMACCR1_MAC0, mac[0]); /* Set MAC for Switch */ - airoha_switch_wr(eth, SWITCH_SMACCR0, macaddr_lsb); - airoha_switch_wr(eth, SWITCH_SMACCR1, macaddr_msb); + airoha_switch_wr(qdma->eth, SWITCH_SMACCR0, macaddr_lsb); + airoha_switch_wr(qdma->eth, SWITCH_SMACCR1, macaddr_msb); return 0; } @@ -986,9 +1215,15 @@ static int arht_eth_write_hwaddr(struct udevice *dev) static int airoha_eth_bind(struct udevice *dev) { struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev); + struct airoha_eth *eth = dev_get_priv(dev); ofnode switch_node, mdio_node; - struct udevice *mdio_dev; - int ret = 0; + int ret; + + /* + * Force Probe as we set the Main ETH driver as misc + * to register multiple eth port for each GDM + */ + dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND); if (!CONFIG_IS_ENABLED(MDIO_MT7531_MMIO)) return 0; @@ -1006,8 +1241,8 @@ static int airoha_eth_bind(struct udevice *dev) return 0; } - ret = device_bind_driver_to_node(dev, "mt7531-mdio-mmio", "mdio", - mdio_node, &mdio_dev); + ret = device_bind_driver_to_node(dev, "mt7531-mdio-mmio", "mt7531-mdio", + mdio_node, ð->switch_mdio_dev); if (ret) debug("Warning: failed to bind mdio controller\n"); @@ -1015,12 +1250,14 @@ static int airoha_eth_bind(struct udevice *dev) } static const struct airoha_eth_soc_data en7523_data = { + .version = 0x7523, .xsi_rsts_names = en7523_xsi_rsts_names, .num_xsi_rsts = ARRAY_SIZE(en7523_xsi_rsts_names), .switch_compatible = "airoha,en7523-switch", }; static const struct airoha_eth_soc_data en7581_data = { + .version = 0x7581, .xsi_rsts_names = en7581_xsi_rsts_names, .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names), .switch_compatible = "airoha,en7581-switch", @@ -1045,13 +1282,21 @@ static const struct eth_ops airoha_eth_ops = { .write_hwaddr = arht_eth_write_hwaddr, }; +U_BOOT_DRIVER(airoha_eth_port) = { + .name = "airoha-eth-port", + .id = UCLASS_ETH, + .of_to_plat = airoha_eth_port_of_to_plat, + .probe = airoha_eth_port_probe, + .ops = &airoha_eth_ops, + .priv_auto = sizeof(struct airoha_gdm_port), + .plat_auto = sizeof(struct eth_pdata), +}; + U_BOOT_DRIVER(airoha_eth) = { .name = "airoha-eth", - .id = UCLASS_ETH, + .id = UCLASS_MISC, .of_match = airoha_eth_ids, .probe = airoha_eth_probe, .bind = airoha_eth_bind, - .ops = &airoha_eth_ops, .priv_auto = sizeof(struct airoha_eth), - .plat_auto = sizeof(struct eth_pdata), }; diff --git a/drivers/net/phy/airoha/Kconfig b/drivers/net/phy/airoha/Kconfig index 999564e4848..fcace9a24ac 100644 --- a/drivers/net/phy/airoha/Kconfig +++ b/drivers/net/phy/airoha/Kconfig @@ -8,4 +8,4 @@ config PHY_AIROHA_EN8811 select FW_LOADER 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 1a628ede82b..0b974472732 100644 --- a/drivers/net/phy/airoha/air_en8811.c +++ b/drivers/net/phy/airoha/air_en8811.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Driver for the Airoha EN8811H 2.5 Gigabit PHY. + * Driver for the Airoha EN8811H and AN8811HB 2.5 Gigabit PHY. * * Limitations of the EN8811H: * - Only full duplex supported @@ -8,9 +8,8 @@ * * Source originated from linux air_en8811h.c * - * Copyright (C) 2025 Airoha Technology Corp. + * Copyright (C) 2025, 2026 Airoha Technology Corp. */ - #include <phy.h> #include <errno.h> #include <log.h> @@ -20,27 +19,15 @@ #include <asm/unaligned.h> #include <linux/iopoll.h> #include <linux/bitops.h> +#include <linux/bitfield.h> #include <linux/compat.h> #include <dm/device_compat.h> #include <u-boot/crc.h> -#define EN8811H_PHY_ID 0x03a2a411 - -#define AIR_FW_ADDR_DM 0x00000000 -#define AIR_FW_ADDR_DSP 0x00100000 - -#define EN8811H_MD32_DM_SIZE 0x4000 -#define EN8811H_MD32_DSP_SIZE 0x20000 - -#define EN8811H_FW_CTRL_1 0x0f0018 -#define EN8811H_FW_CTRL_1_START 0x0 -#define EN8811H_FW_CTRL_1_FINISH 0x1 -#define EN8811H_FW_CTRL_2 0x800000 -#define EN8811H_FW_CTRL_2_LOADING BIT(11) - /* MII Registers */ #define AIR_AUX_CTRL_STATUS 0x1d #define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2) +#define AIR_AUX_CTRL_STATUS_SPEED_10 0x0 #define AIR_AUX_CTRL_STATUS_SPEED_100 0x4 #define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8 #define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc @@ -49,6 +36,7 @@ #define AIR_PHY_PAGE_STANDARD 0x0000 #define AIR_PHY_PAGE_EXTENDED_4 0x0004 +#define AIR_PBUS_MODE_ADDR_HIGH 0x1c /* MII Registers Page 4 */ #define AIR_BPBUS_MODE 0x10 #define AIR_BPBUS_MODE_ADDR_FIXED 0x0000 @@ -63,8 +51,16 @@ #define AIR_BPBUS_RD_DATA_LOW 0x18 /* Registers on MDIO_MMD_VEND1 */ -#define EN8811H_PHY_FW_STATUS 0x8009 -#define EN8811H_PHY_READY 0x02 +#define AIR_PHY_MCU_CMD_1 0x800c +#define AIR_PHY_MCU_CMD_1_MODE1 0x0 +#define AIR_PHY_MCU_CMD_2 0x800d +#define AIR_PHY_MCU_CMD_2_MODE1 0x0 +#define AIR_PHY_MCU_CMD_3 0x800e +#define AIR_PHY_MCU_CMD_3_MODE1 0x1101 +#define AIR_PHY_MCU_CMD_3_DOCMD 0x1100 +#define AIR_PHY_MCU_CMD_4 0x800f +#define AIR_PHY_MCU_CMD_4_MODE1 0x0002 +#define AIR_PHY_MCU_CMD_4_INTCLR 0x00e4 /* Registers on MDIO_MMD_VEND2 */ #define AIR_PHY_LED_BCR 0x021 @@ -77,7 +73,7 @@ #define AIR_PHY_LED_DUR_BLINK 0x023 -#define AIR_PHY_LED_ON(i) (0x024 + ((i) * 2)) +#define AIR_PHY_LED_ON(i) (0x024 + ((i) * 2)) #define AIR_PHY_LED_ON_MASK (GENMASK(6, 0) | BIT(8)) #define AIR_PHY_LED_ON_LINK1000 BIT(0) #define AIR_PHY_LED_ON_LINK100 BIT(1) @@ -90,7 +86,7 @@ #define AIR_PHY_LED_ON_POLARITY BIT(14) #define AIR_PHY_LED_ON_ENABLE BIT(15) -#define AIR_PHY_LED_BLINK(i) (0x025 + ((i) * 2)) +#define AIR_PHY_LED_BLINK(i) (0x025 + ((i) * 2)) #define AIR_PHY_LED_BLINK_1000TX BIT(0) #define AIR_PHY_LED_BLINK_1000RX BIT(1) #define AIR_PHY_LED_BLINK_100TX BIT(2) @@ -104,21 +100,101 @@ #define AIR_PHY_LED_BLINK_2500TX BIT(10) #define AIR_PHY_LED_BLINK_2500RX BIT(11) +/* Registers on BUCKPBUS */ +#define AIR_PHY_CONTROL 0x3a9c +#define AIR_PHY_CONTROL_SURGE_5R BIT(3) +#define AIR_PHY_CONTROL_INTERNAL BIT(11) + +/* Led definitions */ +#define EN8811H_LED_COUNT 3 + +/* Firmware registers */ +#define AIR_FW_ADDR_DM 0x00000000 +#define AIR_FW_ADDR_DSP 0x00100000 +#define EN8811H_FW_CTRL_1 0x0f0018 +#define EN8811H_FW_CTRL_1_START 0x0 +#define EN8811H_FW_CTRL_1_FINISH 0x1 +#define EN8811H_FW_CTRL_2 0x800000 +#define EN8811H_FW_CTRL_2_LOADING BIT(11) +#define EN8811H_PHY_FW_STATUS 0x8009 +#define EN8811H_PHY_READY 0x02 +#define AIR_PHY_FW_STATUS 0x8009 +#define AIR_PHY_READY 0x02 + +#define AIR_PHY_FW_CTRL_1 0x0f0018 +#define AIR_PHY_FW_CTRL_1_START 0x0 +#define AIR_PHY_FW_CTRL_1_FINISH 0x1 + +/* EN8811H */ +#define EN8811H_PHY_ID 0x03a2a411 +#define EN8811H_MD32_DM_SIZE 0x4000 +#define EN8811H_MD32_DSP_SIZE 0x20000 #define EN8811H_FW_VERSION 0x3b3c #define EN8811H_POLARITY 0xca0f8 #define EN8811H_POLARITY_TX_NORMAL BIT(0) #define EN8811H_POLARITY_RX_REVERSE BIT(1) - #define EN8811H_CLK_CGM 0xcf958 #define EN8811H_CLK_CGM_CKO BIT(26) #define EN8811H_HWTRAP1 0xcf914 #define EN8811H_HWTRAP1_CKO BIT(12) -#define clear_bit(bit, bitmap) __clear_bit(bit, bitmap) - -/* Led definitions */ -#define EN8811H_LED_COUNT 3 +/* AN8811HB */ +#define AN8811HB_PHY_ID 0xc0ff04a0 +#define AIR_MD32_DM_SIZE 0x8000 +#define AIR_MD32_DSP_SIZE 0x20000 +#define AIR_PHY_MD32FW_VERSION 0x3b3c + +#define AN8811HB_GPIO_OUTPUT 0x5cf8b8 +#define AN8811HB_GPIO_OUTPUT_MASK GENMASK(15, 0) +#define AN8811HB_GPIO_OUTPUT_345 (BIT(3) | BIT(4) | BIT(5)) +#define AN8811HB_GPIO_OUTPUT_0115 (BIT(0) | BIT(1) | BIT(15)) +#define AN8811HB_GPIO_SEL_1 0x5cf8bc +#define AN8811HB_GPIO_SEL_1_0_MASK GENMASK(2, 0) +#define AN8811HB_GPIO_SEL_1_1_MASK GENMASK(6, 4) +#define AN8811HB_GPIO_SEL_1_0 FIELD_PREP(AN8811HB_GPIO_SEL_1_0_MASK, 1) +#define AN8811HB_GPIO_SEL_1_1 FIELD_PREP(AN8811HB_GPIO_SEL_1_1_MASK, 0) +#define AN8811HB_GPIO_SEL_2 0x5cf8c0 +#define AN8811HB_GPIO_SEL_2_15_MASK GENMASK(30, 28) +#define AN8811HB_GPIO_SEL_2_15 FIELD_PREP(AN8811HB_GPIO_SEL_2_15_MASK, 2) + +#define AN8811HB_CRC_PM_SET1 0xf020c +#define AN8811HB_CRC_PM_MON2 0xf0218 +#define AN8811HB_CRC_PM_MON3 0xf021c +#define AN8811HB_CRC_DM_SET1 0xf0224 +#define AN8811HB_CRC_DM_MON2 0xf0230 +#define AN8811HB_CRC_DM_MON3 0xf0234 +#define AN8811HB_CRC_RD_EN BIT(0) +#define AN8811HB_CRC_ST (BIT(0) | BIT(1)) +#define AN8811HB_CRC_CHECK_PASS BIT(0) + +#define AN8811HB_TX_POLARITY 0x5ce004 +#define AN8811HB_TX_POLARITY_NORMAL BIT(7) +#define AN8811HB_RX_POLARITY 0x5ce61c +#define AN8811HB_RX_POLARITY_NORMAL BIT(7) + +#define AN8811HB_HWTRAP1 0x5cf910 +#define AN8811HB_HWTRAP2 0x5cf914 +#define AN8811HB_HWTRAP2_CKO BIT(28) +#define AN8811HB_HWTRAP2_PKG (BIT(12) | BIT(13) | BIT(14)) +#define AN8811HB_PRO_ID 0x5cf920 +#define AN8811HB_PRO_ID_VERSION GENMASK(3, 0) + +#define AN8811HB_CLK_DRV 0x5cf9e4 +#define AN8811HB_CLK_DRV_CKO_MASK GENMASK(14, 12) +#define AN8811HB_CLK_DRV_CKOPWD BIT(12) +#define AN8811HB_CLK_DRV_CKO_LDPWD BIT(13) +#define AN8811HB_CLK_DRV_CKO_LPPWD BIT(14) + +#define AN8811HB_MCU_SW_RST 0x5cf9f8 +#define AN8811HB_MCU_SW_RST_HOLD BIT(16) +#define AN8811HB_MCU_SW_RST_RUN (BIT(16) | BIT(0)) +#define AN8811HB_MCU_SW_START 0x5cf9fc +#define AN8811HB_MCU_SW_START_EN BIT(16) + +#define clear_bit(bit, bitmap) __clear_bit(bit, bitmap) + +#define SCRIPT_NAME(name) #name "_load_firmware" struct led { unsigned long rules; @@ -191,11 +267,48 @@ enum air_led_trigger_netdev_modes { #define AIR_PHY_LED_DUR (AIR_PHY_LED_DUR_UNIT << AIR_PHY_LED_DUR_BLINK_64MS) struct en8811h_priv { - int firmware_version; + u32 firmware_version; bool mcu_needs_restart; struct led led[EN8811H_LED_COUNT]; + u32 pro_id; + u32 pkg_sel; + u32 mem_size; + const char *script_name; }; +static int air_pbus_reg_write(struct phy_device *phydev, + u32 pbus_reg, u32 pbus_data) +{ + int pbus_addr = (phydev->addr) + 8; + struct mii_dev *bus = phydev->bus; + int ret; + + ret = bus->write(bus, pbus_addr, MDIO_DEVAD_NONE, + AIR_EXT_PAGE_ACCESS, + (pbus_reg >> 16)); + if (ret < 0) + return ret; + + ret = bus->write(bus, pbus_addr, MDIO_DEVAD_NONE, + AIR_PBUS_MODE_ADDR_HIGH, + ((pbus_reg & GENMASK(15, 6)) >> 6)); + if (ret < 0) + return ret; + + ret = bus->write(bus, pbus_addr, MDIO_DEVAD_NONE, + ((pbus_reg & GENMASK(5, 2)) >> 2), + (pbus_data & GENMASK(15, 0))); + if (ret < 0) + return ret; + + ret = bus->write(bus, pbus_addr, MDIO_DEVAD_NONE, 0x10, + ((pbus_data & GENMASK(31, 16)) >> 16)); + if (ret < 0) + return ret; + + return ret; +} + static int air_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address, u32 pbus_data) { @@ -359,8 +472,8 @@ restore_page: static int air_write_buf(struct phy_device *phydev, unsigned long address, unsigned long array_size, const unsigned char *buffer) { - unsigned int offset; int ret, saved_page; + u32 offset; u16 val; saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4); @@ -419,18 +532,144 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev) return ret; } -int en8811h_read_fw(void **fw, size_t *fwsize) +static int an8811hb_check_crc(struct phy_device *phydev, + u32 set1, u32 mon2, u32 mon3) +{ + int ret, retry = 10; + u32 pbus_value; + + /* Configure CRC */ + ret = air_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN, + AN8811HB_CRC_RD_EN); + if (ret < 0) + return ret; + + ret = air_buckpbus_reg_read(phydev, set1, &pbus_value); + if (ret < 0) + return ret; + + debug("%d: reg 0x%x val 0x%x!\n", __LINE__, set1, pbus_value); + + do { + mdelay(300); + + ret = air_buckpbus_reg_read(phydev, mon2, &pbus_value); + if (ret < 0) + return ret; + + debug("%d: reg 0x%x val 0x%x!\n", __LINE__, mon2, pbus_value); + + if (pbus_value & AN8811HB_CRC_ST) { + ret = air_buckpbus_reg_read(phydev, mon3, &pbus_value); + if (ret < 0) + return ret; + + debug("%d: reg 0x%x val 0x%x!\n", __LINE__, mon3, + pbus_value); + + if (pbus_value & AN8811HB_CRC_CHECK_PASS) + debug("CRC Check PASS!\n"); + else + dev_err(phydev->dev, "CRC Check FAIL!(0x%lx)\n", + pbus_value & AN8811HB_CRC_CHECK_PASS); + + break; + } + + if (!retry) { + dev_err(phydev->dev, + "CRC Check is not ready.(Status %u)\n", + pbus_value); + return -ENODEV; + } + } while (--retry); + + ret = air_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN, 0); + if (ret < 0) + return ret; + + ret = air_buckpbus_reg_read(phydev, set1, &pbus_value); + if (ret < 0) + return ret; + + debug("%d: reg 0x%x val 0x%x!\n", __LINE__, set1, pbus_value); + + return ret; +} + +static int an8811hb_mcu_assert(struct phy_device *phydev) +{ + int ret; + + ret = air_pbus_reg_write(phydev, AN8811HB_MCU_SW_RST, + AN8811HB_MCU_SW_RST_HOLD); + if (ret < 0) + return ret; + + ret = air_pbus_reg_write(phydev, AN8811HB_MCU_SW_START, 0); + if (ret < 0) + return ret; + + debug("MCU asserted\n"); + mdelay(50); + + return ret; +} + +static int an8811hb_mcu_deassert(struct phy_device *phydev) +{ + int ret; + + ret = air_pbus_reg_write(phydev, AN8811HB_MCU_SW_START, + AN8811HB_MCU_SW_START_EN); + if (ret < 0) + return ret; + + ret = air_pbus_reg_write(phydev, AN8811HB_MCU_SW_RST, + AN8811HB_MCU_SW_RST_RUN); + if (ret < 0) + return ret; + + debug("MCU deasserted\n"); + mdelay(50); + + return ret; +} + +static int an8811hb_surge_protect_cfg(struct phy_device *phydev) +{ + ofnode node = phy_get_ofnode(phydev); + int ret = 0; + + if (!ofnode_read_bool(node, "airoha,surge-5r")) { + debug("Surge Protection mode - 0R\n"); + return ret; + } + + ret = air_buckpbus_reg_modify(phydev, AIR_PHY_CONTROL, + AIR_PHY_CONTROL_SURGE_5R, + AIR_PHY_CONTROL_SURGE_5R); + if (ret < 0) + return ret; + + debug("Surge Protection mode - 5R\n"); + + return ret; +} + +static int en8811h_read_fw(void **fw, size_t *fwsize, struct en8811h_priv *priv) { + const char *script_name = priv->script_name; + u32 mem_size = priv->mem_size; void *buffer; int ret; - buffer = malloc(EN8811H_MD32_DM_SIZE + EN8811H_MD32_DSP_SIZE); + buffer = malloc(mem_size); if (!buffer) return -ENOMEM; - ret = request_firmware_into_buf_via_script(buffer, - EN8811H_MD32_DM_SIZE + EN8811H_MD32_DSP_SIZE, - "en8811h_load_firmware", fwsize); + ret = request_firmware_into_buf_via_script(buffer, mem_size, + script_name, fwsize); if (ret) { free(buffer); return ret; @@ -450,7 +689,10 @@ static int en8811h_load_firmware(struct phy_device *phydev) void *buffer; int ret; - ret = en8811h_read_fw(&buffer, &fw_size); + priv->script_name = SCRIPT_NAME(en8811h); + priv->mem_size = EN8811H_MD32_DM_SIZE + EN8811H_MD32_DSP_SIZE; + + ret = en8811h_read_fw(&buffer, &fw_size, priv); if (ret < 0) { dev_err(phydev->dev, "Failed to get firmware data\n"); return -EINVAL; @@ -496,9 +738,12 @@ static int en8811h_load_firmware(struct phy_device *phydev) goto en8811h_load_firmware_out; ret = en8811h_wait_mcu_ready(phydev); + if (ret < 0) + goto en8811h_load_firmware_out; air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION, &priv->firmware_version); + dev_info(phydev->dev, "MD32 firmware version: %08x\n", priv->firmware_version); @@ -510,6 +755,130 @@ en8811h_load_firmware_out: return ret; } +static int an8811hb_load_firmware(struct phy_device *phydev) +{ + struct en8811h_priv *priv = phydev->priv; + int ret, retry = 10; + size_t fw_size; + void *buffer; + u32 reg_val; + + ret = an8811hb_mcu_assert(phydev); + if (ret < 0) + return ret; + + ret = an8811hb_mcu_deassert(phydev); + if (ret < 0) + return ret; + + priv->script_name = SCRIPT_NAME(an8811hb); + priv->mem_size = AIR_MD32_DM_SIZE + AIR_MD32_DSP_SIZE; + + ret = en8811h_read_fw(&buffer, &fw_size, priv); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1, + AIR_PHY_FW_CTRL_1_START); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = air_write_buf(phydev, AIR_FW_ADDR_DM, AIR_MD32_DM_SIZE, + (unsigned char *)buffer); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = an8811hb_check_crc(phydev, AN8811HB_CRC_DM_SET1, + AN8811HB_CRC_DM_MON2, AN8811HB_CRC_DM_MON3); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, AIR_MD32_DSP_SIZE, + (unsigned char *)buffer + AIR_MD32_DM_SIZE); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = an8811hb_check_crc(phydev, AN8811HB_CRC_PM_SET1, + AN8811HB_CRC_PM_MON2, AN8811HB_CRC_PM_MON3); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1, + AIR_PHY_FW_CTRL_1_FINISH); + if (ret < 0) + goto an8811hb_load_firmware_out; + + ret = an8811hb_surge_protect_cfg(phydev); + if (ret < 0) { + dev_err(phydev->dev, "an8811hb_surge_protect_cfg fail. (ret=%d)\n", ret); + goto an8811hb_load_firmware_out; + } + + do { + mdelay(300); + + ret = air_buckpbus_reg_read(phydev, AIR_PHY_FW_CTRL_1, ®_val); + if (ret < 0) + goto an8811hb_load_firmware_out; + + if (reg_val == AIR_PHY_FW_CTRL_1_FINISH) + break; + + debug("%d: reg 0x%x val 0x%x!\n", __LINE__, AIR_PHY_FW_CTRL_1, + reg_val); + + ret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1, + AIR_PHY_FW_CTRL_1_FINISH); + if (ret < 0) + goto an8811hb_load_firmware_out; + + } while (--retry); + + ret = en8811h_wait_mcu_ready(phydev); + if (ret < 0) + goto an8811hb_load_firmware_out; + + air_buckpbus_reg_read(phydev, AIR_PHY_MD32FW_VERSION, + &priv->firmware_version); + + debug("MD32 firmware version: %08x\n", priv->firmware_version); + +an8811hb_load_firmware_out: + free(buffer); + if (ret < 0) + dev_err(phydev->dev, "Firmware loading failed: %d\n", ret); + + return ret; +} + +int an8811hb_cko_cfg(struct phy_device *phydev) +{ + ofnode node = phy_get_ofnode(phydev); + u32 pbus_value; + int ret = 0; + + if (!ofnode_read_bool(node, "airoha,phy-output-clock")) { + ret = air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV, + AN8811HB_CLK_DRV_CKO_MASK, + AN8811HB_CLK_DRV_CKOPWD | + AN8811HB_CLK_DRV_CKO_LDPWD | + AN8811HB_CLK_DRV_CKO_LPPWD); + if (ret < 0) + return ret; + + debug("CKO Output mode - Disabled\n"); + } else { + ret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value); + if (ret < 0) + return ret; + + debug("CKO Output %dMHz - Enabled\n", + (pbus_value & AN8811HB_HWTRAP2_CKO) ? 50 : 25); + } + + return ret; +} + static int en8811h_restart_mcu(struct phy_device *phydev) { int ret; @@ -613,13 +982,30 @@ static int air_led_init(struct phy_device *phydev, u8 index, u8 state, u8 pol) return 0; } +/** + * air_leds_init - Initialize and configure LEDs for a phy device. + * + * @phydev: Pointer to the phy_device structure. + * @num: Number of LEDs to initialize. + * @dur: Duration for LED blink in milliseconds. It sets the duration + * for both the ON and OFF periods (OFF period will be half of `dur`). + * @mode: LED operation mode. Supported modes are: + * - AIR_LED_MODE_DISABLE: Disables LED control. + * - AIR_LED_MODE_USER_DEFINE: Enables user-defined LED control. + * + * Initializes and configures LEDs on a phy device with a specified blink duration + * and mode. Supports disabling or enabling user-defined control. + * Return: + * On success, returns 0. On error, it returns a negative value that denotes + * the error code. + */ + static int air_leds_init(struct phy_device *phydev, int num, u16 dur, int mode) { struct en8811h_priv *priv = phydev->priv; int ret, i; - ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_BLINK, - dur); + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_BLINK, dur); if (ret < 0) return ret; @@ -707,10 +1093,121 @@ static int en8811h_config(struct phy_device *phydev) pbus_value |= EN8811H_POLARITY_TX_NORMAL; ret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY, EN8811H_POLARITY_RX_REVERSE | - EN8811H_POLARITY_TX_NORMAL, pbus_value); + EN8811H_POLARITY_TX_NORMAL, + pbus_value); + if (ret < 0) + return ret; + + ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR, + AIR_LED_MODE_USER_DEFINE); + if (ret < 0) { + dev_err(phydev->dev, "Failed to disable leds: %d\n", ret); + return ret; + } + + return 0; +} + +static int an8811hb_config(struct phy_device *phydev) +{ + struct en8811h_priv *priv = phydev->priv; + u32 pbus_value = 0; + ofnode node; + int ret = 0; + + node = phy_get_ofnode(phydev); + if (!ofnode_valid(node)) + return 0; + + /* If restart happened in .probe(), no need to restart now */ + if (priv->mcu_needs_restart) { + ret = an8811hb_mcu_assert(phydev); + if (ret < 0) + return ret; + + ret = an8811hb_mcu_deassert(phydev); + if (ret < 0) + return ret; + + ret = en8811h_restart_mcu(phydev); + if (ret < 0) + return ret; + } else { + ret = an8811hb_load_firmware(phydev); + if (ret) { + dev_err(phydev->dev, "Load firmware fail.\n"); + return ret; + } + /* Next calls to .config() mcu needs to restart */ + priv->mcu_needs_restart = true; + } + + ret = air_buckpbus_reg_read(phydev, AN8811HB_PRO_ID, &pbus_value); + if (ret < 0) + return ret; + priv->pro_id = (pbus_value & AN8811HB_PRO_ID_VERSION) + 1; + + ret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value); + if (ret < 0) + return ret; + priv->pkg_sel = (pbus_value & AN8811HB_HWTRAP2_PKG) >> 12; + debug("%s(%d) Version: E%d\n", + priv->pkg_sel ? "AN8811HBCN" : "AN8811HBN", priv->pkg_sel, + priv->pro_id); + + /* Serdes polarity */ + pbus_value = 0; + if (ofnode_read_bool(node, "airoha,pnswap-rx")) + pbus_value &= ~AN8811HB_RX_POLARITY_NORMAL; + else + pbus_value |= AN8811HB_RX_POLARITY_NORMAL; + + debug("1 pbus_value 0x%x\n", pbus_value); + ret = air_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY, + AN8811HB_RX_POLARITY_NORMAL, pbus_value); + if (ret < 0) + return ret; + + pbus_value = 0; + if (ofnode_read_bool(node, "airoha,pnswap-tx")) + pbus_value &= ~AN8811HB_TX_POLARITY_NORMAL; + else + pbus_value |= AN8811HB_TX_POLARITY_NORMAL; + + debug("2 pbus_value 0x%x\n", pbus_value); + ret = air_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY, + AN8811HB_TX_POLARITY_NORMAL, pbus_value); if (ret < 0) return ret; + /* Configure led gpio pins as output */ + if (priv->pkg_sel) { + ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT, + AN8811HB_GPIO_OUTPUT_MASK, + AN8811HB_GPIO_OUTPUT_0115); + if (ret < 0) + return ret; + ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_1, + AN8811HB_GPIO_SEL_1_0_MASK | + AN8811HB_GPIO_SEL_1_1_MASK, + AN8811HB_GPIO_SEL_1_0 | + AN8811HB_GPIO_SEL_1_1); + if (ret < 0) + return ret; + + ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_2, + AN8811HB_GPIO_SEL_2_15_MASK, + AN8811HB_GPIO_SEL_2_15); + if (ret < 0) + return ret; + } else { + ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT, + AN8811HB_GPIO_OUTPUT_345, + AN8811HB_GPIO_OUTPUT_345); + if (ret < 0) + return ret; + } + ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR, AIR_LED_MODE_USER_DEFINE); if (ret < 0) { @@ -718,9 +1215,91 @@ static int en8811h_config(struct phy_device *phydev) return ret; } + /* Co-Clock Output */ + ret = an8811hb_cko_cfg(phydev); + if (ret) + return ret; + + printf("AN8811HB initialize OK !\n"); + + return 0; +} + +static int an8811hb_update_duplex(struct phy_device *phydev) +{ + int lpa; + + if (phydev->autoneg == AUTONEG_ENABLE) { + lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA); + if (lpa < 0) + return lpa; + + switch (phydev->speed) { + case SPEED_2500: + case SPEED_1000: + phydev->duplex = DUPLEX_FULL; + break; + case SPEED_100: + phydev->duplex = (lpa & LPA_100FULL) ? DUPLEX_FULL : + DUPLEX_HALF; + break; + case SPEED_10: + phydev->duplex = (lpa & LPA_10FULL) ? DUPLEX_FULL : + DUPLEX_HALF; + break; + } + } else { + int bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); + + if (phydev->speed == SPEED_2500) + phydev->duplex = DUPLEX_FULL; + else + phydev->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : + DUPLEX_HALF; + } + return 0; } +static int an8811hb_parse_status(struct phy_device *phydev) +{ + int ret = 0, reg_value; + + reg_value = phy_read(phydev, MDIO_DEVAD_NONE, AIR_AUX_CTRL_STATUS); + if (reg_value < 0) + return reg_value; + + switch (reg_value & AIR_AUX_CTRL_STATUS_SPEED_MASK) { + case AIR_AUX_CTRL_STATUS_SPEED_2500: + phydev->speed = SPEED_2500; + break; + case AIR_AUX_CTRL_STATUS_SPEED_1000: + phydev->speed = SPEED_1000; + break; + case AIR_AUX_CTRL_STATUS_SPEED_100: + phydev->speed = SPEED_100; + break; + case AIR_AUX_CTRL_STATUS_SPEED_10: + phydev->speed = SPEED_10; + break; + default: + dev_err(phydev->dev, + "Auto-neg error, defaulting to 2500M/FD\n"); + phydev->speed = SPEED_2500; + phydev->duplex = DUPLEX_FULL; + return 0; + } + + /* Update duplex mode based on speed and negotiation status */ + ret = an8811hb_update_duplex(phydev); + if (ret < 0) + return ret; + + debug("Speed: %d, %s duplex\n", phydev->speed, + (phydev->duplex) ? "full" : "half"); + return ret; +} + static int en8811h_parse_status(struct phy_device *phydev) { int ret = 0, reg_value; @@ -742,7 +1321,8 @@ static int en8811h_parse_status(struct phy_device *phydev) phydev->speed = SPEED_100; break; default: - dev_err(phydev->dev, "Auto-neg error, defaulting to 2500M/FD\n"); + dev_err(phydev->dev, + "Auto-neg error, defaulting to 2500M/FD\n"); phydev->speed = SPEED_2500; break; } @@ -752,24 +1332,35 @@ static int en8811h_parse_status(struct phy_device *phydev) static int en8811h_startup(struct phy_device *phydev) { + u32 phy_id = phydev->phy_id; int ret = 0; ret = genphy_update_link(phydev); if (ret) return ret; - return en8811h_parse_status(phydev); + if (phy_id == EN8811H_PHY_ID) + ret = en8811h_parse_status(phydev); + else if (phy_id == AN8811HB_PHY_ID) + ret = an8811hb_parse_status(phydev); + + return ret; } static int en8811h_probe(struct phy_device *phydev) { struct en8811h_priv *priv; + int phy_id; priv = malloc(sizeof(*priv)); if (!priv) return -ENOMEM; memset(priv, 0, sizeof(*priv)); + debug("%s driver is probed.\n", phydev->drv->name); + get_phy_id(phydev->bus, phydev->addr, MDIO_DEVAD_NONE, &phy_id); + debug("phy id is 0x%x.\n", phy_id); + priv->led[0].rules = AIR_DEFAULT_TRIGGER_LED0; priv->led[1].rules = AIR_DEFAULT_TRIGGER_LED1; priv->led[2].rules = AIR_DEFAULT_TRIGGER_LED2; @@ -782,12 +1373,12 @@ static int en8811h_probe(struct phy_device *phydev) return 0; } -static int en8811h_read_page(struct phy_device *phydev) +static int air_phy_read_page(struct phy_device *phydev) { return phy_read(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS); } -static int en8811h_write_page(struct phy_device *phydev, int page) +static int air_phy_write_page(struct phy_device *phydev, int page) { return phy_write(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS, page); } @@ -798,8 +1389,20 @@ U_BOOT_PHY_DRIVER(en8811h) = { .mask = 0x0ffffff0, .config = &en8811h_config, .probe = &en8811h_probe, - .read_page = &en8811h_read_page, - .write_page = &en8811h_write_page, + .read_page = &air_phy_read_page, + .write_page = &air_phy_write_page, + .startup = &en8811h_startup, + .shutdown = &genphy_shutdown, +}; + +U_BOOT_PHY_DRIVER(an8811hb) = { + .name = "Airoha AN8811HB", + .uid = AN8811HB_PHY_ID, + .mask = 0x0ffffff0, + .config = &an8811hb_config, + .probe = &en8811h_probe, + .read_page = &air_phy_read_page, + .write_page = &air_phy_write_page, .startup = &en8811h_startup, .shutdown = &genphy_shutdown, }; |
