mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge tag 'net-20251022' of https://source.denx.de/u-boot/custodians/u-boot-net
Pull request net-20251022 net: - airoha: improvements - Tighten a few more driver dependencies - designware: fix bitbang init error - phy: Make driver overloading get_phy_id depend on !COMPILE_TEST - phy: add paged PHY register accessors - make dhcp_run() common for NET and NET_LWIP - dwc_eth_ops: Correct check for FDT_64BIT - mediatek: mt7988: various fixup + MDIO detach - phy: aquantia: switch to use phy_get_ofnode(), fix bindings typo net-legacy: - bootp: Prevent buffer overflow to avoid leaking the RAM content - tftp: make TFTP ports unconditionally configurable misc: - uthreads: Make use of CONFIG_IS_ENABLED consistently
This commit is contained in:
@@ -179,7 +179,7 @@ config CALXEDA_XGMAC
|
||||
machines.
|
||||
|
||||
config DWC_ETH_XGMAC
|
||||
bool "Synopsys DWC Ethernet XGMAC device support"
|
||||
bool
|
||||
select PHYLIB
|
||||
help
|
||||
This driver supports the Synopsys Designware Ethernet XGMAC (10G
|
||||
@@ -190,7 +190,8 @@ config DWC_ETH_XGMAC_SOCFPGA
|
||||
bool "Synopsys DWC Ethernet XGMAC device support for SOCFPGA"
|
||||
select REGMAP
|
||||
select SYSCON
|
||||
depends on DWC_ETH_XGMAC
|
||||
select DWC_ETH_XGMAC
|
||||
depends on ARCH_SOCFPGA
|
||||
default y if TARGET_SOCFPGA_AGILEX5
|
||||
help
|
||||
The Synopsys Designware Ethernet XGMAC IP block with specific
|
||||
@@ -376,7 +377,7 @@ config ETH_DESIGNWARE_SOCFPGA
|
||||
select SYSCON
|
||||
select DW_ALTDESCRIPTOR
|
||||
bool "Altera SoCFPGA extras for Synopsys Designware Ethernet MAC"
|
||||
depends on ETH_DESIGNWARE
|
||||
depends on ARCH_SOCFPGA && ETH_DESIGNWARE
|
||||
help
|
||||
The Altera SoCFPGA requires additional configuration of the
|
||||
Altera system manager to correctly interface with the PHY.
|
||||
@@ -966,6 +967,9 @@ config TSEC_ENET
|
||||
This driver implements support for the (Enhanced) Three-Speed
|
||||
Ethernet Controller found on Freescale SoCs.
|
||||
|
||||
config MDIO_MT7531_MMIO
|
||||
bool
|
||||
|
||||
source "drivers/net/mtk_eth/Kconfig"
|
||||
|
||||
config HIFEMAC_ETH
|
||||
|
||||
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACB) += macb.o
|
||||
obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
|
||||
obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
|
||||
obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o
|
||||
obj-$(CONFIG_MDIO_MT7531_MMIO) += mdio-mt7531-mmio.o
|
||||
obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
|
||||
obj-$(CONFIG_MDIO_MUX_MESON_G12A) += mdio_mux_meson_g12a.o
|
||||
obj-$(CONFIG_MDIO_MUX_MESON_GXL) += mdio_mux_meson_gxl.o
|
||||
|
||||
@@ -449,14 +449,10 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
|
||||
RX_RING_SIZE_MASK,
|
||||
FIELD_PREP(RX_RING_SIZE_MASK, ndesc));
|
||||
|
||||
/*
|
||||
* See arht_eth_free_pkt() for the reasons used to fill
|
||||
* REG_RX_CPU_IDX(qid) register.
|
||||
*/
|
||||
airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
FIELD_PREP(RX_RING_THR_MASK, 0));
|
||||
airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, q->ndesc - 3));
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, q->ndesc - 1));
|
||||
airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
@@ -920,7 +916,6 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
|
||||
struct airoha_qdma *qdma = ð->qdma[0];
|
||||
struct airoha_queue *q;
|
||||
int qid;
|
||||
u16 prev, pprev;
|
||||
|
||||
if (!packet)
|
||||
return 0;
|
||||
@@ -930,22 +925,29 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
|
||||
|
||||
/*
|
||||
* Due to cpu cache issue the airoha_qdma_reset_rx_desc() function
|
||||
* will always touch 2 descriptors:
|
||||
* - if current descriptor is even, then the previous and the one
|
||||
* before previous descriptors will be touched (previous cacheline)
|
||||
* - if current descriptor is odd, then only current and previous
|
||||
* descriptors will be touched (current cacheline)
|
||||
* will always touch 2 descriptors placed on the same cacheline:
|
||||
* - if current descriptor is even, then current and next
|
||||
* descriptors will be touched
|
||||
* - if current descriptor is odd, then current and previous
|
||||
* descriptors will be touched
|
||||
*
|
||||
* Thus, to prevent possible destroying of rx queue, only (q->ndesc - 2)
|
||||
* descriptors might be used for packet receiving.
|
||||
* Thus, to prevent possible destroying of rx queue, we should:
|
||||
* - do nothing in the even descriptor case,
|
||||
* - utilize 2 descriptors (current and previous one) in the
|
||||
* odd descriptor case.
|
||||
*
|
||||
* WARNING: Observations shows that PKTBUFSRX must be even and
|
||||
* larger than 7 for reliable driver operations.
|
||||
*/
|
||||
prev = (q->head + q->ndesc - 1) % q->ndesc;
|
||||
pprev = (q->head + q->ndesc - 2) % q->ndesc;
|
||||
q->head = (q->head + 1) % q->ndesc;
|
||||
if (q->head & 0x01) {
|
||||
airoha_qdma_reset_rx_desc(q, q->head - 1);
|
||||
airoha_qdma_reset_rx_desc(q, q->head);
|
||||
|
||||
airoha_qdma_reset_rx_desc(q, prev);
|
||||
airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, pprev));
|
||||
airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head));
|
||||
}
|
||||
|
||||
q->head = (q->head + 1) % q->ndesc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -125,6 +125,16 @@ static int dw_mdio_reset(struct mii_dev *bus)
|
||||
|
||||
return __dw_mdio_reset(dev);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BITBANGMII)
|
||||
static int dw_bb_mdio_reset(struct mii_dev *bus)
|
||||
{
|
||||
struct dw_eth_dev *priv = bus->priv;
|
||||
|
||||
return __dw_mdio_reset(priv->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_DM_MDIO)
|
||||
@@ -348,7 +358,7 @@ static int dw_bb_mdio_init(const char *name, struct udevice *dev)
|
||||
bus->read = dw_bb_miiphy_read;
|
||||
bus->write = dw_bb_miiphy_write;
|
||||
#if CONFIG_IS_ENABLED(DM_GPIO)
|
||||
bus->reset = dw_mdio_reset;
|
||||
bus->reset = dw_bb_mdio_reset;
|
||||
#endif
|
||||
bus->priv = dwpriv;
|
||||
|
||||
|
||||
168
drivers/net/mdio-mt7531-mmio.c
Normal file
168
drivers/net/mdio-mt7531-mmio.c
Normal file
@@ -0,0 +1,168 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <dm.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <miiphy.h>
|
||||
|
||||
#define MT7531_PHY_IAC 0x701c
|
||||
#define MT7531_PHY_ACS_ST BIT(31)
|
||||
#define MT7531_MDIO_REG_ADDR_CL22 GENMASK(29, 25)
|
||||
#define MT7531_MDIO_DEV_ADDR MT7531_MDIO_REG_ADDR_CL22
|
||||
#define MT7531_MDIO_PHY_ADDR GENMASK(24, 20)
|
||||
#define MT7531_MDIO_CMD GENMASK(19, 18)
|
||||
#define MT7531_MDIO_CMD_READ_CL45 FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x3)
|
||||
#define MT7531_MDIO_CMD_READ_CL22 FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x2)
|
||||
#define MT7531_MDIO_CMD_WRITE FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x1)
|
||||
#define MT7531_MDIO_CMD_ADDR FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x0)
|
||||
#define MT7531_MDIO_ST GENMASK(17, 16)
|
||||
#define MT7531_MDIO_ST_CL22 FIELD_PREP_CONST(MT7531_MDIO_ST, 0x1)
|
||||
#define MT7531_MDIO_ST_CL45 FIELD_PREP_CONST(MT7531_MDIO_ST, 0x0)
|
||||
#define MT7531_MDIO_RW_DATA GENMASK(15, 0)
|
||||
#define MT7531_MDIO_REG_ADDR_CL45 MT7531_MDIO_RW_DATA
|
||||
|
||||
#define MT7531_MDIO_TIMEOUT 100000
|
||||
#define MT7531_MDIO_SLEEP 20
|
||||
|
||||
struct mt7531_mdio_priv {
|
||||
phys_addr_t switch_regs;
|
||||
};
|
||||
|
||||
static int mt7531_mdio_wait_busy(struct mt7531_mdio_priv *priv)
|
||||
{
|
||||
unsigned int busy;
|
||||
|
||||
return readl_poll_sleep_timeout(priv->switch_regs + MT7531_PHY_IAC,
|
||||
busy, (busy & MT7531_PHY_ACS_ST) == 0,
|
||||
MT7531_MDIO_SLEEP, MT7531_MDIO_TIMEOUT);
|
||||
}
|
||||
|
||||
static int mt7531_mdio_read(struct mt7531_mdio_priv *priv, int addr, int devad, int reg)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (devad != MDIO_DEVAD_NONE) {
|
||||
if (mt7531_mdio_wait_busy(priv))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
val = MT7531_PHY_ACS_ST |
|
||||
MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR |
|
||||
FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
|
||||
FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) |
|
||||
FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg);
|
||||
|
||||
writel(val, priv->switch_regs + MT7531_PHY_IAC);
|
||||
}
|
||||
|
||||
if (mt7531_mdio_wait_busy(priv))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr);
|
||||
if (devad != MDIO_DEVAD_NONE)
|
||||
val |= MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_READ_CL45 |
|
||||
FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad);
|
||||
else
|
||||
val |= MT7531_MDIO_ST_CL22 | MT7531_MDIO_CMD_READ_CL22 |
|
||||
FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg);
|
||||
|
||||
writel(val, priv->switch_regs + MT7531_PHY_IAC);
|
||||
|
||||
if (mt7531_mdio_wait_busy(priv))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
val = readl(priv->switch_regs + MT7531_PHY_IAC);
|
||||
return val & MT7531_MDIO_RW_DATA;
|
||||
}
|
||||
|
||||
static int mt7531_mdio_write(struct mt7531_mdio_priv *priv, int addr, int devad,
|
||||
int reg, u16 value)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (devad != MDIO_DEVAD_NONE) {
|
||||
if (mt7531_mdio_wait_busy(priv))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
val = MT7531_PHY_ACS_ST |
|
||||
MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR |
|
||||
FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
|
||||
FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) |
|
||||
FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg);
|
||||
|
||||
writel(val, priv->switch_regs + MT7531_PHY_IAC);
|
||||
}
|
||||
|
||||
if (mt7531_mdio_wait_busy(priv))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
|
||||
MT7531_MDIO_CMD_WRITE | FIELD_PREP(MT7531_MDIO_RW_DATA, value);
|
||||
if (devad != MDIO_DEVAD_NONE)
|
||||
val |= MT7531_MDIO_ST_CL45 |
|
||||
FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad);
|
||||
else
|
||||
val |= MT7531_MDIO_ST_CL22 |
|
||||
FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg);
|
||||
|
||||
writel(val, priv->switch_regs + MT7531_PHY_IAC);
|
||||
|
||||
if (mt7531_mdio_wait_busy(priv))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg)
|
||||
{
|
||||
struct mt7531_mdio_priv *priv = bus->priv;
|
||||
|
||||
return mt7531_mdio_read(priv, addr, devad, reg);
|
||||
}
|
||||
|
||||
int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad,
|
||||
int reg, u16 value)
|
||||
{
|
||||
struct mt7531_mdio_priv *priv = bus->priv;
|
||||
|
||||
return mt7531_mdio_write(priv, addr, devad, reg, value);
|
||||
}
|
||||
|
||||
static int dm_mt7531_mdio_read(struct udevice *dev, int addr, int devad, int reg)
|
||||
{
|
||||
struct mt7531_mdio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return mt7531_mdio_read(priv, addr, devad, reg);
|
||||
}
|
||||
|
||||
static int dm_mt7531_mdio_write(struct udevice *dev, int addr, int devad,
|
||||
int reg, u16 value)
|
||||
{
|
||||
struct mt7531_mdio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return mt7531_mdio_write(priv, addr, devad, reg, value);
|
||||
}
|
||||
|
||||
static const struct mdio_ops mt7531_mdio_ops = {
|
||||
.read = dm_mt7531_mdio_read,
|
||||
.write = dm_mt7531_mdio_write,
|
||||
};
|
||||
|
||||
static int mt7531_mdio_probe(struct udevice *dev)
|
||||
{
|
||||
struct mt7531_mdio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->switch_regs = dev_read_addr(dev);
|
||||
if (priv->switch_regs == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(mt7531_mdio) = {
|
||||
.name = "mt7531-mdio-mmio",
|
||||
.id = UCLASS_MDIO,
|
||||
.probe = mt7531_mdio_probe,
|
||||
.ops = &mt7531_mdio_ops,
|
||||
.priv_auto = sizeof(struct mt7531_mdio_priv),
|
||||
};
|
||||
9
drivers/net/mdio-mt7531-mmio.h
Normal file
9
drivers/net/mdio-mt7531-mmio.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
struct mt7531_mdio_mmio_priv {
|
||||
phys_addr_t switch_regs;
|
||||
};
|
||||
|
||||
int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg);
|
||||
int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad,
|
||||
int reg, u16 value);
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
config MEDIATEK_ETH
|
||||
bool "MediaTek Ethernet GMAC Driver"
|
||||
depends on ARCH_MEDIATEK || ARCH_MTMIPS
|
||||
select PHYLIB
|
||||
select DM_GPIO
|
||||
select DM_RESET
|
||||
@@ -30,6 +31,7 @@ config MTK_ETH_SWITCH_MT7531
|
||||
config MTK_ETH_SWITCH_MT7988
|
||||
bool "Support for MediaTek MT7988 built-in ethernet switch"
|
||||
depends on TARGET_MT7988
|
||||
select MDIO_MT7531_MMIO
|
||||
default y
|
||||
|
||||
config MTK_ETH_SWITCH_AN8855
|
||||
|
||||
@@ -22,17 +22,13 @@
|
||||
|
||||
static int mt7531_core_reg_read(struct mt753x_switch_priv *priv, u32 reg)
|
||||
{
|
||||
u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
|
||||
|
||||
return mt7531_mmd_read(priv, phy_addr, 0x1f, reg);
|
||||
return mt7531_mmd_read(priv, 0, 0x1f, reg);
|
||||
}
|
||||
|
||||
static void mt7531_core_reg_write(struct mt753x_switch_priv *priv, u32 reg,
|
||||
u32 val)
|
||||
{
|
||||
u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
|
||||
|
||||
mt7531_mmd_write(priv, phy_addr, 0x1f, reg, val);
|
||||
mt7531_mmd_write(priv, 0, 0x1f, reg, val);
|
||||
}
|
||||
|
||||
static void mt7531_core_pll_setup(struct mt753x_switch_priv *priv)
|
||||
@@ -171,7 +167,7 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
|
||||
{
|
||||
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
|
||||
u32 i, val, pmcr, port5_sgmii;
|
||||
u16 phy_addr, phy_val;
|
||||
u16 phy_val;
|
||||
|
||||
priv->smi_addr = MT753X_DFL_SMI_ADDR;
|
||||
priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
|
||||
@@ -180,10 +176,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
|
||||
|
||||
/* Turn off PHYs */
|
||||
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||
phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
|
||||
phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
|
||||
phy_val = mt7531_mii_read(priv, i, MII_BMCR);
|
||||
phy_val |= BMCR_PDOWN;
|
||||
mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
|
||||
mt7531_mii_write(priv, i, MII_BMCR, phy_val);
|
||||
}
|
||||
|
||||
/* Force MAC link down before reset */
|
||||
@@ -239,10 +234,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
|
||||
|
||||
/* Turn on PHYs */
|
||||
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||
phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
|
||||
phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
|
||||
phy_val = mt7531_mii_read(priv, i, MII_BMCR);
|
||||
phy_val &= ~BMCR_PDOWN;
|
||||
mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
|
||||
mt7531_mii_write(priv, i, MII_BMCR, phy_val);
|
||||
}
|
||||
|
||||
mt7531_phy_setting(priv);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* Author: Mark Lee <mark-mc.lee@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <miiphy.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mdio.h>
|
||||
@@ -14,6 +15,8 @@
|
||||
#include "mtk_eth.h"
|
||||
#include "mt753x.h"
|
||||
|
||||
#include "../mdio-mt7531-mmio.h"
|
||||
|
||||
static int mt7988_reg_read(struct mt753x_switch_priv *priv, u32 reg, u32 *data)
|
||||
{
|
||||
*data = readl(priv->epriv.ethsys_base + GSW_BASE + reg);
|
||||
@@ -30,20 +33,34 @@ static int mt7988_reg_write(struct mt753x_switch_priv *priv, u32 reg, u32 data)
|
||||
|
||||
static void mt7988_phy_setting(struct mt753x_switch_priv *priv)
|
||||
{
|
||||
struct mii_dev *mdio_bus = priv->mdio_bus;
|
||||
u16 val;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||
u16 addr = MT753X_PHY_ADDR(priv->phy_base, i);
|
||||
|
||||
/* Set PHY to PHY page 1 */
|
||||
mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
|
||||
0x1f, 0x1);
|
||||
|
||||
/* Enable HW auto downshift */
|
||||
mt7531_mii_write(priv, i, 0x1f, 0x1);
|
||||
val = mt7531_mii_read(priv, i, PHY_EXT_REG_14);
|
||||
val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE,
|
||||
PHY_EXT_REG_14);
|
||||
val |= PHY_EN_DOWN_SHFIT;
|
||||
mt7531_mii_write(priv, i, PHY_EXT_REG_14, val);
|
||||
mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
|
||||
PHY_EXT_REG_14, val);
|
||||
|
||||
/* PHY link down power saving enable */
|
||||
val = mt7531_mii_read(priv, i, PHY_EXT_REG_17);
|
||||
val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE,
|
||||
PHY_EXT_REG_17);
|
||||
val |= PHY_LINKDOWN_POWER_SAVING_EN;
|
||||
mt7531_mii_write(priv, i, PHY_EXT_REG_17, val);
|
||||
mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
|
||||
PHY_EXT_REG_17, val);
|
||||
|
||||
/* Restore PHY to PHY page 0 */
|
||||
mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
|
||||
0x1f, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,24 +75,66 @@ static void mt7988_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable)
|
||||
mt7988_reg_write(priv, PMCR_REG(6), pmcr);
|
||||
}
|
||||
|
||||
static int mt7988_mdio_register(struct mt753x_switch_priv *priv)
|
||||
{
|
||||
struct mt7531_mdio_mmio_priv *mdio_priv;
|
||||
struct mii_dev *mdio_bus = mdio_alloc();
|
||||
int ret;
|
||||
|
||||
if (!mdio_bus)
|
||||
return -ENOMEM;
|
||||
|
||||
mdio_priv = malloc(sizeof(*mdio_priv));
|
||||
if (!mdio_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
mdio_priv->switch_regs = (phys_addr_t)priv->epriv.ethsys_base + GSW_BASE;
|
||||
|
||||
mdio_bus->read = mt7531_mdio_mmio_read;
|
||||
mdio_bus->write = mt7531_mdio_mmio_write;
|
||||
snprintf(mdio_bus->name, sizeof(mdio_bus->name), priv->epriv.sw->name);
|
||||
|
||||
mdio_bus->priv = mdio_priv;
|
||||
|
||||
ret = mdio_register(mdio_bus);
|
||||
if (ret) {
|
||||
free(mdio_bus->priv);
|
||||
mdio_free(mdio_bus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->mdio_bus = mdio_bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
|
||||
{
|
||||
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
|
||||
struct mii_dev *mdio_bus;
|
||||
u16 phy_addr, phy_val;
|
||||
int ret, i;
|
||||
u32 pmcr;
|
||||
int i;
|
||||
|
||||
priv->smi_addr = MT753X_DFL_SMI_ADDR;
|
||||
priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
|
||||
priv->reg_read = mt7988_reg_read;
|
||||
priv->reg_write = mt7988_reg_write;
|
||||
|
||||
ret = mt7988_mdio_register(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdio_bus = priv->mdio_bus;
|
||||
|
||||
/* Turn off PHYs */
|
||||
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||
phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
|
||||
phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
|
||||
phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr,
|
||||
MDIO_DEVAD_NONE, MII_BMCR);
|
||||
phy_val |= BMCR_PDOWN;
|
||||
mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
|
||||
mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE,
|
||||
MII_BMCR, phy_val);
|
||||
}
|
||||
|
||||
switch (priv->epriv.phy_interface) {
|
||||
@@ -129,21 +188,26 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
|
||||
/* Turn on PHYs */
|
||||
for (i = 0; i < MT753X_NUM_PHYS; i++) {
|
||||
phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
|
||||
phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
|
||||
phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr,
|
||||
MDIO_DEVAD_NONE, MII_BMCR);
|
||||
phy_val &= ~BMCR_PDOWN;
|
||||
mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
|
||||
mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE,
|
||||
MII_BMCR, phy_val);
|
||||
}
|
||||
|
||||
mt7988_phy_setting(priv);
|
||||
|
||||
return mt7531_mdio_register(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7531_cleanup(struct mtk_eth_switch_priv *swpriv)
|
||||
static int mt7988_cleanup(struct mtk_eth_switch_priv *swpriv)
|
||||
{
|
||||
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
|
||||
struct mii_dev *mdio_bus = priv->mdio_bus;
|
||||
|
||||
mdio_unregister(priv->mdio_bus);
|
||||
mdio_unregister(mdio_bus);
|
||||
free(mdio_bus->priv);
|
||||
mdio_free(mdio_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -155,6 +219,6 @@ MTK_ETH_SWITCH(mt7988) = {
|
||||
.reset_wait_time = 50,
|
||||
|
||||
.setup = mt7988_setup,
|
||||
.cleanup = mt7531_cleanup,
|
||||
.cleanup = mt7988_cleanup,
|
||||
.mac_control = mt7988_mac_control,
|
||||
};
|
||||
|
||||
@@ -56,6 +56,7 @@ endif # B53_SWITCH
|
||||
|
||||
config MV88E61XX_SWITCH
|
||||
bool "Marvell MV88E61xx Ethernet switch PHY support."
|
||||
depends on !COMPILE_TEST
|
||||
|
||||
if MV88E61XX_SWITCH
|
||||
|
||||
@@ -119,6 +120,7 @@ config PHY_BROADCOM
|
||||
|
||||
config PHY_CORTINA
|
||||
bool "Cortina Ethernet PHYs support"
|
||||
depends on !COMPILE_TEST
|
||||
|
||||
config SYS_CORTINA_NO_FW_UPLOAD
|
||||
bool "Cortina firmware loading support"
|
||||
|
||||
@@ -338,7 +338,7 @@ static int aquantia_set_proto(struct phy_device *phydev,
|
||||
|
||||
static int aquantia_dts_config(struct phy_device *phydev)
|
||||
{
|
||||
ofnode node = phydev->node;
|
||||
ofnode node = phy_get_ofnode(phydev);
|
||||
u32 prop;
|
||||
u16 reg;
|
||||
|
||||
|
||||
@@ -1250,3 +1250,116 @@ bool phy_interface_is_ncsi(void)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* __phy_read_page() - read the current page
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
*
|
||||
* Returns page index or < 0 on error
|
||||
*/
|
||||
static int __phy_read_page(struct phy_device *phydev)
|
||||
{
|
||||
struct phy_driver *drv = phydev->drv;
|
||||
|
||||
if (!drv->read_page) {
|
||||
debug("read_page callback not available, PHY driver not loaded?\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return drv->read_page(phydev);
|
||||
}
|
||||
|
||||
/**
|
||||
* __phy_write_page() - Write a new page
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @page: page index to select
|
||||
*
|
||||
* Returns 0 or < 0 on error.
|
||||
*/
|
||||
static int __phy_write_page(struct phy_device *phydev, int page)
|
||||
{
|
||||
struct phy_driver *drv = phydev->drv;
|
||||
|
||||
if (!drv->write_page) {
|
||||
debug("write_page callback not available, PHY driver not loaded?\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return drv->write_page(phydev, page);
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_save_page() - save the current page
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
*
|
||||
* Return the current page number. On error,
|
||||
* returns a negative errno. phy_restore_page() must always be called
|
||||
* after this, irrespective of success or failure of this call.
|
||||
*/
|
||||
int phy_save_page(struct phy_device *phydev)
|
||||
{
|
||||
return __phy_read_page(phydev);
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_select_page - Switch to a PHY page and return the previous page
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @page: desired page
|
||||
*
|
||||
* NOTE: Save the current PHY page, and set the current page.
|
||||
* On error, returns a negative errno, otherwise returns the previous page number.
|
||||
* phy_restore_page() must always be called after this, irrespective
|
||||
* of success or failure of this call.
|
||||
*/
|
||||
int phy_select_page(struct phy_device *phydev, int page)
|
||||
{
|
||||
int ret, oldpage;
|
||||
|
||||
oldpage = ret = phy_save_page(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (oldpage != page) {
|
||||
ret = __phy_write_page(phydev, page);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return oldpage;
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_restore_page - Restore a previously saved page and propagate status
|
||||
* @phydev: a pointer to a &struct phy_device
|
||||
* @oldpage: the old page, return value from phy_save_page() or phy_select_page()
|
||||
* @ret: operation's return code
|
||||
*
|
||||
* Restoring @oldpage if it is a valid page.
|
||||
* This function propagates the earliest error code from the group of
|
||||
* operations.
|
||||
*
|
||||
* Returns:
|
||||
* @oldpage if it was a negative value, otherwise
|
||||
* @ret if it was a negative errno value, otherwise
|
||||
* phy_write_page()'s negative value if it were in error, otherwise
|
||||
* @ret.
|
||||
*/
|
||||
int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (oldpage >= 0) {
|
||||
r = __phy_write_page(phydev, oldpage);
|
||||
|
||||
/* Propagate the operation return code if the page write
|
||||
* was successful.
|
||||
*/
|
||||
if (ret >= 0 && r < 0)
|
||||
ret = r;
|
||||
} else {
|
||||
/* Propagate the phy page selection error code */
|
||||
ret = oldpage;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ config APPLE_PMGR_POWER_DOMAIN
|
||||
|
||||
config AGILEX5_PMGR_POWER_DOMAIN
|
||||
bool "Enable the Agilex5 PMGR power domain driver"
|
||||
depends on SPL_POWER_DOMAIN
|
||||
depends on SPL_POWER_DOMAIN && TARGET_SOCFPGA_SOC64
|
||||
help
|
||||
Enable support for power gating peripherals' SRAM specified in
|
||||
the handoff data values obtained from the bitstream to reduce
|
||||
|
||||
Reference in New Issue
Block a user