summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/designware.c16
-rw-r--r--drivers/net/macb.c186
-rw-r--r--drivers/net/mtk_eth.c57
-rw-r--r--drivers/net/mtk_eth.h9
4 files changed, 180 insertions, 88 deletions
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index c15fb36ae3f..c222197b114 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -685,8 +685,8 @@ int designware_eth_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
struct dw_eth_dev *priv = dev_get_priv(dev);
- u32 iobase = pdata->iobase;
- ulong ioaddr;
+ phys_addr_t iobase = pdata->iobase;
+ void *ioaddr;
int ret, err;
struct reset_ctl_bulk reset_bulk;
#ifdef CONFIG_CLK
@@ -746,16 +746,18 @@ int designware_eth_probe(struct udevice *dev)
* or via a PCI bridge, fill in plat before we probe the hardware.
*/
if (IS_ENABLED(CONFIG_PCI) && device_is_on_pci_bus(dev)) {
- dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase);
- iobase &= PCI_BASE_ADDRESS_MEM_MASK;
- iobase = dm_pci_mem_to_phys(dev, iobase);
+ u32 pcibase;
+ dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &pcibase);
+ pcibase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ iobase = dm_pci_mem_to_phys(dev, pcibase);
pdata->iobase = iobase;
pdata->phy_interface = PHY_INTERFACE_MODE_RMII;
}
- debug("%s, iobase=%x, priv=%p\n", __func__, iobase, priv);
- ioaddr = iobase;
+ debug("%s, iobase=%pa, priv=%p\n", __func__, &iobase, priv);
+ ioaddr = phys_to_virt(iobase);
priv->mac_regs_p = (struct eth_mac_regs *)ioaddr;
priv->dma_regs_p = (struct eth_dma_regs *)(ioaddr + DW_DMA_BASE_OFFSET);
priv->interface = pdata->phy_interface;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index bfc48dac079..bca014c3cbb 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -128,6 +128,8 @@ struct macb_device {
unsigned long dummy_desc_dma;
const struct device *dev;
+ unsigned int duplex;
+ unsigned int speed;
unsigned short phy_addr;
struct mii_dev *bus;
#ifdef CONFIG_PHYLIB
@@ -178,6 +180,12 @@ static int gem_is_gigabit_capable(struct macb_device *macb)
return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4();
}
+/* Is the port a fixed link */
+static int macb_port_is_fixed_link(struct macb_device *macb)
+{
+ return macb->phy_addr > PHY_MAX_ADDR;
+}
+
static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg,
u16 value)
{
@@ -666,97 +674,109 @@ static int macb_phy_init(struct udevice *dev, const char *name)
int i;
arch_get_mdio_control(name);
- /* Auto-detect phy_addr */
- ret = macb_phy_find(macb, name);
- if (ret)
- return ret;
+ /* If port is not fixed -> setup PHY */
+ if (!macb_port_is_fixed_link(macb)) {
+ /* Auto-detect phy_addr */
+ ret = macb_phy_find(macb, name);
+ if (ret)
+ return ret;
- /* Check if the PHY is up to snuff... */
- phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
- if (phy_id == 0xffff) {
- printf("%s: No PHY present\n", name);
- return -ENODEV;
- }
+ /* Check if the PHY is up to snuff... */
+ phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1);
+ if (phy_id == 0xffff) {
+ printf("%s: No PHY present\n", name);
+ return -ENODEV;
+ }
#ifdef CONFIG_PHYLIB
- macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
- macb->phy_interface);
- if (!macb->phydev) {
- printf("phy_connect failed\n");
- return -ENODEV;
- }
+ macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev,
+ macb->phy_interface);
+ if (!macb->phydev) {
+ printf("phy_connect failed\n");
+ return -ENODEV;
+ }
- phy_config(macb->phydev);
+ phy_config(macb->phydev);
#endif
- status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
- if (!(status & BMSR_LSTATUS)) {
- /* Try to re-negotiate if we don't have link already. */
- macb_phy_reset(macb, name);
-
- for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
- status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
- if (status & BMSR_LSTATUS) {
- /*
- * Delay a bit after the link is established,
- * so that the next xfer does not fail
- */
- mdelay(10);
- break;
+ status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
+ if (!(status & BMSR_LSTATUS)) {
+ /* Try to re-negotiate if we don't have link already. */
+ macb_phy_reset(macb, name);
+
+ for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
+ status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR);
+ if (status & BMSR_LSTATUS) {
+ /*
+ * Delay a bit after the link is established,
+ * so that the next xfer does not fail
+ */
+ mdelay(10);
+ break;
+ }
+ udelay(100);
}
- udelay(100);
}
- }
- if (!(status & BMSR_LSTATUS)) {
- printf("%s: link down (status: 0x%04x)\n",
- name, status);
- return -ENETDOWN;
- }
+ if (!(status & BMSR_LSTATUS)) {
+ printf("%s: link down (status: 0x%04x)\n",
+ name, status);
+ return -ENETDOWN;
+ }
- /* First check for GMAC and that it is GiB capable */
- if (gem_is_gigabit_capable(macb)) {
- lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
+ /* First check for GMAC and that it is GiB capable */
+ if (gem_is_gigabit_capable(macb)) {
+ lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000);
- if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
- LPA_1000XHALF)) {
- duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
- 1 : 0);
+ if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL |
+ LPA_1000XHALF)) {
+ duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ?
+ 1 : 0);
- printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
- name,
- duplex ? "full" : "half",
- lpa);
+ printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
+ name,
+ duplex ? "full" : "half",
+ lpa);
- ncfgr = macb_readl(macb, NCFGR);
- ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
- ncfgr |= GEM_BIT(GBE);
+ ncfgr = macb_readl(macb, NCFGR);
+ ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+ ncfgr |= GEM_BIT(GBE);
- if (duplex)
- ncfgr |= MACB_BIT(FD);
+ if (duplex)
+ ncfgr |= MACB_BIT(FD);
- macb_writel(macb, NCFGR, ncfgr);
+ macb_writel(macb, NCFGR, ncfgr);
- ret = macb_linkspd_cb(dev, _1000BASET);
- if (ret)
- return ret;
+ ret = macb_linkspd_cb(dev, _1000BASET);
+ if (ret)
+ return ret;
- return 0;
+ return 0;
+ }
}
- }
- /* fall back for EMAC checking */
- adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
- lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
- media = mii_nway_result(lpa & adv);
- speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
- ? 1 : 0);
- duplex = (media & ADVERTISE_FULL) ? 1 : 0;
- printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
- name,
- speed ? "100" : "10",
- duplex ? "full" : "half",
- lpa);
+ /* fall back for EMAC checking */
+ adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE);
+ lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA);
+ media = mii_nway_result(lpa & adv);
+ speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
+ ? 1 : 0);
+ duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+ printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
+ name,
+ speed ? "100" : "10",
+ duplex ? "full" : "half",
+ lpa);
+ } else {
+ /* if macb port is a fixed link */
+ /* TODO : manage gigabit capable processors */
+ speed = macb->speed;
+ duplex = macb->duplex;
+ printf("%s: link up, %sMbps %s-duplex\n",
+ name,
+ speed ? "100" : "10",
+ duplex ? "full" : "half");
+ }
ncfgr = macb_readl(macb, NCFGR);
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
@@ -1276,6 +1296,28 @@ int __weak macb_late_eth_of_to_plat(struct udevice *dev)
static int macb_eth_of_to_plat(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
+ struct macb_device *macb = dev_get_priv(dev);
+ void *blob = (void *)gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ int fl_node, speed_fdt;
+
+ /* fetch 'fixed-link' property */
+ fl_node = fdt_subnode_offset(blob, node, "fixed-link");
+ if (fl_node >= 0) {
+ /* set phy_addr to invalid value for fixed link */
+ macb->phy_addr = PHY_MAX_ADDR + 1;
+ macb->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex");
+ speed_fdt = fdtdec_get_int(blob, fl_node, "speed", 0);
+ if (speed_fdt == 100) {
+ macb->speed = 1;
+ } else if (speed_fdt == 10) {
+ macb->speed = 0;
+ } else {
+ printf("%s: The given speed %d of ethernet in the DT is not supported\n",
+ __func__, speed_fdt);
+ return -EINVAL;
+ }
+ }
pdata->iobase = (uintptr_t)dev_remap_addr(dev);
if (!pdata->iobase)
diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c
index 3cfce058451..75e7bcf83b7 100644
--- a/drivers/net/mtk_eth.c
+++ b/drivers/net/mtk_eth.c
@@ -137,6 +137,7 @@ struct mtk_eth_priv {
int force_mode;
int speed;
int duplex;
+ int mdc;
bool pn_swap;
struct phy_device *phydev;
@@ -1245,7 +1246,8 @@ static int mtk_phy_start(struct mtk_eth_priv *priv)
}
if (!priv->force_mode) {
- if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII)
+ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+ priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
mtk_xphy_link_adjust(priv);
else
mtk_phy_link_adjust(priv);
@@ -1515,7 +1517,7 @@ static void mtk_mac_init(struct mtk_eth_priv *priv)
static void mtk_xmac_init(struct mtk_eth_priv *priv)
{
- u32 sts;
+ u32 force_link = 0;
switch (priv->phy_interface) {
case PHY_INTERFACE_MODE_USXGMII:
@@ -1530,15 +1532,19 @@ static void mtk_xmac_init(struct mtk_eth_priv *priv)
SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id),
0);
- if (priv->gmac_id == 1) {
+ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII &&
+ priv->gmac_id == 1) {
mtk_infra_rmw(priv, TOPMISC_NETSYS_PCS_MUX,
NETSYS_PCS_MUX_MASK, MUX_G2_USXGMII_SEL);
- } else if (priv->gmac_id == 2) {
- sts = mtk_gmac_read(priv, XGMAC_STS(priv->gmac_id));
- sts |= XGMAC_FORCE_LINK;
- mtk_gmac_write(priv, XGMAC_STS(priv->gmac_id), sts);
}
+ if (priv->phy_interface == PHY_INTERFACE_MODE_XGMII ||
+ priv->gmac_id == 2)
+ force_link = XGMAC_FORCE_LINK(priv->gmac_id);
+
+ mtk_gmac_rmw(priv, XGMAC_STS(priv->gmac_id),
+ XGMAC_FORCE_LINK(priv->gmac_id), force_link);
+
/* Force GMAC link down */
mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), FORCE_MODE);
}
@@ -1607,6 +1613,26 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv)
mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0);
}
+static void mtk_eth_mdc_init(struct mtk_eth_priv *priv)
+{
+ u32 divider;
+
+ if (priv->mdc == 0)
+ return;
+
+ divider = min_t(u32, DIV_ROUND_UP(MDC_MAX_FREQ, priv->mdc), MDC_MAX_DIVIDER);
+
+ /* Configure MDC turbo mode */
+ if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3))
+ mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, MISC_MDC_TURBO);
+ else
+ mtk_gmac_rmw(priv, GMAC_PPSC_REG, 0, MISC_MDC_TURBO);
+
+ /* Configure MDC divider */
+ mtk_gmac_rmw(priv, GMAC_PPSC_REG, PHY_MDC_CFG,
+ FIELD_PREP(PHY_MDC_CFG, divider));
+}
+
static int mtk_eth_start(struct udevice *dev)
{
struct mtk_eth_priv *priv = dev_get_priv(dev);
@@ -1803,8 +1829,12 @@ static int mtk_eth_probe(struct udevice *dev)
noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC,
ARCH_DMA_MINALIGN);
+ /* Set MDC divider */
+ mtk_eth_mdc_init(priv);
+
/* Set MAC mode */
- if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII)
+ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII ||
+ priv->phy_interface == PHY_INTERFACE_MODE_XGMII)
mtk_xmac_init(priv);
else
mtk_mac_init(priv);
@@ -1881,6 +1911,17 @@ static int mtk_eth_of_to_plat(struct udevice *dev)
priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0);
+ priv->mdc = 0;
+ subnode = ofnode_find_subnode(dev_ofnode(dev), "mdio");
+ if (ofnode_valid(subnode)) {
+ priv->mdc = ofnode_read_u32_default(subnode, "clock-frequency", 2500000);
+ if (priv->mdc > MDC_MAX_FREQ ||
+ priv->mdc < MDC_MAX_FREQ / MDC_MAX_DIVIDER) {
+ printf("error: MDIO clock frequency out of range\n");
+ return -EINVAL;
+ }
+ }
+
/* Interface mode is required */
pdata->phy_interface = dev_read_phy_mode(dev);
priv->phy_interface = pdata->phy_interface;
diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h
index 491cac56a81..fd31c782c7f 100644
--- a/drivers/net/mtk_eth.h
+++ b/drivers/net/mtk_eth.h
@@ -180,6 +180,12 @@ enum mkt_eth_capabilities {
/* GMAC Registers */
+#define GMAC_PPSC_REG 0x0000
+#define PHY_MDC_CFG GENMASK(29, 24)
+#define MDC_TURBO BIT(20)
+#define MDC_MAX_FREQ 25000000
+#define MDC_MAX_DIVIDER 63
+
#define GMAC_PIAC_REG 0x0004
#define PHY_ACS_ST BIT(31)
#define MDIO_REG_ADDR_S 25
@@ -197,6 +203,7 @@ enum mkt_eth_capabilities {
#define P1_XGMAC_FORCE_LINK BIT(15)
#define GMAC_MAC_MISC_REG 0x0010
+#define MISC_MDC_TURBO BIT(4)
#define GMAC_GSW_CFG_REG 0x0080
#define GSWTX_IPG_M 0xF0000
@@ -261,7 +268,7 @@ enum mkt_eth_capabilities {
/* XGMAC Status Registers */
#define XGMAC_STS(x) (((x) == 2) ? 0x001C : 0x000C)
-#define XGMAC_FORCE_LINK BIT(15)
+#define XGMAC_FORCE_LINK(x) (((x) == 1) ? BIT(31) : BIT(15))
/* XGMAC Registers */
#define XGMAC_PORT_MCR(x) (0x2000 + (((x) - 1) * 0x1000))