mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-16 09:54:35 +00:00
Merge branch '2024-03-28-assorted-net-changes' into next
- A few ncsi PHY fixes, clean up PHY GPIO reset code, support LEDs on BCM54210E PHY, fix a signed shift overflow in the PHY code, hifemac updates, E1000 i225-IT support, improve DM_MDIO+DM_PHY support and enable it on the BeaglePlay platform.
This commit is contained in:
commit
7761226e6a
12 changed files with 357 additions and 87 deletions
|
@ -88,9 +88,9 @@ CONFIG_SPL_MMC_SDHCI_ADMA=y
|
|||
CONFIG_MMC_SDHCI_AM654=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_PHY_TI=y
|
||||
CONFIG_PHY_FIXED=y
|
||||
CONFIG_TI_AM65_CPSW_NUSS=y
|
||||
CONFIG_PHY=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPL_PINCTRL=y
|
||||
CONFIG_PINCTRL_SINGLE=y
|
||||
|
|
|
@ -116,6 +116,8 @@ static struct pci_device_id e1000_supported[] = {
|
|||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I210_1000BASEKX) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I225_IT) },
|
||||
|
||||
{}
|
||||
};
|
||||
|
@ -1575,6 +1577,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
|
|||
case PCI_DEVICE_ID_INTEL_I210_SERDES:
|
||||
case PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS:
|
||||
case PCI_DEVICE_ID_INTEL_I210_1000BASEKX:
|
||||
case PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED:
|
||||
case PCI_DEVICE_ID_INTEL_I225_IT:
|
||||
hw->mac_type = e1000_igb;
|
||||
break;
|
||||
default:
|
||||
|
@ -3258,7 +3262,8 @@ e1000_setup_copper_link(struct e1000_hw *hw)
|
|||
if (ret_val)
|
||||
return ret_val;
|
||||
} else if (hw->phy_type == e1000_phy_m88 ||
|
||||
hw->phy_type == e1000_phy_igb) {
|
||||
hw->phy_type == e1000_phy_igb ||
|
||||
hw->phy_type == e1000_phy_igc) {
|
||||
ret_val = e1000_copper_link_mgp_setup(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
@ -4531,6 +4536,8 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
|
|||
case e1000_igb:
|
||||
while (timeout) {
|
||||
if (hw->mac_type == e1000_igb) {
|
||||
if (hw->phy_type == e1000_phy_igc)
|
||||
break;
|
||||
if (E1000_READ_REG(hw, I210_EEMNGCTL) & cfg_mask)
|
||||
break;
|
||||
} else {
|
||||
|
@ -4769,6 +4776,7 @@ e1000_phy_reset(struct e1000_hw *hw)
|
|||
case e1000_phy_igp_3:
|
||||
case e1000_phy_ife:
|
||||
case e1000_phy_igb:
|
||||
case e1000_phy_igc:
|
||||
ret_val = e1000_phy_hw_reset(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
@ -4834,6 +4842,9 @@ static int e1000_set_phy_type (struct e1000_hw *hw)
|
|||
case I210_I_PHY_ID:
|
||||
hw->phy_type = e1000_phy_igb;
|
||||
break;
|
||||
case I225_I_PHY_ID:
|
||||
hw->phy_type = e1000_phy_igc;
|
||||
break;
|
||||
/* Fall Through */
|
||||
default:
|
||||
/* Should never have loaded on this device */
|
||||
|
@ -4941,6 +4952,8 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
|
|||
case e1000_igb:
|
||||
if (hw->phy_id == I210_I_PHY_ID)
|
||||
match = true;
|
||||
if (hw->phy_id == I225_I_PHY_ID)
|
||||
match = true;
|
||||
break;
|
||||
default:
|
||||
DEBUGOUT("Invalid MAC type %d\n", hw->mac_type);
|
||||
|
|
|
@ -212,6 +212,7 @@ typedef enum {
|
|||
e1000_phy_igp_3,
|
||||
e1000_phy_ife,
|
||||
e1000_phy_igb,
|
||||
e1000_phy_igc,
|
||||
e1000_phy_bm,
|
||||
e1000_phy_undefined = 0xFF
|
||||
} e1000_phy_type;
|
||||
|
@ -2420,6 +2421,7 @@ struct e1000_hw {
|
|||
#define BME1000_E_PHY_ID 0x01410CB0
|
||||
|
||||
#define I210_I_PHY_ID 0x01410C00
|
||||
#define I225_I_PHY_ID 0x67C9DCC0
|
||||
|
||||
/* Miscellaneous PHY bit definitions. */
|
||||
#define PHY_PREAMBLE 0xFFFFFFFF
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include <wait_bit.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
|
@ -124,6 +127,57 @@ struct hisi_femac_priv {
|
|||
u32 link_status;
|
||||
};
|
||||
|
||||
struct hisi_femac_stat_entry {
|
||||
const char *name;
|
||||
u32 offset;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
/* please refer to the datasheet for the description of these entries */
|
||||
static const struct hisi_femac_stat_entry hisi_femac_stats_table[] = {
|
||||
{ "rxsof_cnt", 0x584, GENMASK(31, 28) },
|
||||
{ "rxeof_cnt", 0x584, GENMASK(27, 24) },
|
||||
{ "rxcrcok_cnt", 0x584, GENMASK(23, 20) },
|
||||
{ "rxcrcbad_cnt", 0x584, GENMASK(19, 16) },
|
||||
{ "txsof_cnt", 0x584, GENMASK(15, 12) },
|
||||
{ "txeof_cnt", 0x584, GENMASK(11, 8) },
|
||||
{ "txcrcok_cnt", 0x584, GENMASK(7, 4) },
|
||||
{ "txcrcbad_cnt", 0x584, GENMASK(3, 0) },
|
||||
{ "pkts_cpu", 0x5a0, GENMASK(15, 0) },
|
||||
{ "addr_cpu", 0x5a4, GENMASK(15, 0) },
|
||||
{ "pkts_port", 0x5a8, GENMASK(15, 0) },
|
||||
{ "pkts_cpu2tx", 0x5ac, GENMASK(15, 0) },
|
||||
{ "rxdvrise", 0x600, GENMASK(31, 0) },
|
||||
{ "ifinoctets", 0x604, GENMASK(31, 0) },
|
||||
{ "octets_rx", 0x608, GENMASK(31, 0) },
|
||||
{ "local_mac_match", 0x60c, GENMASK(31, 0) },
|
||||
{ "pkts", 0x610, GENMASK(31, 0) },
|
||||
{ "broadcastpkts", 0x614, GENMASK(31, 0) },
|
||||
{ "multicastpkts", 0x618, GENMASK(31, 0) },
|
||||
{ "ifinucastpkts", 0x61c, GENMASK(31, 0) },
|
||||
{ "ifinerrors", 0x620, GENMASK(31, 0) },
|
||||
{ "crcerr", 0x624, GENMASK(31, 0) },
|
||||
{ "abnormalsizepkts", 0x628, GENMASK(31, 0) },
|
||||
{ "dot3alignmenterr", 0x62c, GENMASK(31, 0) },
|
||||
{ "dot3pause", 0x630, GENMASK(31, 0) },
|
||||
{ "dropevents", 0x634, GENMASK(31, 0) },
|
||||
{ "flux_frame_cnt", 0x638, GENMASK(31, 0) },
|
||||
{ "flux_drop_cnt", 0x63c, GENMASK(31, 0) },
|
||||
{ "mac_not2cpu_pkts", 0x64c, GENMASK(31, 0) },
|
||||
{ "pkts_tx", 0x780, GENMASK(31, 0) },
|
||||
{ "broadcastpkts_tx", 0x784, GENMASK(31, 0) },
|
||||
{ "multicastpkts_tx", 0x788, GENMASK(31, 0) },
|
||||
{ "ifoutucastpkts_tx", 0x78c, GENMASK(31, 0) },
|
||||
{ "octets_tx", 0x790, GENMASK(31, 0) },
|
||||
{ "dot3pause", 0x794, GENMASK(31, 0) },
|
||||
{ "retry_times_tx", 0x798, GENMASK(31, 0) },
|
||||
{ "collisions", 0x79c, GENMASK(31, 0) },
|
||||
{ "dot3latecol", 0x7a0, GENMASK(31, 0) },
|
||||
{ "dot3colok", 0x7a4, GENMASK(31, 0) },
|
||||
{ "dot3excessivecol", 0x7a8, GENMASK(31, 0) },
|
||||
{ "dot3colcnt", 0x7ac, GENMASK(31, 0) },
|
||||
};
|
||||
|
||||
static void hisi_femac_irq_enable(struct hisi_femac_priv *priv, int irqs)
|
||||
{
|
||||
u32 val;
|
||||
|
@ -245,8 +299,10 @@ static int hisi_femac_start(struct udevice *dev)
|
|||
hisi_femac_rx_refill(priv);
|
||||
|
||||
ret = phy_startup(priv->phy);
|
||||
if (ret)
|
||||
return log_msg_ret("Failed to startup phy", ret);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to startup phy: %d\n", ret);
|
||||
return log_msg_ret("phy", ret);
|
||||
}
|
||||
|
||||
if (!priv->phy->link) {
|
||||
debug("%s: link down\n", __func__);
|
||||
|
@ -281,8 +337,10 @@ static int hisi_femac_send(struct udevice *dev, void *packet, int length)
|
|||
|
||||
// wait until FIFO is empty
|
||||
ret = wait_for_bit_le32(priv->glb_base + GLB_IRQ_RAW, IRQ_INT_TX_PER_PACKET, true, 50, false);
|
||||
if (ret == -ETIMEDOUT)
|
||||
return log_msg_ret("FIFO timeout", ret);
|
||||
if (ret == -ETIMEDOUT) {
|
||||
dev_err(dev, "FIFO timeout\n");
|
||||
return log_msg_ret("net", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -329,10 +387,43 @@ static void hisi_femac_stop(struct udevice *dev)
|
|||
writel(SOFT_RESET_ALL, priv->glb_base + GLB_SOFT_RESET);
|
||||
}
|
||||
|
||||
int hisi_femac_of_to_plat(struct udevice *dev)
|
||||
static int hisi_femac_get_sset_count(struct udevice *dev)
|
||||
{
|
||||
return ARRAY_SIZE(hisi_femac_stats_table);
|
||||
}
|
||||
|
||||
static void hisi_femac_get_strings(struct udevice *dev, u8 *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++)
|
||||
strcpy(data + i * ETH_GSTRING_LEN, hisi_femac_stats_table[i].name);
|
||||
}
|
||||
|
||||
/* Non-constant mask variant of FIELD_GET/FIELD_PREP */
|
||||
#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
|
||||
|
||||
static void hisi_femac_get_stats(struct udevice *dev, u64 *data)
|
||||
{
|
||||
int i;
|
||||
u32 mask, reg;
|
||||
struct hisi_femac_priv *priv = dev_get_priv(dev);
|
||||
void __iomem *port_base = priv->port_base;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hisi_femac_stats_table); i++) {
|
||||
mask = hisi_femac_stats_table[i].mask;
|
||||
reg = readl(port_base + hisi_femac_stats_table[i].offset);
|
||||
|
||||
data[i] = field_get(mask, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int hisi_femac_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
int ret, i;
|
||||
struct hisi_femac_priv *priv = dev_get_priv(dev);
|
||||
ofnode mdio_node;
|
||||
bool mdio_registered = false;
|
||||
static const char * const clk_strs[] = {
|
||||
[CLK_MAC] = "mac",
|
||||
[CLK_BUS] = "bus",
|
||||
|
@ -340,40 +431,75 @@ int hisi_femac_of_to_plat(struct udevice *dev)
|
|||
};
|
||||
|
||||
priv->port_base = dev_remap_addr_name(dev, "port");
|
||||
if (IS_ERR(priv->port_base))
|
||||
return log_msg_ret("Failed to remap port address space", PTR_ERR(priv->port_base));
|
||||
if (!priv->port_base) {
|
||||
dev_err(dev, "Failed to remap port address space\n");
|
||||
return log_msg_ret("net", -EINVAL);
|
||||
}
|
||||
|
||||
priv->glb_base = dev_remap_addr_name(dev, "glb");
|
||||
if (IS_ERR(priv->glb_base))
|
||||
return log_msg_ret("Failed to remap global address space", PTR_ERR(priv->glb_base));
|
||||
if (IS_ERR(priv->glb_base)) {
|
||||
dev_err(dev, "Failed to remap global address space\n");
|
||||
return log_msg_ret("net", -EINVAL);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clk_strs); i++) {
|
||||
priv->clks[i] = devm_clk_get(dev, clk_strs[i]);
|
||||
if (IS_ERR(priv->clks[i])) {
|
||||
dev_err(dev, "Error getting clock %s\n", clk_strs[i]);
|
||||
return log_msg_ret("Failed to get clocks", PTR_ERR(priv->clks[i]));
|
||||
return log_msg_ret("clk", PTR_ERR(priv->clks[i]));
|
||||
}
|
||||
}
|
||||
|
||||
priv->mac_rst = devm_reset_control_get(dev, "mac");
|
||||
if (IS_ERR(priv->mac_rst))
|
||||
return log_msg_ret("Failed to get MAC reset", PTR_ERR(priv->mac_rst));
|
||||
if (IS_ERR(priv->mac_rst)) {
|
||||
dev_err(dev, "Failed to get MAC reset %ld\n", PTR_ERR(priv->mac_rst));
|
||||
return log_msg_ret("rst", PTR_ERR(priv->mac_rst));
|
||||
}
|
||||
|
||||
priv->phy_rst = devm_reset_control_get(dev, "phy");
|
||||
if (IS_ERR(priv->phy_rst))
|
||||
return log_msg_ret("Failed to get PHY reset", PTR_ERR(priv->phy_rst));
|
||||
if (IS_ERR(priv->phy_rst)) {
|
||||
dev_err(dev, "Failed to get PHY reset %ld\n", PTR_ERR(priv->phy_rst));
|
||||
return log_msg_ret("rst", PTR_ERR(priv->phy_rst));
|
||||
}
|
||||
|
||||
ret = dev_read_u32_array(dev,
|
||||
PHY_RESET_DELAYS_PROPERTY,
|
||||
priv->phy_reset_delays,
|
||||
DELAYS_NUM);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to get PHY reset delays", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to get PHY reset delays %d\n", ret);
|
||||
return log_msg_ret("rst", ret);
|
||||
}
|
||||
|
||||
priv->mac_reset_delay = dev_read_u32_default(dev,
|
||||
MAC_RESET_DELAY_PROPERTY,
|
||||
MAC_RESET_ASSERT_PERIOD);
|
||||
|
||||
/* Create MDIO bus */
|
||||
ofnode_for_each_subnode(mdio_node, dev_ofnode(dev)) {
|
||||
const char *subnode_name = ofnode_get_name(mdio_node);
|
||||
struct udevice *mdiodev;
|
||||
|
||||
// Skip subnodes not starting with "mdio"
|
||||
if (strncmp(subnode_name, "mdio", 4))
|
||||
continue;
|
||||
|
||||
ret = device_bind_driver_to_node(dev, "hisi-femac-mdio",
|
||||
subnode_name, mdio_node, &mdiodev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register MDIO bus device %d\n", ret);
|
||||
return log_msg_ret("net", ret);
|
||||
}
|
||||
|
||||
mdio_registered = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mdio_registered) {
|
||||
dev_err(dev, "No MDIO subnode is found!\n");
|
||||
return log_msg_ret("mdio", -ENODATA);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -385,37 +511,49 @@ static int hisi_femac_phy_reset(struct hisi_femac_priv *priv)
|
|||
|
||||
// Disable MAC clk before phy reset
|
||||
ret = clk_disable(priv->clks[CLK_MAC]);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to disable MAC clock", ret);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to disable MAC clock %d\n", __func__, ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
ret = clk_disable(priv->clks[CLK_BUS]);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to disable bus clock", ret);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to disable bus clock %d\n", __func__, ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
udelay(delays[PRE_DELAY]);
|
||||
|
||||
ret = reset_assert(rst);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to assert reset", ret);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to assert reset %d\n", __func__, ret);
|
||||
return log_msg_ret("rst", ret);
|
||||
}
|
||||
|
||||
udelay(delays[PULSE]);
|
||||
|
||||
ret = reset_deassert(rst);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to deassert reset", ret);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to deassert reset %d\n", __func__, ret);
|
||||
return log_msg_ret("rst", ret);
|
||||
}
|
||||
|
||||
udelay(delays[POST_DELAY]);
|
||||
|
||||
ret = clk_enable(priv->clks[CLK_MAC]);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to enable MAC clock", ret);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to enable MAC clock %d\n", __func__, ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
ret = clk_enable(priv->clks[CLK_BUS]);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to enable MAC bus clock", ret);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Failed to enable MAC bus clock %d\n", __func__, ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hisi_femac_probe(struct udevice *dev)
|
||||
static int hisi_femac_probe(struct udevice *dev)
|
||||
{
|
||||
struct hisi_femac_priv *priv = dev_get_priv(dev);
|
||||
int ret, i;
|
||||
|
@ -423,30 +561,40 @@ int hisi_femac_probe(struct udevice *dev)
|
|||
// Enable clocks
|
||||
for (i = 0; i < CLK_NUM; i++) {
|
||||
ret = clk_prepare_enable(priv->clks[i]);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to enable clks", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enable clk %d: %d\n", i, ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset MAC
|
||||
ret = reset_assert(priv->mac_rst);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to assert MAC reset", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to assert MAC reset: %d\n", ret);
|
||||
return log_msg_ret("net", ret);
|
||||
}
|
||||
|
||||
udelay(priv->mac_reset_delay);
|
||||
|
||||
ret = reset_deassert(priv->mac_rst);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to deassert MAC reset", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to deassert MAC reset: %d\n", ret);
|
||||
return log_msg_ret("net", ret);
|
||||
}
|
||||
|
||||
// Reset PHY
|
||||
ret = hisi_femac_phy_reset(priv);
|
||||
if (ret < 0)
|
||||
return log_msg_ret("Failed to reset phy", ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to reset PHY: %d\n", ret);
|
||||
return log_msg_ret("net", ret);
|
||||
}
|
||||
|
||||
// Connect to PHY
|
||||
priv->phy = dm_eth_phy_connect(dev);
|
||||
if (!priv->phy)
|
||||
return log_msg_ret("Failed to connect to phy", -EINVAL);
|
||||
if (!priv->phy) {
|
||||
dev_err(dev, "Failed to connect to phy\n");
|
||||
return log_msg_ret("phy", -EINVAL);
|
||||
}
|
||||
|
||||
hisi_femac_port_init(priv);
|
||||
return 0;
|
||||
|
@ -459,6 +607,9 @@ static const struct eth_ops hisi_femac_ops = {
|
|||
.free_pkt = hisi_femac_free_pkt,
|
||||
.stop = hisi_femac_stop,
|
||||
.write_hwaddr = hisi_femac_set_hw_mac_addr,
|
||||
.get_sset_count = hisi_femac_get_sset_count,
|
||||
.get_strings = hisi_femac_get_strings,
|
||||
.get_stats = hisi_femac_get_stats,
|
||||
};
|
||||
|
||||
static const struct udevice_id hisi_femac_ids[] = {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <dm.h>
|
||||
#include <clk.h>
|
||||
#include <miiphy.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
|
@ -74,7 +75,8 @@ static int hisi_femac_mdio_of_to_plat(struct udevice *dev)
|
|||
data->membase = dev_remap_addr(dev);
|
||||
if (IS_ERR(data->membase)) {
|
||||
ret = PTR_ERR(data->membase);
|
||||
return log_msg_ret("Failed to remap base addr", ret);
|
||||
dev_err(dev, "Failed to remap base addr %d\n", ret);
|
||||
return log_msg_ret("mdio", ret);
|
||||
}
|
||||
|
||||
// clk is optional
|
||||
|
@ -89,8 +91,10 @@ static int hisi_femac_mdio_probe(struct udevice *dev)
|
|||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(data->clk);
|
||||
if (ret)
|
||||
return log_msg_ret("Failed to enable clk", ret);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to enable clock: %d\n", ret);
|
||||
return log_msg_ret("clk", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,5 +116,6 @@ U_BOOT_DRIVER(hisi_femac_mdio_driver) = {
|
|||
.of_to_plat = hisi_femac_mdio_of_to_plat,
|
||||
.probe = hisi_femac_mdio_probe,
|
||||
.ops = &hisi_femac_mdio_ops,
|
||||
.plat_auto = sizeof(struct mdio_perdev_priv),
|
||||
.priv_auto = sizeof(struct hisi_femac_mdio_data),
|
||||
};
|
||||
|
|
|
@ -42,6 +42,12 @@
|
|||
#define BCM54810_SHD_CLK_CTL 0x3
|
||||
#define BCM54810_SHD_CLK_CTL_GTXCLK_EN BIT(9)
|
||||
|
||||
#define BCM54XX_SHD_LEDS1 0x0d
|
||||
#define BCM_LED_SRC_LINKSPD2 0x1
|
||||
#define BCM_LED_SRC_ACTIVITYLED 0x3
|
||||
#define BCM54XX_SHD_LEDS1_LED3(src) (((src) & 0xf) << 4)
|
||||
#define BCM54XX_SHD_LEDS1_LED1(src) (((src) & 0xf) << 0)
|
||||
|
||||
static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
|
||||
{
|
||||
/* The register must be written to both the Shadow Register Select and
|
||||
|
@ -148,7 +154,16 @@ static int bcm54210e_config(struct phy_device *phydev)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return bcm5461_config(phydev);
|
||||
ret = bcm5461_config(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Configure LEDs to blink. */
|
||||
bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1,
|
||||
BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
|
||||
BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm54xx_parse_status(struct phy_device *phydev)
|
||||
|
|
|
@ -18,12 +18,11 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
|
|||
{
|
||||
struct phy_device *phydev;
|
||||
struct ofnode_phandle_args phandle_args;
|
||||
struct gpio_desc gpio;
|
||||
const char *node_name;
|
||||
struct udevice *pdev;
|
||||
ofnode node;
|
||||
u32 id, assert, deassert;
|
||||
u16 vendor, device;
|
||||
ofnode node;
|
||||
u32 id;
|
||||
int ret;
|
||||
|
||||
if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
|
||||
|
@ -41,35 +40,9 @@ struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_DM_ETH_PHY)) {
|
||||
ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
|
||||
GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
|
||||
if (!ret) {
|
||||
assert = ofnode_read_u32_default(node,
|
||||
"reset-assert-us", 0);
|
||||
deassert = ofnode_read_u32_default(node,
|
||||
"reset-deassert-us",
|
||||
0);
|
||||
ret = dm_gpio_set_value(&gpio, 1);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed assert gpio, err: %d\n", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udelay(assert);
|
||||
|
||||
ret = dm_gpio_set_value(&gpio, 0);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed deassert gpio, err: %d\n",
|
||||
ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udelay(deassert);
|
||||
}
|
||||
}
|
||||
ret = phy_gpio_reset(dev);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
if (phyaddr == -1)
|
||||
phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1);
|
||||
|
|
|
@ -286,11 +286,11 @@ static void ncsi_rsp_gc(struct ncsi_rsp_pkt *pkt)
|
|||
}
|
||||
|
||||
c = &ncsi_priv->packages[np].channels[nc];
|
||||
c->cap_generic = ntohl(gc->cap) & NCSI_CAP_GENERIC_MASK;
|
||||
c->cap_bc = ntohl(gc->bc_cap) & NCSI_CAP_BC_MASK;
|
||||
c->cap_mc = ntohl(gc->mc_cap) & NCSI_CAP_MC_MASK;
|
||||
c->cap_aen = ntohl(gc->aen_cap) & NCSI_CAP_AEN_MASK;
|
||||
c->cap_vlan = ntohl(gc->vlan_mode) & NCSI_CAP_VLAN_MASK;
|
||||
c->cap_generic = get_unaligned_be32(&gc->cap) & NCSI_CAP_GENERIC_MASK;
|
||||
c->cap_bc = get_unaligned_be32(&gc->bc_cap) & NCSI_CAP_BC_MASK;
|
||||
c->cap_mc = get_unaligned_be32(&gc->mc_cap) & NCSI_CAP_MC_MASK;
|
||||
c->cap_aen = get_unaligned_be32(&gc->aen_cap) & NCSI_CAP_AEN_MASK;
|
||||
c->cap_vlan = gc->vlan_mode & NCSI_CAP_VLAN_MASK;
|
||||
|
||||
/* End of probe for this channel */
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ static int ncsi_send_command(unsigned int np, unsigned int nc, unsigned int cmd,
|
|||
checksum = ncsi_calculate_checksum((unsigned char *)hdr,
|
||||
sizeof(*hdr) + len);
|
||||
pchecksum = (__be32 *)((void *)(hdr + 1) + len);
|
||||
put_unaligned_be32(htonl(checksum), pchecksum);
|
||||
put_unaligned_be32(checksum, pchecksum);
|
||||
|
||||
if (wait) {
|
||||
net_set_timeout_handler(1000UL, ncsi_timeout_handler);
|
||||
|
@ -619,9 +619,12 @@ static void ncsi_handle_aen(struct ip_udp_hdr *ip, unsigned int len)
|
|||
|
||||
/* Link or configuration lost - just redo the discovery process */
|
||||
ncsi_priv->state = NCSI_PROBE_PACKAGE_SP;
|
||||
for (i = 0; i < ncsi_priv->n_packages; i++)
|
||||
for (i = 0; i < ncsi_priv->n_packages; i++) {
|
||||
free(ncsi_priv->packages[i].channels);
|
||||
ncsi_priv->packages[i].channels = NULL;
|
||||
}
|
||||
free(ncsi_priv->packages);
|
||||
ncsi_priv->packages = NULL;
|
||||
ncsi_priv->n_packages = 0;
|
||||
|
||||
ncsi_priv->current_package = NCSI_PACKAGE_MAX;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <phy.h>
|
||||
#include <errno.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/of_extra.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -566,7 +568,8 @@ struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID)
|
||||
if (addr >= 0 && addr < PHY_MAX_ADDR && phy_id != PHY_FIXED_ID &&
|
||||
phy_id != PHY_NCSI_ID)
|
||||
bus->phymap[addr] = dev;
|
||||
|
||||
return dev;
|
||||
|
@ -642,12 +645,12 @@ static struct phy_device *search_for_existing_phy(struct mii_dev *bus,
|
|||
{
|
||||
/* If we have one, return the existing device, with new interface */
|
||||
while (phy_mask) {
|
||||
int addr = ffs(phy_mask) - 1;
|
||||
unsigned int addr = ffs(phy_mask) - 1;
|
||||
|
||||
if (bus->phymap[addr])
|
||||
return bus->phymap[addr];
|
||||
|
||||
phy_mask &= ~(1 << addr);
|
||||
phy_mask &= ~(1U << addr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -768,6 +771,59 @@ int miiphy_reset(const char *devname, unsigned char addr)
|
|||
return phy_reset(phydev);
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_GPIO) && CONFIG_IS_ENABLED(OF_REAL) && \
|
||||
!IS_ENABLED(CONFIG_DM_ETH_PHY)
|
||||
int phy_gpio_reset(struct udevice *dev)
|
||||
{
|
||||
struct ofnode_phandle_args phandle_args;
|
||||
struct gpio_desc gpio;
|
||||
u32 assert, deassert;
|
||||
ofnode node;
|
||||
int ret;
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
|
||||
&phandle_args);
|
||||
/* No PHY handle is OK */
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
node = phandle_args.node;
|
||||
if (!ofnode_valid(node))
|
||||
return -EINVAL;
|
||||
|
||||
ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
|
||||
GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
|
||||
/* No PHY reset GPIO is OK */
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
assert = ofnode_read_u32_default(node, "reset-assert-us", 20000);
|
||||
deassert = ofnode_read_u32_default(node, "reset-deassert-us", 1000);
|
||||
ret = dm_gpio_set_value(&gpio, 1);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed assert gpio, err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
udelay(assert);
|
||||
|
||||
ret = dm_gpio_set_value(&gpio, 0);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed deassert gpio, err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
udelay(deassert);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int phy_gpio_reset(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct phy_device *phy_find_by_mask(struct mii_dev *bus, uint phy_mask)
|
||||
{
|
||||
/* Reset the bus */
|
||||
|
|
|
@ -2710,6 +2710,8 @@
|
|||
#define PCI_DEVICE_ID_INTEL_I211_COPPER 0x1539
|
||||
#define PCI_DEVICE_ID_INTEL_I210_COPPER_FLASHLESS 0x157b
|
||||
#define PCI_DEVICE_ID_INTEL_I210_SERDES_FLASHLESS 0x157c
|
||||
#define PCI_DEVICE_ID_INTEL_I225_UNPROGRAMMED 0x15dF
|
||||
#define PCI_DEVICE_ID_INTEL_I225_IT 0x0d9f
|
||||
#define PCI_DEVICE_ID_INTEL_80960_RP 0x1960
|
||||
#define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21
|
||||
#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30
|
||||
|
|
|
@ -183,6 +183,15 @@ struct fixed_link {
|
|||
*/
|
||||
int phy_reset(struct phy_device *phydev);
|
||||
|
||||
/**
|
||||
* phy_gpio_reset() - Resets the specified PHY using GPIO reset
|
||||
* Toggles the optional PHY reset GPIO
|
||||
*
|
||||
* @dev: PHY udevice to reset
|
||||
* @return: 0 if OK, -ve on error
|
||||
*/
|
||||
int phy_gpio_reset(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* phy_find_by_mask() - Searches for a PHY on the specified MDIO bus
|
||||
* The function checks the PHY addresses flagged in phy_mask and returns a
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/lists.h>
|
||||
#include <eth_phy.h>
|
||||
#include <log.h>
|
||||
#include <malloc.h>
|
||||
#include <miiphy.h>
|
||||
|
@ -121,6 +123,42 @@ static int mdio_reset(struct mii_dev *mii_bus)
|
|||
return dm_mdio_reset(mii_bus->priv);
|
||||
}
|
||||
|
||||
static int mdio_bind_phy_nodes(struct udevice *mdio_dev)
|
||||
{
|
||||
ofnode mdio_node, phy_node;
|
||||
struct udevice *phy_dev;
|
||||
const char *node_name;
|
||||
int ret;
|
||||
|
||||
mdio_node = dev_ofnode(mdio_dev);
|
||||
if (!ofnode_valid(mdio_node)) {
|
||||
dev_dbg(mdio_dev, "invalid ofnode for mdio_dev\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ofnode_for_each_subnode(phy_node, mdio_node) {
|
||||
node_name = ofnode_get_name(phy_node);
|
||||
dev_dbg(mdio_dev, "* Found child node: '%s'\n", node_name);
|
||||
ret = device_bind_driver_to_node(mdio_dev,
|
||||
"eth_phy_generic_drv",
|
||||
node_name, phy_node, &phy_dev);
|
||||
if (ret) {
|
||||
dev_dbg(mdio_dev, " - Eth phy binding error: %d\n", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_dbg(mdio_dev, " - bound phy device: '%s'\n", node_name);
|
||||
ret = device_probe(phy_dev);
|
||||
if (ret) {
|
||||
dev_dbg(mdio_dev, "Device '%s' probe failed\n", phy_dev->name);
|
||||
device_unbind(phy_dev);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm_mdio_post_probe(struct udevice *dev)
|
||||
{
|
||||
struct mdio_perdev_priv *pdata = dev_get_uclass_priv(dev);
|
||||
|
@ -154,6 +192,9 @@ static int dm_mdio_post_probe(struct udevice *dev)
|
|||
}
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(DM_ETH_PHY))
|
||||
mdio_bind_phy_nodes(dev);
|
||||
|
||||
return mdio_register(pdata->mii_bus);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue