#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy.h>
#include <linux/regmap.h>
#define MTK_GPHY_ID_MT7981 …
#define MTK_GPHY_ID_MT7988 …
#define MTK_EXT_PAGE_ACCESS …
#define MTK_PHY_PAGE_STANDARD …
#define MTK_PHY_PAGE_EXTENDED_3 …
#define MTK_PHY_LPI_REG_14 …
#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK …
#define MTK_PHY_LPI_REG_1c …
#define MTK_PHY_SMI_DET_ON_THRESH_MASK …
#define MTK_PHY_PAGE_EXTENDED_2A30 …
#define MTK_PHY_PAGE_EXTENDED_52B5 …
#define ANALOG_INTERNAL_OPERATION_MAX_US …
#define TXRESERVE_MIN …
#define TXRESERVE_MAX …
#define MTK_PHY_ANARG_RG …
#define MTK_PHY_TCLKOFFSET_MASK …
#define MTK_PHY_TXVLD_DA_RG …
#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK …
#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 …
#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK …
#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 …
#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK …
#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 …
#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK …
#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 …
#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK …
#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 …
#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK …
#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 …
#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK …
#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK …
#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 …
#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK …
#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK …
#define MTK_PHY_RXADC_CTRL_RG7 …
#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK …
#define MTK_PHY_RXADC_CTRL_RG9 …
#define MTK_PHY_DA_RX_PSBN_TBT_MASK …
#define MTK_PHY_DA_RX_PSBN_HBT_MASK …
#define MTK_PHY_DA_RX_PSBN_GBE_MASK …
#define MTK_PHY_DA_RX_PSBN_LP_MASK …
#define MTK_PHY_LDO_OUTPUT_V …
#define MTK_PHY_RG_ANA_CAL_RG0 …
#define MTK_PHY_RG_CAL_CKINV …
#define MTK_PHY_RG_ANA_CALEN …
#define MTK_PHY_RG_ZCALEN_A …
#define MTK_PHY_RG_ANA_CAL_RG1 …
#define MTK_PHY_RG_ZCALEN_B …
#define MTK_PHY_RG_ZCALEN_C …
#define MTK_PHY_RG_ZCALEN_D …
#define MTK_PHY_RG_TXVOS_CALEN …
#define MTK_PHY_RG_ANA_CAL_RG5 …
#define MTK_PHY_RG_REXT_TRIM_MASK …
#define MTK_PHY_RG_TX_FILTER …
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 …
#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK …
#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK …
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 …
#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK …
#define MTK_PHY_RG_TESTMUX_ADC_CTRL …
#define MTK_PHY_RG_TXEN_DIG_MASK …
#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B …
#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK …
#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK …
#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D …
#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK …
#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK …
#define MTK_PHY_RG_AD_CAL_COMP …
#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT …
#define MTK_PHY_RG_AD_CAL_CLK …
#define MTK_PHY_DA_CAL_CLK …
#define MTK_PHY_RG_AD_CALIN …
#define MTK_PHY_DA_CALIN_FLAG …
#define MTK_PHY_RG_DASN_DAC_IN0_A …
#define MTK_PHY_DASN_DAC_IN0_A_MASK …
#define MTK_PHY_RG_DASN_DAC_IN0_B …
#define MTK_PHY_DASN_DAC_IN0_B_MASK …
#define MTK_PHY_RG_DASN_DAC_IN0_C …
#define MTK_PHY_DASN_DAC_IN0_C_MASK …
#define MTK_PHY_RG_DASN_DAC_IN0_D …
#define MTK_PHY_DASN_DAC_IN0_D_MASK …
#define MTK_PHY_RG_DASN_DAC_IN1_A …
#define MTK_PHY_DASN_DAC_IN1_A_MASK …
#define MTK_PHY_RG_DASN_DAC_IN1_B …
#define MTK_PHY_DASN_DAC_IN1_B_MASK …
#define MTK_PHY_RG_DASN_DAC_IN1_C …
#define MTK_PHY_DASN_DAC_IN1_C_MASK …
#define MTK_PHY_RG_DASN_DAC_IN1_D …
#define MTK_PHY_DASN_DAC_IN1_D_MASK …
#define MTK_PHY_RG_DEV1E_REG19b …
#define MTK_PHY_BYPASS_DSP_LPI_READY …
#define MTK_PHY_RG_LP_IIR2_K1_L …
#define MTK_PHY_RG_LP_IIR2_K1_U …
#define MTK_PHY_RG_LP_IIR2_K2_L …
#define MTK_PHY_RG_LP_IIR2_K2_U …
#define MTK_PHY_RG_LP_IIR2_K3_L …
#define MTK_PHY_RG_LP_IIR2_K3_U …
#define MTK_PHY_RG_LP_IIR2_K4_L …
#define MTK_PHY_RG_LP_IIR2_K4_U …
#define MTK_PHY_RG_LP_IIR2_K5_L …
#define MTK_PHY_RG_LP_IIR2_K5_U …
#define MTK_PHY_RG_DEV1E_REG234 …
#define MTK_PHY_TR_OPEN_LOOP_EN_MASK …
#define MTK_PHY_LPF_X_AVERAGE_MASK …
#define MTK_PHY_TR_LP_IIR_EEE_EN …
#define MTK_PHY_RG_LPF_CNT_VAL …
#define MTK_PHY_RG_DEV1E_REG238 …
#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK …
#define MTK_PHY_LPI_SLV_SEND_TX_EN …
#define MTK_PHY_RG_DEV1E_REG239 …
#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK …
#define MTK_PHY_LPI_TXPCS_LOC_RCV …
#define MTK_PHY_RG_DEV1E_REG27C …
#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK …
#define MTK_PHY_RG_DEV1E_REG27D …
#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK …
#define MTK_PHY_RG_DEV1E_REG2C7 …
#define MTK_PHY_MAX_GAIN_MASK …
#define MTK_PHY_MIN_GAIN_MASK …
#define MTK_PHY_RG_DEV1E_REG2D1 …
#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK …
#define MTK_PHY_LPI_SKIP_SD_SLV_TR …
#define MTK_PHY_LPI_TR_READY …
#define MTK_PHY_LPI_VCO_EEE_STG0_EN …
#define MTK_PHY_RG_DEV1E_REG323 …
#define MTK_PHY_EEE_WAKE_MAS_INT_DC …
#define MTK_PHY_EEE_WAKE_SLV_INT_DC …
#define MTK_PHY_RG_DEV1E_REG324 …
#define MTK_PHY_SMI_DETCNT_MAX_MASK …
#define MTK_PHY_SMI_DET_MAX_EN …
#define MTK_PHY_RG_DEV1E_REG326 …
#define MTK_PHY_LPI_MODE_SD_ON …
#define MTK_PHY_RESET_RANDUPD_CNT …
#define MTK_PHY_TREC_UPDATE_ENAB_CLR …
#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF …
#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP …
#define MTK_PHY_LDO_PUMP_EN_PAIRAB …
#define MTK_PHY_LDO_PUMP_EN_PAIRCD …
#define MTK_PHY_DA_TX_R50_PAIR_A …
#define MTK_PHY_DA_TX_R50_PAIR_B …
#define MTK_PHY_DA_TX_R50_PAIR_C …
#define MTK_PHY_DA_TX_R50_PAIR_D …
#define MTK_PHY_LED0_ON_CTRL …
#define MTK_PHY_LED1_ON_CTRL …
#define MTK_PHY_LED_ON_MASK …
#define MTK_PHY_LED_ON_LINK1000 …
#define MTK_PHY_LED_ON_LINK100 …
#define MTK_PHY_LED_ON_LINK10 …
#define MTK_PHY_LED_ON_LINK …
#define MTK_PHY_LED_ON_LINKDOWN …
#define MTK_PHY_LED_ON_FDX …
#define MTK_PHY_LED_ON_HDX …
#define MTK_PHY_LED_ON_FORCE_ON …
#define MTK_PHY_LED_ON_POLARITY …
#define MTK_PHY_LED_ON_ENABLE …
#define MTK_PHY_LED0_BLINK_CTRL …
#define MTK_PHY_LED1_BLINK_CTRL …
#define MTK_PHY_LED_BLINK_1000TX …
#define MTK_PHY_LED_BLINK_1000RX …
#define MTK_PHY_LED_BLINK_100TX …
#define MTK_PHY_LED_BLINK_100RX …
#define MTK_PHY_LED_BLINK_10TX …
#define MTK_PHY_LED_BLINK_10RX …
#define MTK_PHY_LED_BLINK_RX …
#define MTK_PHY_LED_BLINK_TX …
#define MTK_PHY_LED_BLINK_COLLISION …
#define MTK_PHY_LED_BLINK_RX_CRC_ERR …
#define MTK_PHY_LED_BLINK_RX_IDLE_ERR …
#define MTK_PHY_LED_BLINK_FORCE_BLINK …
#define MTK_PHY_LED1_DEFAULT_POLARITIES …
#define MTK_PHY_RG_BG_RASEL …
#define MTK_PHY_RG_BG_RASEL_MASK …
#define RG_GPIO_MISC_TPBANK0 …
#define RG_GPIO_MISC_TPBANK0_BOOTMODE …
#define EFS_DA_TX_I2MPB_A(x) …
#define EFS_DA_TX_I2MPB_B(x) …
#define EFS_DA_TX_I2MPB_C(x) …
#define EFS_DA_TX_I2MPB_D(x) …
#define EFS_DA_TX_AMP_OFFSET_A(x) …
#define EFS_DA_TX_AMP_OFFSET_B(x) …
#define EFS_DA_TX_AMP_OFFSET_C(x) …
#define EFS_DA_TX_AMP_OFFSET_D(x) …
#define EFS_DA_TX_R50_A(x) …
#define EFS_DA_TX_R50_B(x) …
#define EFS_DA_TX_R50_C(x) …
#define EFS_DA_TX_R50_D(x) …
#define EFS_RG_BG_RASEL(x) …
#define EFS_RG_REXT_TRIM(x) …
enum { … };
enum calibration_mode { … };
enum CAL_ITEM { … };
enum CAL_MODE { … };
#define MTK_PHY_LED_STATE_FORCE_ON …
#define MTK_PHY_LED_STATE_FORCE_BLINK …
#define MTK_PHY_LED_STATE_NETDEV …
struct mtk_socphy_priv { … };
struct mtk_socphy_shared { … };
static int mtk_socphy_read_page(struct phy_device *phydev)
{ … }
static int mtk_socphy_write_page(struct phy_device *phydev, int page)
{ … }
static int cal_cycle(struct phy_device *phydev, int devad,
u32 regnum, u16 mask, u16 cal_val)
{ … }
static int rext_fill_result(struct phy_device *phydev, u16 *buf)
{ … }
static int rext_cal_efuse(struct phy_device *phydev, u32 *buf)
{ … }
static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf)
{ … }
static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf)
{ … }
static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
{ … }
static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf)
{ … }
static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val,
u8 txg_calen_x)
{ … }
static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf,
u8 txg_calen_x)
{ … }
static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x)
{ … }
static void mt798x_phy_common_finetune(struct phy_device *phydev)
{ … }
static void mt7981_phy_finetune(struct phy_device *phydev)
{ … }
static void mt7988_phy_finetune(struct phy_device *phydev)
{ … }
static void mt798x_phy_eee(struct phy_device *phydev)
{ … }
static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
u8 start_pair, u8 end_pair)
{ … }
static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item,
u8 start_pair, u8 end_pair, u32 *buf)
{ … }
static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item,
enum CAL_MODE cal_mode, u8 start_pair,
u8 end_pair, u32 *buf)
{ … }
static int mt798x_phy_calibration(struct phy_device *phydev)
{ … }
static int mt798x_phy_config_init(struct phy_device *phydev)
{ … }
static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
bool on)
{ … }
static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
bool blinking)
{ … }
static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
unsigned long *delay_on,
unsigned long *delay_off)
{ … }
static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
u8 index, enum led_brightness value)
{ … }
static const unsigned long supported_triggers = …;
static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
unsigned long rules)
{
if (index > 1)
return -EINVAL;
if (rules & ~supported_triggers)
return -EOPNOTSUPP;
return 0;
};
static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
unsigned long *rules)
{
unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
struct mtk_socphy_priv *priv = phydev->priv;
int on, blink;
if (index > 1)
return -EINVAL;
on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
if (on < 0)
return -EIO;
blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
index ? MTK_PHY_LED1_BLINK_CTRL :
MTK_PHY_LED0_BLINK_CTRL);
if (blink < 0)
return -EIO;
if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
MTK_PHY_LED_ON_LINKDOWN)) ||
(blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
set_bit(bit_netdev, &priv->led_state);
else
clear_bit(bit_netdev, &priv->led_state);
if (on & MTK_PHY_LED_ON_FORCE_ON)
set_bit(bit_on, &priv->led_state);
else
clear_bit(bit_on, &priv->led_state);
if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
set_bit(bit_blink, &priv->led_state);
else
clear_bit(bit_blink, &priv->led_state);
if (!rules)
return 0;
if (on & MTK_PHY_LED_ON_LINK)
*rules |= BIT(TRIGGER_NETDEV_LINK);
if (on & MTK_PHY_LED_ON_LINK10)
*rules |= BIT(TRIGGER_NETDEV_LINK_10);
if (on & MTK_PHY_LED_ON_LINK100)
*rules |= BIT(TRIGGER_NETDEV_LINK_100);
if (on & MTK_PHY_LED_ON_LINK1000)
*rules |= BIT(TRIGGER_NETDEV_LINK_1000);
if (on & MTK_PHY_LED_ON_FDX)
*rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
if (on & MTK_PHY_LED_ON_HDX)
*rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
if (blink & MTK_PHY_LED_BLINK_RX)
*rules |= BIT(TRIGGER_NETDEV_RX);
if (blink & MTK_PHY_LED_BLINK_TX)
*rules |= BIT(TRIGGER_NETDEV_TX);
return 0;
};
static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
unsigned long rules)
{
unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
struct mtk_socphy_priv *priv = phydev->priv;
u16 on = 0, blink = 0;
int ret;
if (index > 1)
return -EINVAL;
if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
on |= MTK_PHY_LED_ON_FDX;
if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
on |= MTK_PHY_LED_ON_HDX;
if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK10;
if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK100;
if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
on |= MTK_PHY_LED_ON_LINK1000;
if (rules & BIT(TRIGGER_NETDEV_RX)) {
blink |= (on & MTK_PHY_LED_ON_LINK) ?
(((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
MTK_PHY_LED_BLINK_RX;
}
if (rules & BIT(TRIGGER_NETDEV_TX)) {
blink |= (on & MTK_PHY_LED_ON_LINK) ?
(((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
MTK_PHY_LED_BLINK_TX;
}
if (blink || on)
set_bit(bit_netdev, &priv->led_state);
else
clear_bit(bit_netdev, &priv->led_state);
ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
MTK_PHY_LED1_ON_CTRL :
MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED_ON_FDX |
MTK_PHY_LED_ON_HDX |
MTK_PHY_LED_ON_LINK,
on);
if (ret)
return ret;
return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
MTK_PHY_LED1_BLINK_CTRL :
MTK_PHY_LED0_BLINK_CTRL, blink);
};
static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
{ … }
static int mt7988_phy_fix_leds_polarities(struct phy_device *phydev)
{ … }
static int mt7988_phy_probe_shared(struct phy_device *phydev)
{ … }
static void mt798x_phy_leds_state_init(struct phy_device *phydev)
{ … }
static int mt7988_phy_probe(struct phy_device *phydev)
{ … }
static int mt7981_phy_probe(struct phy_device *phydev)
{ … }
static struct phy_driver mtk_socphy_driver[] = …;
module_phy_driver(mtk_socphy_driver);
static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = …;
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;
MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl);