forked from OERV-BSP/u-boot
Merge patch series "Add support for MediaTek MT7987/MT7988 built-in 2.5Gb ethernet PHY (v4)"
Weijie Gao <weijie.gao@mediatek.com> says: This patch adds PHY driver for MediaTek MT7987/MT7988 built-in 2.5Gb ethernet PHY. [trini: Change 'tristate' Kconfig to 'bool'] Link: https://lore.kernel.org/r/cover.1757315849.git.weijie.gao@mediatek.com
This commit is contained in:
+2
-2
@@ -423,6 +423,8 @@ F: drivers/clk/mediatek/
|
||||
F: drivers/cpu/mtk_cpu.c
|
||||
F: drivers/i2c/mtk_i2c.c
|
||||
F: drivers/mmc/mtk-sd.c
|
||||
F: drivers/net/mtk_eth/
|
||||
F: drivers/net/phy/mediatek/
|
||||
F: drivers/phy/phy-mtk-*
|
||||
F: drivers/pinctrl/mediatek/
|
||||
F: drivers/power/domain/mtk-power-domain.c
|
||||
@@ -437,8 +439,6 @@ F: drivers/timer/mtk_timer.c
|
||||
F: drivers/usb/host/xhci-mtk.c
|
||||
F: drivers/usb/mtu3/
|
||||
F: drivers/watchdog/mtk_wdt.c
|
||||
F: drivers/net/mtk_eth.c
|
||||
F: drivers/net/mtk_eth.h
|
||||
F: drivers/reset/reset-mediatek.c
|
||||
F: drivers/serial/serial_mtk.c
|
||||
F: include/dt-bindings/clock/mediatek,*
|
||||
|
||||
@@ -229,20 +229,18 @@ int request_firmware_into_buf(struct udevice *dev,
|
||||
}
|
||||
|
||||
int request_firmware_into_buf_via_script(void **buf, size_t max_size,
|
||||
const char *script_name)
|
||||
const char *script_name,
|
||||
size_t *retsize)
|
||||
{
|
||||
char *args[2] = { "run", (char *)script_name };
|
||||
int ret, repeatable;
|
||||
ulong addr, size;
|
||||
int ret;
|
||||
char cmd[32];
|
||||
|
||||
if (!buf || !script_name || !max_size)
|
||||
return -EINVAL;
|
||||
|
||||
/* Create command to run the firmware loading script */
|
||||
snprintf(cmd, sizeof(cmd), "run %s", script_name);
|
||||
|
||||
/* Run the firmware loading script */
|
||||
ret = run_command_list(cmd, -1, 0);
|
||||
ret = cmd_process(0, 2, args, &repeatable, NULL);
|
||||
if (ret) {
|
||||
log_err("Firmware loading script '%s' not defined or failed.\n",
|
||||
script_name);
|
||||
@@ -269,6 +267,9 @@ int request_firmware_into_buf_via_script(void **buf, size_t max_size,
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
if (retsize)
|
||||
*retsize = size;
|
||||
|
||||
memcpy(*buf, (void *)addr, size);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -100,6 +100,7 @@ struct mtk_eth_priv {
|
||||
bool pn_swap;
|
||||
|
||||
struct phy_device *phydev;
|
||||
ofnode phy_node;
|
||||
int phy_interface;
|
||||
int phy_addr;
|
||||
|
||||
@@ -572,6 +573,7 @@ static int mtk_phy_probe(struct udevice *dev)
|
||||
if (!phydev)
|
||||
return -ENODEV;
|
||||
|
||||
phydev->node = priv->phy_node;
|
||||
phydev->supported &= PHY_GBIT_FEATURES;
|
||||
phydev->advertising = phydev->supported;
|
||||
|
||||
@@ -1458,6 +1460,8 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->phy_node = args.node;
|
||||
|
||||
priv->phy_addr = ofnode_read_s32_default(args.node, "reg", -1);
|
||||
if (priv->phy_addr < 0) {
|
||||
printf("error: phy address is not specified\n");
|
||||
|
||||
@@ -184,6 +184,8 @@ config PHY_MARVELL_10G
|
||||
help
|
||||
Support for the Marvell Alaska MV88X3310 and compatible PHYs.
|
||||
|
||||
source "drivers/net/phy/mediatek/Kconfig"
|
||||
|
||||
config PHY_MESON_GXL
|
||||
bool "Amlogic Meson GXL Internal PHY support"
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ obj-$(CONFIG_PHY_ET1011C) += et1011c.o
|
||||
obj-$(CONFIG_PHY_LXT) += lxt.o
|
||||
obj-$(CONFIG_PHY_MARVELL) += marvell.o
|
||||
obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o
|
||||
obj-y += mediatek/
|
||||
obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
|
||||
obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
|
||||
obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
config MTK_NET_PHYLIB
|
||||
bool
|
||||
|
||||
config PHY_MEDIATEK_2P5GE
|
||||
bool "MediaTek built-in 2.5Gb ethernet PHYs"
|
||||
depends on OF_CONTROL && (TARGET_MT7987 || TARGET_MT7988)
|
||||
select MTK_NET_PHYLIB
|
||||
select FS_LOADER
|
||||
help
|
||||
Supports MediaTek SoC built-in 2.5Gb ethernet PHYs.
|
||||
|
||||
This driver requires firmware download for PHY to enable its
|
||||
functionality. The board can override certian firmware downloading
|
||||
function to provide the firmware data.
|
||||
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
|
||||
obj-$(CONFIG_PHY_MEDIATEK_2P5GE) += mtk-2p5ge.o
|
||||
@@ -0,0 +1,627 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2025 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Author: Sky Huang <SkyLake.Huang@mediatek.com>
|
||||
* Author: Weijie Gao <weijie.gao@mediatek.com>
|
||||
*/
|
||||
#include <asm/io.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/of_access.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <dm/ofnode.h>
|
||||
#include <fs_loader.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <phy.h>
|
||||
#include "mtk.h"
|
||||
|
||||
#define MTK_2P5GPHY_ID_MT7987 0x00339c91
|
||||
#define MTK_2P5GPHY_ID_MT7988 0x00339c11
|
||||
|
||||
#define PBUS_BASE 0x0f000000
|
||||
#define PBUS_SIZE 0x1f0024
|
||||
|
||||
#define MTK_2P5GPHY_PMD_REG 0x010000
|
||||
#define DO_NOT_RESET (MTK_2P5GPHY_PMD_REG + 0x28)
|
||||
#define DO_NOT_RESET_XBZ BIT(0)
|
||||
#define DO_NOT_RESET_PMA BIT(3)
|
||||
#define DO_NOT_RESET_RX BIT(5)
|
||||
#define FNPLL_PWR_CTRL1 (MTK_2P5GPHY_PMD_REG + 0x208)
|
||||
#define RG_SPEED_MASK GENMASK(3, 0)
|
||||
#define RG_SPEED_2500 BIT(3)
|
||||
#define RG_SPEED_100 BIT(0)
|
||||
#define FNPLL_PWR_CTRL_STATUS (MTK_2P5GPHY_PMD_REG + 0x20c)
|
||||
#define RG_STABLE_MASK GENMASK(3, 0)
|
||||
#define RG_SPEED_2500_STABLE BIT(3)
|
||||
#define RG_SPEED_100_STABLE BIT(0)
|
||||
|
||||
#define MTK_2P5GPHY_XBZ_PCS 0x030000
|
||||
#define PHY_CTRL_CONFIG (MTK_2P5GPHY_XBZ_PCS + 0x200)
|
||||
#define PMU_WP (MTK_2P5GPHY_XBZ_PCS + 0x800)
|
||||
#define WRITE_PROTECT_KEY 0xCAFEF00D
|
||||
#define PMU_PMA_AUTO_CFG (MTK_2P5GPHY_XBZ_PCS + 0x820)
|
||||
#define POWER_ON_AUTO_MODE BIT(16)
|
||||
#define PMU_AUTO_MODE_EN BIT(0)
|
||||
#define PMU_PMA_STATUS (MTK_2P5GPHY_XBZ_PCS + 0x840)
|
||||
#define CLK_IS_DISABLED BIT(3)
|
||||
|
||||
#define MTK_2P5GPHY_XBZ_PMA_RX 0x080000
|
||||
#define SMEM_WDAT0 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5000)
|
||||
#define SMEM_WDAT1 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5004)
|
||||
#define SMEM_WDAT2 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5008)
|
||||
#define SMEM_WDAT3 (MTK_2P5GPHY_XBZ_PMA_RX + 0x500c)
|
||||
#define SMEM_CTRL (MTK_2P5GPHY_XBZ_PMA_RX + 0x5024)
|
||||
#define SMEM_HW_RDATA_ZERO BIT(24)
|
||||
#define SMEM_ADDR_REF_ADDR (MTK_2P5GPHY_XBZ_PMA_RX + 0x502c)
|
||||
#define CM_CTRL_P01 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5100)
|
||||
#define CM_CTRL_P23 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5124)
|
||||
#define DM_CTRL_P01 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5200)
|
||||
#define DM_CTRL_P23 (MTK_2P5GPHY_XBZ_PMA_RX + 0x5224)
|
||||
|
||||
#define MTK_2P5GPHY_CHIP_SCU 0x0cf800
|
||||
#define SYS_SW_RESET (MTK_2P5GPHY_CHIP_SCU + 0x128)
|
||||
#define RESET_RST_CNT BIT(0)
|
||||
|
||||
#define MTK_2P5GPHY_MCU_CSR 0x0f0000
|
||||
#define MD32_EN_CFG (MTK_2P5GPHY_MCU_CSR + 0x18)
|
||||
#define MD32_EN BIT(0)
|
||||
|
||||
#define MTK_2P5GPHY_PMB_FW 0x100000
|
||||
|
||||
#define MTK_2P5GPHY_FCM_BASE 0x0e0000
|
||||
#define FC_LWM (MTK_2P5GPHY_FCM_BASE + 0x14)
|
||||
#define TX_FC_LWM_MASK GENMASK(31, 16)
|
||||
#define MIN_IPG_NUM (MTK_2P5GPHY_FCM_BASE + 0x2c)
|
||||
#define LS_MIN_IPG_NUM_MASK GENMASK(7, 0)
|
||||
#define FIFO_CTRL (MTK_2P5GPHY_FCM_BASE + 0x40)
|
||||
#define TX_SFIFO_IDLE_CNT_MASK GENMASK(31, 28)
|
||||
#define TX_SFIFO_DEL_IPG_WM_MASK GENMASK(23, 16)
|
||||
|
||||
#define MTK_2P5GPHY_APB_BASE 0x11c30000
|
||||
#define MTK_2P5GPHY_APB_SIZE 0x9c
|
||||
#define SW_RESET 0x94
|
||||
#define MD32_RESTART_EN_CLEAR BIT(9)
|
||||
|
||||
/* Registers on CL22 page 0 */
|
||||
#define PHY_AUX_CTRL_STATUS 0x1d
|
||||
#define PHY_AUX_DPX_MASK GENMASK(5, 5)
|
||||
#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
|
||||
|
||||
enum {
|
||||
PHY_AUX_SPD_10 = 0,
|
||||
PHY_AUX_SPD_100,
|
||||
PHY_AUX_SPD_1000,
|
||||
PHY_AUX_SPD_2500,
|
||||
};
|
||||
|
||||
/* Registers on MDIO_MMD_VEND1 */
|
||||
#define MTK_PHY_LINK_STATUS_RELATED 0x147
|
||||
#define MTK_PHY_BYPASS_LINK_STATUS_OK BIT(4)
|
||||
#define MTK_PHY_FORCE_LINK_STATUS_HCD BIT(3)
|
||||
|
||||
#define MTK_PHY_AN_FORCE_SPEED_REG 0x313
|
||||
#define MTK_PHY_MASTER_FORCE_SPEED_SEL_EN BIT(7)
|
||||
#define MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK GENMASK(6, 0)
|
||||
|
||||
#define MTK_PHY_LPI_PCS_DSP_CTRL 0x121
|
||||
#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
|
||||
|
||||
#define MTK_PHY_PMA_PMD_SPEED_ABILITY 0x300
|
||||
#define CAP_100X_HDX BIT(14)
|
||||
#define CAP_10T_HDX BIT(12)
|
||||
|
||||
/* Registers on MDIO_MMD_VEND2 */
|
||||
#define MT7987_OPTIONS 0x110
|
||||
#define NORMAL_RETRAIN_DISABLE BIT(0)
|
||||
|
||||
/* Registers on Token Ring debug nodes */
|
||||
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
|
||||
#define AUTO_NP_10XEN BIT(6)
|
||||
|
||||
/* Firmware file size */
|
||||
#define MT7987_2P5GE_PMB_FW_SIZE 0x18000
|
||||
#define MT7988_2P5GE_PMB_FW_SIZE 0x20000
|
||||
|
||||
#define MT7987_2P5GE_DSPBITTB_SIZE 0x7000
|
||||
|
||||
struct mtk_i2p5ge_fw_info {
|
||||
u8 datecode[4];
|
||||
u8 plat[2];
|
||||
u8 ver[2];
|
||||
};
|
||||
|
||||
struct mtk_i2p5ge_priv {
|
||||
void __iomem *reg_base;
|
||||
};
|
||||
|
||||
static inline void pbus_write(struct mtk_i2p5ge_priv *priv, u32 offset,
|
||||
u32 val)
|
||||
{
|
||||
writel(val, priv->reg_base + offset);
|
||||
}
|
||||
|
||||
static inline void pbus_rmw(struct mtk_i2p5ge_priv *priv, u32 offset, u32 clr,
|
||||
u32 set)
|
||||
{
|
||||
clrsetbits_le32(priv->reg_base + offset, clr, set);
|
||||
}
|
||||
|
||||
static int mt798x_i2p5ge_download_fw(struct mtk_i2p5ge_priv *priv,
|
||||
size_t fwsize, const void *fwdata)
|
||||
{
|
||||
u32 __iomem *fwmem = priv->reg_base + MTK_2P5GPHY_PMB_FW;
|
||||
const u32 *fw;
|
||||
u32 i;
|
||||
|
||||
/* Assume fw data is 4-byte aligned */
|
||||
fw = fwdata;
|
||||
|
||||
for (i = 0; i < (fwsize >> 2); i++)
|
||||
writel(fw[i], &fwmem[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt798x_i2p5ge_phy_probe(struct phy_device *phydev)
|
||||
{
|
||||
struct mtk_i2p5ge_priv *priv;
|
||||
|
||||
priv = malloc(sizeof(*priv));
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->reg_base = ioremap(PBUS_BASE, PBUS_SIZE);
|
||||
if (!priv->reg_base) {
|
||||
free(priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
phydev->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt798x_i2p5ge_phy_config(struct phy_device *phydev)
|
||||
{
|
||||
|
||||
/* Setup LED */
|
||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
|
||||
MTK_PHY_LED_ON_LINK10 |
|
||||
MTK_PHY_LED_ON_LINK100 |
|
||||
MTK_PHY_LED_ON_LINK1000 |
|
||||
MTK_PHY_LED_ON_LINK2500);
|
||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
|
||||
MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX);
|
||||
|
||||
/* Switch pinctrl after setting polarity to avoid bogus blinking */
|
||||
pinctrl_select_state(phydev->dev, "i2p5gbe-led");
|
||||
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
|
||||
MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
|
||||
|
||||
/* Enable 16-bit next page exchange bit if 1000-BT isn't advertising */
|
||||
mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AUTO_NP_10XEN,
|
||||
FIELD_PREP(AUTO_NP_10XEN, 0x1));
|
||||
|
||||
/* Set HW auto downshift */
|
||||
mtk_phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_1);
|
||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
|
||||
MTK_PHY_AUX_CTRL_AND_STATUS,
|
||||
MTK_PHY_ENABLE_DOWNSHIFT);
|
||||
mtk_phy_restore_page(phydev);
|
||||
|
||||
/* Configure parallel detction functionality */
|
||||
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
|
||||
MTK_PHY_PMA_PMD_SPEED_ABILITY,
|
||||
CAP_10T_HDX | CAP_100X_HDX);
|
||||
phy_clear_bits_mmd(phydev, MDIO_DEVAD_NONE,
|
||||
MII_ADVERTISE,
|
||||
ADVERTISE_10HALF | ADVERTISE_100HALF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt798x_i2p5ge_print_fw_info(const void *fwdata, size_t fwsize)
|
||||
{
|
||||
const struct mtk_i2p5ge_fw_info *info;
|
||||
u8 ver_minor, ver_patch;
|
||||
|
||||
info = (const void *)((uintptr_t)fwdata + fwsize - sizeof(*info));
|
||||
|
||||
ver_minor = info->ver[1] >> 4;
|
||||
ver_patch = info->ver[1] & 0xf;
|
||||
|
||||
printf("Firmware loaded, date %02x%02x/%02x/%02x, ver %x.%u.%u\n",
|
||||
info->datecode[0], info->datecode[1], info->datecode[2],
|
||||
info->datecode[3], info->ver[0], ver_minor, ver_patch);
|
||||
}
|
||||
|
||||
int __weak mt7987_i2p5ge_get_fw(void **fw, size_t *fwsize,
|
||||
void **dspfw, size_t *dspfwsize)
|
||||
{
|
||||
void *pmb, *dsp;
|
||||
int ret;
|
||||
|
||||
pmb = malloc(MT7987_2P5GE_PMB_FW_SIZE);
|
||||
if (!pmb)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = request_firmware_into_buf_via_script(
|
||||
&pmb, MT7987_2P5GE_PMB_FW_SIZE,
|
||||
"mt7987_i2p5ge_load_pmb_firmware", fwsize);
|
||||
if (ret) {
|
||||
free(pmb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsp = malloc(MT7987_2P5GE_DSPBITTB_SIZE);
|
||||
if (!dsp) {
|
||||
free(pmb);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = request_firmware_into_buf_via_script(
|
||||
&dsp, MT7987_2P5GE_DSPBITTB_SIZE,
|
||||
"mt7987_i2p5ge_load_dspbit_firmware", dspfwsize);
|
||||
if (ret) {
|
||||
free(pmb);
|
||||
free(dsp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*fw = pmb;
|
||||
*dspfw = dsp;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mt7987_i2p5ge_download_dspfw(struct mtk_i2p5ge_priv *priv,
|
||||
const void *dspfw_data)
|
||||
{
|
||||
const u32 *dspfw;
|
||||
u32 i;
|
||||
|
||||
pbus_rmw(priv, SMEM_CTRL, 0, SMEM_HW_RDATA_ZERO);
|
||||
|
||||
pbus_rmw(priv, PHY_CTRL_CONFIG, 0, BIT(16));
|
||||
|
||||
/* Initialize data memory */
|
||||
pbus_rmw(priv, DM_CTRL_P01, 0, BIT(28));
|
||||
pbus_rmw(priv, DM_CTRL_P23, 0, BIT(28));
|
||||
|
||||
/* Initialize coefficient memory */
|
||||
pbus_rmw(priv, CM_CTRL_P01, 0, BIT(28));
|
||||
pbus_rmw(priv, CM_CTRL_P23, 0, BIT(28));
|
||||
|
||||
/* Initialize PM offset */
|
||||
pbus_write(priv, SMEM_ADDR_REF_ADDR, 0);
|
||||
|
||||
/* Assume DSP bit data is 4-byte aligned */
|
||||
dspfw = dspfw_data;
|
||||
|
||||
for (i = 0; i < (MT7987_2P5GE_DSPBITTB_SIZE >> 2); i += 4) {
|
||||
pbus_write(priv, SMEM_WDAT0, dspfw[i]);
|
||||
pbus_write(priv, SMEM_WDAT1, dspfw[i + 1]);
|
||||
pbus_write(priv, SMEM_WDAT2, dspfw[i + 2]);
|
||||
pbus_write(priv, SMEM_WDAT3, dspfw[i + 3]);
|
||||
}
|
||||
|
||||
pbus_rmw(priv, DM_CTRL_P01, BIT(28), 0);
|
||||
pbus_rmw(priv, DM_CTRL_P23, BIT(28), 0);
|
||||
|
||||
pbus_rmw(priv, CM_CTRL_P01, BIT(28), 0);
|
||||
pbus_rmw(priv, CM_CTRL_P23, BIT(28), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7987_i2p5ge_phy_load_fw(struct phy_device *phydev)
|
||||
{
|
||||
struct mtk_i2p5ge_priv *priv = phydev->priv;
|
||||
size_t fw_size, dspfw_size;
|
||||
void __iomem *apb_base;
|
||||
void *fw, *dspfw;
|
||||
int ret, fwrc;
|
||||
u32 reg;
|
||||
|
||||
apb_base = ioremap(MTK_2P5GPHY_APB_BASE, MTK_2P5GPHY_APB_SIZE);
|
||||
if (!apb_base)
|
||||
return -ENODEV;
|
||||
|
||||
fwrc = mt7987_i2p5ge_get_fw(&fw, &fw_size, &dspfw, &dspfw_size);
|
||||
if (fwrc < 0) {
|
||||
dev_err(phydev->dev, "Failed to get firmware data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fw_size != MT7987_2P5GE_PMB_FW_SIZE) {
|
||||
dev_err(phydev->dev,
|
||||
"PMB firmware size mismatch (0x%zx != 0x%x)\n",
|
||||
fw_size, MT7987_2P5GE_PMB_FW_SIZE);
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (dspfw_size != MT7987_2P5GE_DSPBITTB_SIZE) {
|
||||
dev_err(phydev->dev,
|
||||
"DSP code size mismatch (0x%zx != 0x%x)\n",
|
||||
dspfw_size, MT7987_2P5GE_DSPBITTB_SIZE);
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Force 2.5Gphy back to AN state */
|
||||
phy_set_bits_mmd(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
|
||||
mdelay(5);
|
||||
phy_set_bits_mmd(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_PDOWN);
|
||||
|
||||
clrbits_le16(apb_base + SW_RESET, MD32_RESTART_EN_CLEAR);
|
||||
setbits_le16(apb_base + SW_RESET, MD32_RESTART_EN_CLEAR);
|
||||
clrbits_le16(apb_base + SW_RESET, MD32_RESTART_EN_CLEAR);
|
||||
|
||||
pbus_rmw(priv, MD32_EN_CFG, MD32_EN, 0);
|
||||
|
||||
ret = mt798x_i2p5ge_download_fw(priv, MT7987_2P5GE_PMB_FW_SIZE, fw);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
/* Enable 100Mbps module clock. */
|
||||
pbus_rmw(priv, FNPLL_PWR_CTRL1, RG_SPEED_MASK, RG_SPEED_100);
|
||||
|
||||
/* Check if 100Mbps module clock is ready. */
|
||||
ret = readl_poll_timeout(priv->reg_base + FNPLL_PWR_CTRL_STATUS, reg,
|
||||
reg & RG_SPEED_100_STABLE, 10000);
|
||||
if (ret) {
|
||||
dev_err(phydev->dev,
|
||||
"Timed out enabling 100Mbps module clock\n");
|
||||
}
|
||||
|
||||
/* Enable 2.5Gbps module clock. */
|
||||
pbus_rmw(priv, FNPLL_PWR_CTRL1, RG_SPEED_MASK, RG_SPEED_2500);
|
||||
|
||||
/* Check if 2.5Gbps module clock is ready. */
|
||||
ret = readl_poll_timeout(priv->reg_base + FNPLL_PWR_CTRL_STATUS, reg,
|
||||
reg & RG_SPEED_2500_STABLE, 10000);
|
||||
|
||||
if (ret) {
|
||||
dev_err(phydev->dev,
|
||||
"Timed out enabling 2.5Gbps module clock\n");
|
||||
}
|
||||
|
||||
/* Disable AN */
|
||||
phy_clear_bits_mmd(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_ANENABLE);
|
||||
|
||||
/* Force to run at 2.5G speed */
|
||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_AN_FORCE_SPEED_REG,
|
||||
MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK,
|
||||
MTK_PHY_MASTER_FORCE_SPEED_SEL_EN |
|
||||
FIELD_PREP(MTK_PHY_MASTER_FORCE_SPEED_SEL_MASK, 0x1b));
|
||||
|
||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_RELATED,
|
||||
MTK_PHY_BYPASS_LINK_STATUS_OK |
|
||||
MTK_PHY_FORCE_LINK_STATUS_HCD);
|
||||
|
||||
/* Set xbz, pma and rx as "do not reset" in order to input DSP code. */
|
||||
pbus_rmw(priv, DO_NOT_RESET, 0,
|
||||
DO_NOT_RESET_XBZ | DO_NOT_RESET_PMA | DO_NOT_RESET_RX);
|
||||
|
||||
pbus_rmw(priv, SYS_SW_RESET, RESET_RST_CNT, 0);
|
||||
|
||||
pbus_write(priv, PMU_WP, WRITE_PROTECT_KEY);
|
||||
|
||||
pbus_rmw(priv, PMU_PMA_AUTO_CFG, 0,
|
||||
PMU_AUTO_MODE_EN | POWER_ON_AUTO_MODE);
|
||||
|
||||
/* Check if clock in auto mode is disabled. */
|
||||
ret = readl_poll_timeout(priv->reg_base + PMU_PMA_STATUS, reg,
|
||||
(reg & CLK_IS_DISABLED) == 0x0, 100000);
|
||||
if (ret)
|
||||
dev_err(phydev->dev, "Timed out enabling clock auto mode\n");
|
||||
|
||||
ret = mt7987_i2p5ge_download_dspfw(priv, dspfw);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
pbus_rmw(priv, MD32_EN_CFG, 0, MD32_EN);
|
||||
|
||||
phy_set_bits_mmd(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
|
||||
|
||||
/* We need a delay here to stabilize initialization of MCU */
|
||||
mdelay(8);
|
||||
|
||||
mt798x_i2p5ge_print_fw_info(fw, fw_size);
|
||||
|
||||
cleanup:
|
||||
if (fwrc > 0) {
|
||||
free(fw);
|
||||
free(dspfw);
|
||||
}
|
||||
|
||||
iounmap(apb_base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7987_i2p5ge_phy_config(struct phy_device *phydev)
|
||||
{
|
||||
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
|
||||
MTK_PHY_LED_ON_POLARITY);
|
||||
|
||||
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MT7987_OPTIONS,
|
||||
NORMAL_RETRAIN_DISABLE);
|
||||
|
||||
return mt798x_i2p5ge_phy_config(phydev);
|
||||
}
|
||||
|
||||
static int mt7987_i2p5ge_phy_probe(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt798x_i2p5ge_phy_probe(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7987_i2p5ge_phy_load_fw(phydev);
|
||||
}
|
||||
|
||||
int __weak mt7988_i2p5ge_get_fw(void **fw, size_t *size)
|
||||
{
|
||||
void *pmb;
|
||||
int ret;
|
||||
|
||||
pmb = malloc(MT7988_2P5GE_PMB_FW_SIZE);
|
||||
if (!pmb)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = request_firmware_into_buf_via_script(
|
||||
&pmb, MT7988_2P5GE_PMB_FW_SIZE,
|
||||
"mt7988_i2p5ge_load_pmb_firmware", size);
|
||||
if (ret) {
|
||||
free(pmb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*fw = pmb;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mt7988_i2p5ge_phy_load_fw(struct phy_device *phydev)
|
||||
{
|
||||
struct mtk_i2p5ge_priv *priv = phydev->priv;
|
||||
size_t fw_size;
|
||||
int ret, fwrc;
|
||||
void *fw;
|
||||
|
||||
fwrc = mt7988_i2p5ge_get_fw(&fw, &fw_size);
|
||||
if (fwrc < 0) {
|
||||
dev_err(phydev->dev, "Failed to get firmware data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fw_size != MT7988_2P5GE_PMB_FW_SIZE) {
|
||||
dev_err(phydev->dev, "Firmware size mismatch (0x%zx != 0x%x)\n",
|
||||
fw_size, MT7988_2P5GE_PMB_FW_SIZE);
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = mt798x_i2p5ge_download_fw(priv, MT7988_2P5GE_PMB_FW_SIZE, fw);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
pbus_rmw(priv, MD32_EN_CFG, MD32_EN, 0);
|
||||
pbus_rmw(priv, MD32_EN_CFG, 0, MD32_EN);
|
||||
|
||||
phy_set_bits_mmd(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
|
||||
|
||||
/* We need a delay here to stabilize initialization of MCU */
|
||||
mdelay(8);
|
||||
|
||||
mt798x_i2p5ge_print_fw_info(fw, fw_size);
|
||||
|
||||
cleanup:
|
||||
if (fwrc > 0)
|
||||
free(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt7988_i2p5ge_phy_config(struct phy_device *phydev)
|
||||
{
|
||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
|
||||
MTK_PHY_LED_ON_POLARITY);
|
||||
|
||||
return mt798x_i2p5ge_phy_config(phydev);
|
||||
}
|
||||
|
||||
static int mt7988_i2p5ge_phy_probe(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mt798x_i2p5ge_phy_probe(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt7988_i2p5ge_phy_load_fw(phydev);
|
||||
}
|
||||
|
||||
static int mt798x_i2p5ge_phy_startup(struct phy_device *phydev)
|
||||
{
|
||||
struct mtk_i2p5ge_priv *priv = phydev->priv;
|
||||
int ret;
|
||||
|
||||
ret = genphy_update_link(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Initialize speed/duplex */
|
||||
phydev->speed = SPEED_10;
|
||||
phydev->duplex = DUPLEX_HALF;
|
||||
|
||||
if (phydev->link) {
|
||||
ret = phy_read(phydev, MDIO_DEVAD_NONE, PHY_AUX_CTRL_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
|
||||
case PHY_AUX_SPD_10:
|
||||
phydev->speed = SPEED_10;
|
||||
break;
|
||||
|
||||
case PHY_AUX_SPD_100:
|
||||
phydev->speed = SPEED_100;
|
||||
break;
|
||||
|
||||
case PHY_AUX_SPD_1000:
|
||||
pbus_rmw(priv, FIFO_CTRL,
|
||||
TX_SFIFO_IDLE_CNT_MASK | TX_SFIFO_DEL_IPG_WM_MASK,
|
||||
FIELD_PREP(TX_SFIFO_IDLE_CNT_MASK, 0x1) |
|
||||
FIELD_PREP(TX_SFIFO_DEL_IPG_WM_MASK, 0x10));
|
||||
pbus_rmw(priv, MIN_IPG_NUM, LS_MIN_IPG_NUM_MASK,
|
||||
FIELD_PREP(LS_MIN_IPG_NUM_MASK, 0xa));
|
||||
pbus_rmw(priv, FC_LWM, TX_FC_LWM_MASK,
|
||||
FIELD_PREP(TX_FC_LWM_MASK, 0x340));
|
||||
phydev->speed = SPEED_1000;
|
||||
break;
|
||||
|
||||
case PHY_AUX_SPD_2500:
|
||||
phydev->speed = SPEED_2500;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* This PHY always operates in full duplex */
|
||||
phydev->duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_PHY_DRIVER(mt7987_i2p5ge) = {
|
||||
.name = "MediaTek MT7987 built-in 2.5GbE PHY",
|
||||
.uid = MTK_2P5GPHY_ID_MT7987,
|
||||
.mask = 0xfffffff0,
|
||||
.features = PHY_10G_FEATURES,
|
||||
.mmds = (MDIO_MMD_PCS | MDIO_MMD_AN | MDIO_MMD_VEND1 | MDIO_MMD_VEND2),
|
||||
.probe = &mt7987_i2p5ge_phy_probe,
|
||||
.config = &mt7987_i2p5ge_phy_config,
|
||||
.startup = &mt798x_i2p5ge_phy_startup,
|
||||
.shutdown = &genphy_shutdown,
|
||||
};
|
||||
|
||||
U_BOOT_PHY_DRIVER(mt7988_i2p5ge) = {
|
||||
.name = "MediaTek MT7988 built-in 2.5GbE PHY",
|
||||
.uid = MTK_2P5GPHY_ID_MT7988,
|
||||
.mask = 0xfffffff0,
|
||||
.features = PHY_10G_FEATURES,
|
||||
.mmds = (MDIO_MMD_PCS | MDIO_MMD_AN | MDIO_MMD_VEND1 | MDIO_MMD_VEND2),
|
||||
.probe = &mt7988_i2p5ge_phy_probe,
|
||||
.config = &mt7988_i2p5ge_phy_config,
|
||||
.startup = &mt798x_i2p5ge_phy_startup,
|
||||
.shutdown = &genphy_shutdown,
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2025 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Author: Sky Huang <SkyLake.Huang@mediatek.com>
|
||||
*/
|
||||
#include <dm/device_compat.h>
|
||||
#include <phy.h>
|
||||
|
||||
#include "mtk.h"
|
||||
|
||||
void mtk_phy_select_page(struct phy_device *phydev, int page)
|
||||
{
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MTK_EXT_PAGE_ACCESS, page);
|
||||
}
|
||||
|
||||
void mtk_phy_restore_page(struct phy_device *phydev)
|
||||
{
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MTK_EXT_PAGE_ACCESS,
|
||||
MTK_PHY_PAGE_STANDARD);
|
||||
}
|
||||
|
||||
/* Difference between functions with mtk_tr* and __mtk_tr* prefixes is
|
||||
* mtk_tr* functions: wrapped by page switching operations
|
||||
* __mtk_tr* functions: no page switching operations
|
||||
*/
|
||||
static void __mtk_tr_access(struct phy_device *phydev, bool read, u8 ch_addr,
|
||||
u8 node_addr, u8 data_addr)
|
||||
{
|
||||
u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */
|
||||
|
||||
if (read)
|
||||
tr_cmd |= BIT(13);
|
||||
|
||||
tr_cmd |= (((ch_addr & 0x3) << 11) |
|
||||
((node_addr & 0xf) << 7) |
|
||||
((data_addr & 0x3f) << 1));
|
||||
dev_dbg(phydev->dev, "tr_cmd: 0x%x\n", tr_cmd);
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 0x10, tr_cmd);
|
||||
}
|
||||
|
||||
static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u16 *tr_high, u16 *tr_low)
|
||||
{
|
||||
__mtk_tr_access(phydev, true, ch_addr, node_addr, data_addr);
|
||||
*tr_low = phy_read(phydev, MDIO_DEVAD_NONE, 0x11);
|
||||
*tr_high = phy_read(phydev, MDIO_DEVAD_NONE, 0x12);
|
||||
dev_dbg(phydev->dev, "tr_high read: 0x%x, tr_low read: 0x%x\n",
|
||||
*tr_high, *tr_low);
|
||||
}
|
||||
|
||||
u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr)
|
||||
{
|
||||
u16 tr_high;
|
||||
u16 tr_low;
|
||||
|
||||
mtk_phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||
__mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
|
||||
mtk_phy_restore_page(phydev);
|
||||
|
||||
return (tr_high << 16) | tr_low;
|
||||
}
|
||||
|
||||
static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 tr_data)
|
||||
{
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 0x11, tr_data & 0xffff);
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, 0x12, tr_data >> 16);
|
||||
dev_dbg(phydev->dev, "tr_high write: 0x%x, tr_low write: 0x%x\n",
|
||||
tr_data >> 16, tr_data & 0xffff);
|
||||
__mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);
|
||||
}
|
||||
|
||||
void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 mask, u32 set)
|
||||
{
|
||||
u32 tr_data;
|
||||
u16 tr_high;
|
||||
u16 tr_low;
|
||||
|
||||
__mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
|
||||
tr_data = (tr_high << 16) | tr_low;
|
||||
tr_data = (tr_data & ~mask) | set;
|
||||
__mtk_tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
|
||||
}
|
||||
|
||||
void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 mask, u32 set)
|
||||
{
|
||||
mtk_phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||
__mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, mask, set);
|
||||
mtk_phy_restore_page(phydev);
|
||||
}
|
||||
|
||||
void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 set)
|
||||
{
|
||||
__mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, 0, set);
|
||||
}
|
||||
|
||||
void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 clr)
|
||||
{
|
||||
__mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, clr, 0);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2025 MediaTek Inc. All Rights Reserved.
|
||||
*
|
||||
* Author: Sky Huang <SkyLake.Huang@mediatek.com>
|
||||
*
|
||||
* Common definition for Mediatek Ethernet PHYs
|
||||
*/
|
||||
|
||||
#ifndef _MTK_EPHY_H_
|
||||
#define _MTK_EPHY_H_
|
||||
|
||||
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||
#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||
#define MTK_PHY_PAGE_EXTENDED_1 0x0001
|
||||
#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14
|
||||
/* suprv_media_select_RefClk */
|
||||
#define MTK_PHY_LP_DETECTED_MASK GENMASK(7, 6)
|
||||
#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
|
||||
|
||||
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||
|
||||
/* Registers on Token Ring debug nodes */
|
||||
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x2 */
|
||||
#define AN_STATE_MASK GENMASK(22, 19)
|
||||
#define AN_STATE_SHIFT 19
|
||||
#define AN_STATE_TX_DISABLE 1
|
||||
|
||||
/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
|
||||
#define AN_NEW_LP_CNT_LIMIT_MASK GENMASK(23, 20)
|
||||
#define AUTO_NP_10XEN BIT(6)
|
||||
|
||||
/* Registers on MDIO_MMD_VEND1 */
|
||||
#define MTK_PHY_LINK_STATUS_MISC (0xa2)
|
||||
#define MTK_PHY_FINAL_SPEED_1000 BIT(3)
|
||||
|
||||
/* Registers on MDIO_MMD_VEND2 */
|
||||
#define MTK_PHY_LED0_ON_CTRL 0x24
|
||||
#define MTK_PHY_LED1_ON_CTRL 0x26
|
||||
#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0)
|
||||
#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0)
|
||||
#define MTK_PHY_LED_ON_LINK1000 BIT(0)
|
||||
#define MTK_PHY_LED_ON_LINK100 BIT(1)
|
||||
#define MTK_PHY_LED_ON_LINK10 BIT(2)
|
||||
#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
|
||||
#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
|
||||
#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
|
||||
#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
|
||||
#define MTK_PHY_LED_ON_LINK2500 BIT(7)
|
||||
#define MTK_PHY_LED_ON_POLARITY BIT(14)
|
||||
#define MTK_PHY_LED_ON_ENABLE BIT(15)
|
||||
|
||||
#define MTK_PHY_LED0_BLINK_CTRL 0x25
|
||||
#define MTK_PHY_LED1_BLINK_CTRL 0x27
|
||||
#define MTK_PHY_LED_BLINK_1000TX BIT(0)
|
||||
#define MTK_PHY_LED_BLINK_1000RX BIT(1)
|
||||
#define MTK_PHY_LED_BLINK_100TX BIT(2)
|
||||
#define MTK_PHY_LED_BLINK_100RX BIT(3)
|
||||
#define MTK_PHY_LED_BLINK_10TX BIT(4)
|
||||
#define MTK_PHY_LED_BLINK_10RX BIT(5)
|
||||
#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
|
||||
#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
|
||||
#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
|
||||
#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
|
||||
#define MTK_PHY_LED_BLINK_2500TX BIT(10)
|
||||
#define MTK_PHY_LED_BLINK_2500RX BIT(11)
|
||||
|
||||
#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \
|
||||
MTK_PHY_LED_ON_LINK100 | \
|
||||
MTK_PHY_LED_ON_LINK10)
|
||||
#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
|
||||
MTK_PHY_LED_BLINK_100RX | \
|
||||
MTK_PHY_LED_BLINK_10RX)
|
||||
#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
|
||||
MTK_PHY_LED_BLINK_100RX | \
|
||||
MTK_PHY_LED_BLINK_10RX)
|
||||
|
||||
#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \
|
||||
MTK_GPHY_LED_ON_SET)
|
||||
#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
|
||||
MTK_GPHY_LED_RX_BLINK_SET)
|
||||
#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
|
||||
MTK_GPHY_LED_TX_BLINK_SET)
|
||||
|
||||
#define MTK_PHY_LED_STATE_FORCE_ON 0
|
||||
#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
||||
#define MTK_PHY_LED_STATE_NETDEV 2
|
||||
|
||||
void mtk_phy_select_page(struct phy_device *phydev, int page);
|
||||
void mtk_phy_restore_page(struct phy_device *phydev);
|
||||
|
||||
u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr);
|
||||
void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 mask, u32 set);
|
||||
void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 mask, u32 set);
|
||||
void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 set);
|
||||
void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||
u8 data_addr, u32 clr);
|
||||
|
||||
#endif /* _MTK_EPHY_H_ */
|
||||
+3
-1
@@ -71,6 +71,7 @@ int get_fs_loader(struct udevice **dev);
|
||||
* @buf: Pointer to a pointer where the firmware buffer will be stored.
|
||||
* @max_size: Maximum allowed size for the firmware to be loaded.
|
||||
* @script_name: Name of the U-Boot script to execute for firmware loading.
|
||||
* @retsize: Return the actual firmware data size (optional).
|
||||
*
|
||||
* Executes a U-Boot script (@script_name) that loads firmware into
|
||||
* memory and sets the environment variables 'fw_addr' (address) and
|
||||
@@ -87,5 +88,6 @@ int get_fs_loader(struct udevice **dev);
|
||||
* Return: 0 on success, negative value on error.
|
||||
*/
|
||||
int request_firmware_into_buf_via_script(void **buf, size_t max_size,
|
||||
const char *script_name);
|
||||
const char *script_name,
|
||||
size_t *retsize);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user