mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 20:14:06 +02:00
net: phy: air_en8811h: add Airoha AN8811HB support
The Airoha AN8811HB is mostly compatible with the EN8811H, adding 10Base-T support and reducing power consumption. This driver is based on the air_an8811hb v0.0.4 out-of-tree driver written by "Lucien.Jheng <lucien.jheng@airoha.com>" Firmware is available in linux-firmware. The driver has been tested with firmware version 25110702 Signed-off-by: Bjørn Mork <bjorn@mork.no> Link: https://patch.msgid.link/20260127125547.1475164-3-bjorn@mork.no Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
28693bceee
commit
5afda1d734
|
|
@ -1,14 +1,15 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0+
|
// 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 PHYs.
|
||||||
*
|
*
|
||||||
* Limitations of the EN8811H:
|
* Limitations:
|
||||||
* - Only full duplex supported
|
* - Only full duplex supported
|
||||||
* - Forced speed (AN off) is not supported by hardware (100Mbps)
|
* - Forced speed (AN off) is not supported by hardware (100Mbps)
|
||||||
*
|
*
|
||||||
* Source originated from airoha's en8811h.c and en8811h.h v1.2.1
|
* Source originated from airoha's en8811h.c and en8811h.h v1.2.1
|
||||||
|
* with AN8811HB bits from air_an8811hb.c v0.0.4
|
||||||
*
|
*
|
||||||
* Copyright (C) 2023 Airoha Technology Corp.
|
* Copyright (C) 2023, 2026 Airoha Technology Corp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
|
@ -21,9 +22,12 @@
|
||||||
#include <linux/unaligned.h>
|
#include <linux/unaligned.h>
|
||||||
|
|
||||||
#define EN8811H_PHY_ID 0x03a2a411
|
#define EN8811H_PHY_ID 0x03a2a411
|
||||||
|
#define AN8811HB_PHY_ID 0xc0ff04a0
|
||||||
|
|
||||||
#define EN8811H_MD32_DM "airoha/EthMD32.dm.bin"
|
#define EN8811H_MD32_DM "airoha/EthMD32.dm.bin"
|
||||||
#define EN8811H_MD32_DSP "airoha/EthMD32.DSP.bin"
|
#define EN8811H_MD32_DSP "airoha/EthMD32.DSP.bin"
|
||||||
|
#define AN8811HB_MD32_DM "airoha/an8811hb/EthMD32_CRC.DM.bin"
|
||||||
|
#define AN8811HB_MD32_DSP "airoha/an8811hb/EthMD32_CRC.DSP.bin"
|
||||||
|
|
||||||
#define AIR_FW_ADDR_DM 0x00000000
|
#define AIR_FW_ADDR_DM 0x00000000
|
||||||
#define AIR_FW_ADDR_DSP 0x00100000
|
#define AIR_FW_ADDR_DSP 0x00100000
|
||||||
|
|
@ -31,6 +35,7 @@
|
||||||
/* MII Registers */
|
/* MII Registers */
|
||||||
#define AIR_AUX_CTRL_STATUS 0x1d
|
#define AIR_AUX_CTRL_STATUS 0x1d
|
||||||
#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2)
|
#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_100 0x4
|
||||||
#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8
|
#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8
|
||||||
#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc
|
#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc
|
||||||
|
|
@ -56,6 +61,7 @@
|
||||||
#define EN8811H_PHY_FW_STATUS 0x8009
|
#define EN8811H_PHY_FW_STATUS 0x8009
|
||||||
#define EN8811H_PHY_READY 0x02
|
#define EN8811H_PHY_READY 0x02
|
||||||
|
|
||||||
|
#define AIR_PHY_MCU_CMD_0 0x800b
|
||||||
#define AIR_PHY_MCU_CMD_1 0x800c
|
#define AIR_PHY_MCU_CMD_1 0x800c
|
||||||
#define AIR_PHY_MCU_CMD_1_MODE1 0x0
|
#define AIR_PHY_MCU_CMD_1_MODE1 0x0
|
||||||
#define AIR_PHY_MCU_CMD_2 0x800d
|
#define AIR_PHY_MCU_CMD_2 0x800d
|
||||||
|
|
@ -65,6 +71,10 @@
|
||||||
#define AIR_PHY_MCU_CMD_3_DOCMD 0x1100
|
#define AIR_PHY_MCU_CMD_3_DOCMD 0x1100
|
||||||
#define AIR_PHY_MCU_CMD_4 0x800f
|
#define AIR_PHY_MCU_CMD_4 0x800f
|
||||||
#define AIR_PHY_MCU_CMD_4_MODE1 0x0002
|
#define AIR_PHY_MCU_CMD_4_MODE1 0x0002
|
||||||
|
#define AIR_PHY_MCU_CMD_4_CABLE_PAIR_A 0x00d7
|
||||||
|
#define AIR_PHY_MCU_CMD_4_CABLE_PAIR_B 0x00d8
|
||||||
|
#define AIR_PHY_MCU_CMD_4_CABLE_PAIR_C 0x00d9
|
||||||
|
#define AIR_PHY_MCU_CMD_4_CABLE_PAIR_D 0x00da
|
||||||
#define AIR_PHY_MCU_CMD_4_INTCLR 0x00e4
|
#define AIR_PHY_MCU_CMD_4_INTCLR 0x00e4
|
||||||
|
|
||||||
/* Registers on MDIO_MMD_VEND2 */
|
/* Registers on MDIO_MMD_VEND2 */
|
||||||
|
|
@ -106,6 +116,9 @@
|
||||||
#define AIR_PHY_LED_BLINK_2500RX BIT(11)
|
#define AIR_PHY_LED_BLINK_2500RX BIT(11)
|
||||||
|
|
||||||
/* Registers on BUCKPBUS */
|
/* Registers on BUCKPBUS */
|
||||||
|
#define AIR_PHY_CONTROL 0x3a9c
|
||||||
|
#define AIR_PHY_CONTROL_INTERNAL BIT(11)
|
||||||
|
|
||||||
#define EN8811H_2P5G_LPA 0x3b30
|
#define EN8811H_2P5G_LPA 0x3b30
|
||||||
#define EN8811H_2P5G_LPA_2P5G BIT(0)
|
#define EN8811H_2P5G_LPA_2P5G BIT(0)
|
||||||
|
|
||||||
|
|
@ -129,6 +142,34 @@
|
||||||
#define EN8811H_FW_CTRL_2 0x800000
|
#define EN8811H_FW_CTRL_2 0x800000
|
||||||
#define EN8811H_FW_CTRL_2_LOADING BIT(11)
|
#define EN8811H_FW_CTRL_2_LOADING BIT(11)
|
||||||
|
|
||||||
|
#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_GPIO_OUTPUT 0x5cf8b8
|
||||||
|
#define AN8811HB_GPIO_OUTPUT_345 (BIT(3) | BIT(4) | BIT(5))
|
||||||
|
|
||||||
|
#define AN8811HB_HWTRAP1 0x5cf910
|
||||||
|
#define AN8811HB_HWTRAP2 0x5cf914
|
||||||
|
#define AN8811HB_HWTRAP2_CKO BIT(28)
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
/* Led definitions */
|
/* Led definitions */
|
||||||
#define EN8811H_LED_COUNT 3
|
#define EN8811H_LED_COUNT 3
|
||||||
|
|
||||||
|
|
@ -466,6 +507,43 @@ static int en8811h_wait_mcu_ready(struct phy_device *phydev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int an8811hb_check_crc(struct phy_device *phydev, u32 set1,
|
||||||
|
u32 mon2, u32 mon3)
|
||||||
|
{
|
||||||
|
u32 pbus_value;
|
||||||
|
int retry = 25;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Configure CRC */
|
||||||
|
ret = air_buckpbus_reg_modify(phydev, set1,
|
||||||
|
AN8811HB_CRC_RD_EN,
|
||||||
|
AN8811HB_CRC_RD_EN);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
air_buckpbus_reg_read(phydev, set1, &pbus_value);
|
||||||
|
|
||||||
|
do {
|
||||||
|
msleep(300);
|
||||||
|
air_buckpbus_reg_read(phydev, mon2, &pbus_value);
|
||||||
|
|
||||||
|
/* We do not know what errors this check is supposed
|
||||||
|
* catch or what to do about a failure. So print the
|
||||||
|
* result and continue like the vendor driver does.
|
||||||
|
*/
|
||||||
|
if (pbus_value & AN8811HB_CRC_ST) {
|
||||||
|
air_buckpbus_reg_read(phydev, mon3, &pbus_value);
|
||||||
|
phydev_dbg(phydev, "CRC Check %s!\n",
|
||||||
|
pbus_value & AN8811HB_CRC_CHECK_PASS ?
|
||||||
|
"PASS" : "FAIL");
|
||||||
|
return air_buckpbus_reg_modify(phydev, set1,
|
||||||
|
AN8811HB_CRC_RD_EN, 0);
|
||||||
|
}
|
||||||
|
} while (--retry);
|
||||||
|
|
||||||
|
phydev_err(phydev, "CRC Check is not ready (%u)\n", pbus_value);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
static void en8811h_print_fw_version(struct phy_device *phydev)
|
static void en8811h_print_fw_version(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
struct en8811h_priv *priv = phydev->priv;
|
struct en8811h_priv *priv = phydev->priv;
|
||||||
|
|
@ -476,6 +554,54 @@ static void en8811h_print_fw_version(struct phy_device *phydev)
|
||||||
priv->firmware_version);
|
priv->firmware_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int an8811hb_load_file(struct phy_device *phydev, const char *name,
|
||||||
|
u32 address)
|
||||||
|
{
|
||||||
|
struct device *dev = &phydev->mdio.dev;
|
||||||
|
const struct firmware *fw;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = request_firmware_direct(&fw, name, dev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = air_write_buf(phydev, address, fw);
|
||||||
|
release_firmware(fw);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int an8811hb_load_firmware(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
|
||||||
|
EN8811H_FW_CTRL_1_START);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = an8811hb_load_file(phydev, AN8811HB_MD32_DM, AIR_FW_ADDR_DM);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = an8811hb_check_crc(phydev, AN8811HB_CRC_DM_SET1,
|
||||||
|
AN8811HB_CRC_DM_MON2,
|
||||||
|
AN8811HB_CRC_DM_MON3);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = an8811hb_load_file(phydev, AN8811HB_MD32_DSP, AIR_FW_ADDR_DSP);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = an8811hb_check_crc(phydev, AN8811HB_CRC_PM_SET1,
|
||||||
|
AN8811HB_CRC_PM_MON2,
|
||||||
|
AN8811HB_CRC_PM_MON3);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return en8811h_wait_mcu_ready(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
static int en8811h_load_firmware(struct phy_device *phydev)
|
static int en8811h_load_firmware(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
struct device *dev = &phydev->mdio.dev;
|
struct device *dev = &phydev->mdio.dev;
|
||||||
|
|
@ -939,6 +1065,45 @@ static int en8811h_leds_setup(struct phy_device *phydev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int an8811hb_probe(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct en8811h_priv *priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct en8811h_priv),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
phydev->priv = priv;
|
||||||
|
|
||||||
|
ret = an8811hb_load_firmware(phydev);
|
||||||
|
if (ret < 0) {
|
||||||
|
phydev_err(phydev, "Load firmware failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
en8811h_print_fw_version(phydev);
|
||||||
|
|
||||||
|
/* mcu has just restarted after firmware load */
|
||||||
|
priv->mcu_needs_restart = false;
|
||||||
|
|
||||||
|
/* MDIO_DEVS1/2 empty, so set mmds_present bits here */
|
||||||
|
phydev->c45_ids.mmds_present |= MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
|
||||||
|
|
||||||
|
ret = en8811h_leds_setup(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Configure led gpio pins as output */
|
||||||
|
ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
|
||||||
|
AN8811HB_GPIO_OUTPUT_345,
|
||||||
|
AN8811HB_GPIO_OUTPUT_345);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int en8811h_probe(struct phy_device *phydev)
|
static int en8811h_probe(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
struct en8811h_priv *priv;
|
struct en8811h_priv *priv;
|
||||||
|
|
@ -980,6 +1145,37 @@ static int en8811h_probe(struct phy_device *phydev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int an8811hb_config_serdes_polarity(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct device *dev = &phydev->mdio.dev;
|
||||||
|
u32 pbus_value = 0;
|
||||||
|
unsigned int pol;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = phy_get_manual_rx_polarity(dev_fwnode(dev),
|
||||||
|
phy_modes(phydev->interface), &pol);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
if (pol == PHY_POL_NORMAL)
|
||||||
|
pbus_value |= AN8811HB_RX_POLARITY_NORMAL;
|
||||||
|
ret = air_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,
|
||||||
|
AN8811HB_RX_POLARITY_NORMAL,
|
||||||
|
pbus_value);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = phy_get_manual_tx_polarity(dev_fwnode(dev),
|
||||||
|
phy_modes(phydev->interface), &pol);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
pbus_value = 0;
|
||||||
|
if (pol == PHY_POL_NORMAL)
|
||||||
|
pbus_value |= AN8811HB_TX_POLARITY_NORMAL;
|
||||||
|
return air_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,
|
||||||
|
AN8811HB_TX_POLARITY_NORMAL,
|
||||||
|
pbus_value);
|
||||||
|
}
|
||||||
|
|
||||||
static int en8811h_config_serdes_polarity(struct phy_device *phydev)
|
static int en8811h_config_serdes_polarity(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
struct device *dev = &phydev->mdio.dev;
|
struct device *dev = &phydev->mdio.dev;
|
||||||
|
|
@ -1016,6 +1212,33 @@ static int en8811h_config_serdes_polarity(struct phy_device *phydev)
|
||||||
EN8811H_POLARITY_TX_NORMAL, pbus_value);
|
EN8811H_POLARITY_TX_NORMAL, pbus_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int an8811hb_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct en8811h_priv *priv = phydev->priv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* If restart happened in .probe(), no need to restart now */
|
||||||
|
if (priv->mcu_needs_restart) {
|
||||||
|
ret = en8811h_restart_mcu(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
/* Next calls to .config_init() mcu needs to restart */
|
||||||
|
priv->mcu_needs_restart = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = an8811hb_config_serdes_polarity(phydev);
|
||||||
|
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)
|
||||||
|
phydev_err(phydev, "Failed to initialize leds: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int en8811h_config_init(struct phy_device *phydev)
|
static int en8811h_config_init(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
struct en8811h_priv *priv = phydev->priv;
|
struct en8811h_priv *priv = phydev->priv;
|
||||||
|
|
@ -1129,13 +1352,23 @@ static int en8811h_read_status(struct phy_device *phydev)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (phy_id_compare_model(phydev->phy_id, AN8811HB_PHY_ID)) {
|
||||||
|
val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
|
||||||
|
if (val < 0)
|
||||||
|
return val;
|
||||||
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||||
|
phydev->lp_advertising,
|
||||||
|
val & MDIO_AN_10GBT_STAT_LP2_5G);
|
||||||
|
} else {
|
||||||
/* Get link partner 2.5GBASE-T ability from vendor register */
|
/* Get link partner 2.5GBASE-T ability from vendor register */
|
||||||
ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, &pbus_value);
|
ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA,
|
||||||
|
&pbus_value);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||||
phydev->lp_advertising,
|
phydev->lp_advertising,
|
||||||
pbus_value & EN8811H_2P5G_LPA_2P5G);
|
pbus_value & EN8811H_2P5G_LPA_2P5G);
|
||||||
|
}
|
||||||
|
|
||||||
if (phydev->autoneg_complete)
|
if (phydev->autoneg_complete)
|
||||||
phy_resolve_aneg_pause(phydev);
|
phy_resolve_aneg_pause(phydev);
|
||||||
|
|
@ -1157,6 +1390,9 @@ static int en8811h_read_status(struct phy_device *phydev)
|
||||||
case AIR_AUX_CTRL_STATUS_SPEED_100:
|
case AIR_AUX_CTRL_STATUS_SPEED_100:
|
||||||
phydev->speed = SPEED_100;
|
phydev->speed = SPEED_100;
|
||||||
break;
|
break;
|
||||||
|
case AIR_AUX_CTRL_STATUS_SPEED_10:
|
||||||
|
phydev->speed = SPEED_10;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Firmware before version 24011202 has no vendor register 2P5G_LPA.
|
/* Firmware before version 24011202 has no vendor register 2P5G_LPA.
|
||||||
|
|
@ -1241,20 +1477,42 @@ static struct phy_driver en8811h_driver[] = {
|
||||||
.led_brightness_set = air_led_brightness_set,
|
.led_brightness_set = air_led_brightness_set,
|
||||||
.led_hw_control_set = air_led_hw_control_set,
|
.led_hw_control_set = air_led_hw_control_set,
|
||||||
.led_hw_control_get = air_led_hw_control_get,
|
.led_hw_control_get = air_led_hw_control_get,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_MODEL(AN8811HB_PHY_ID),
|
||||||
|
.name = "Airoha AN8811HB",
|
||||||
|
.probe = an8811hb_probe,
|
||||||
|
.get_features = en8811h_get_features,
|
||||||
|
.config_init = an8811hb_config_init,
|
||||||
|
.get_rate_matching = en8811h_get_rate_matching,
|
||||||
|
.config_aneg = en8811h_config_aneg,
|
||||||
|
.read_status = en8811h_read_status,
|
||||||
|
.config_intr = en8811h_clear_intr,
|
||||||
|
.handle_interrupt = en8811h_handle_interrupt,
|
||||||
|
.led_hw_is_supported = en8811h_led_hw_is_supported,
|
||||||
|
.read_page = air_phy_read_page,
|
||||||
|
.write_page = air_phy_write_page,
|
||||||
|
.led_blink_set = air_led_blink_set,
|
||||||
|
.led_brightness_set = air_led_brightness_set,
|
||||||
|
.led_hw_control_set = air_led_hw_control_set,
|
||||||
|
.led_hw_control_get = air_led_hw_control_get,
|
||||||
} };
|
} };
|
||||||
|
|
||||||
module_phy_driver(en8811h_driver);
|
module_phy_driver(en8811h_driver);
|
||||||
|
|
||||||
static const struct mdio_device_id __maybe_unused en8811h_tbl[] = {
|
static const struct mdio_device_id __maybe_unused en8811h_tbl[] = {
|
||||||
{ PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) },
|
{ PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) },
|
||||||
|
{ PHY_ID_MATCH_MODEL(AN8811HB_PHY_ID) },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(mdio, en8811h_tbl);
|
MODULE_DEVICE_TABLE(mdio, en8811h_tbl);
|
||||||
MODULE_FIRMWARE(EN8811H_MD32_DM);
|
MODULE_FIRMWARE(EN8811H_MD32_DM);
|
||||||
MODULE_FIRMWARE(EN8811H_MD32_DSP);
|
MODULE_FIRMWARE(EN8811H_MD32_DSP);
|
||||||
|
MODULE_FIRMWARE(AN8811HB_MD32_DM);
|
||||||
|
MODULE_FIRMWARE(AN8811HB_MD32_DSP);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Airoha EN8811H PHY drivers");
|
MODULE_DESCRIPTION("Airoha EN8811H and AN8811HB PHY drivers");
|
||||||
MODULE_AUTHOR("Airoha");
|
MODULE_AUTHOR("Airoha");
|
||||||
MODULE_AUTHOR("Eric Woudstra <ericwouds@gmail.com>");
|
MODULE_AUTHOR("Eric Woudstra <ericwouds@gmail.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user