static int zynq_phy_init(struct udevice *dev) { int ret; struct zynq_gem_priv *priv = dev_get_priv(dev); struct zynq_gem_regs *regs = priv->iobase; const u32 supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; /* Enable only MDIO bus */ writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s->nwctrl); if (priv->interface != PHY_INTERFACE_MODE_SGMII) { ret = phy_detection(dev); if (ret) { printf("GEM PHY init failed\n"); return ret; } } priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); if (!priv->phydev) return -ENODEV; priv->phydev->supported = supported | ADVERTISED_Pause | ADVERTISED_Asym_Pause; priv->phydev->advertising = priv->phydev->supported; phy_config(priv->phydev); return 0; }
static int zynq_gem_init(struct eth_device *dev, bd_t * bis) { u32 i; unsigned long __maybe_unused clk_rate = 0; struct phy_device *phydev; struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; struct zynq_gem_priv *priv = dev->priv; struct emac_bd *dummy_tx_bd = &priv->tx_bd[4]; struct emac_bd *dummy_rx_bd = &priv->tx_bd[6]; const u32 supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; if (!priv->init) { /* Disable all interrupts */ writel(0xFFFFFFFF, ®s->idr); /* Disable the receiver & transmitter */ writel(0, ®s->nwctrl); writel(0, ®s->txsr); writel(0, ®s->rxsr); writel(0, ®s->phymntnc); /* Clear the Hash registers for the mac address * pointed by AddressPtr */ writel(0x0, ®s->hashl); /* Write bits [63:32] in TOP */ writel(0x0, ®s->hashh); /* Clear all counters */ for (i = 0; i < STAT_SIZE; i++) readl(®s->stat[i]); /* Setup RxBD space */ memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd)); for (i = 0; i < RX_BUF; i++) { priv->rx_bd[i].status = 0xF0000000; priv->rx_bd[i].addr = ((unsigned long)(priv->rxbuffers) + (i * PKTSIZE_ALIGN)); } /* WRAP bit to last BD */ priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK; /* Write RxBDs to IP */ writel((unsigned long)priv->rx_bd, ®s->rxqbase); /* Setup for DMA Configuration register */ writel(ZYNQ_GEM_DMACR_INIT, ®s->dmacr); /* Setup for Network Control register, MDIO, Rx and Tx enable */ setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK); /* * Disable the second priority queue. * FIXME: Consider GEMs with more than 2 queues. */ dummy_tx_bd->addr = 0; dummy_tx_bd->status = ZYNQ_GEM_TXBUF_WRAP_MASK | ZYNQ_GEM_TXBUF_LAST_MASK| ZYNQ_GEM_TXBUF_USED_MASK; dummy_rx_bd->addr = ZYNQ_GEM_RXBUF_WRAP_MASK | ZYNQ_GEM_RXBUF_NEW_MASK; dummy_rx_bd->status = 0; flush_dcache_range((ulong)&dummy_tx_bd, (ulong)&dummy_tx_bd + sizeof(dummy_tx_bd)); flush_dcache_range((ulong)&dummy_rx_bd, (ulong)&dummy_rx_bd + sizeof(dummy_rx_bd)); writel((unsigned long)dummy_tx_bd, ®s->transmit_q1_ptr); writel((unsigned long)dummy_rx_bd, ®s->receive_q1_ptr); priv->init++; } phy_detection(dev); /* interface - look at tsec */ phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); phydev->supported = supported | ADVERTISED_Pause | ADVERTISED_Asym_Pause; phydev->advertising = phydev->supported; priv->phydev = phydev; phy_config(phydev); phy_startup(phydev); phydev->speed = SPEED_1000; if (!phydev->link) { printf("%s: No link.\n", phydev->dev->name); return -1; } switch (phydev->speed) { case SPEED_1000: writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, ®s->nwcfg); clk_rate = ZYNQ_GEM_FREQUENCY_1000; break; case SPEED_100: writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100, ®s->nwcfg); clk_rate = ZYNQ_GEM_FREQUENCY_100; break; case SPEED_10: clk_rate = ZYNQ_GEM_FREQUENCY_10; break; } /* Change the rclk and clk only not using EMIO interface */ if (!priv->emio) zynq_slcr_gem_clk_setup(dev->iobase != ZYNQ_GEM_BASEADDR0, clk_rate); /* set hardware address because of ... */ if (!is_valid_ethaddr(dev->enetaddr)) { printf("%s: mac address is not valid\n", dev->name); return -1; } zynq_gem_setup_mac(dev); setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); return 0; }