+// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2011 Michal Simek
*
*
* Based on Xilinx gmac driver:
* (C) Copyright 2011 Xilinx
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <clk.h>
int phy_of_handle;
struct mii_dev *bus;
struct clk clk;
+ u32 max_speed;
+ bool int_pcs;
};
-static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
+static int phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
u32 op, u16 *data)
{
u32 mgtcr;
struct zynq_gem_regs *regs = priv->iobase;
int err;
- err = wait_for_bit(__func__, ®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
- true, 20000, true);
+ err = wait_for_bit_le32(®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+ true, 20000, false);
if (err)
return err;
/* Write mgtcr and wait for completion */
writel(mgtcr, ®s->phymntnc);
- err = wait_for_bit(__func__, ®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
- true, 20000, true);
+ err = wait_for_bit_le32(®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+ true, 20000, false);
if (err)
return err;
return 0;
}
-static u32 phyread(struct zynq_gem_priv *priv, u32 phy_addr,
+static int phyread(struct zynq_gem_priv *priv, u32 phy_addr,
u32 regnum, u16 *val)
{
- u32 ret;
+ int ret;
ret = phy_setup_op(priv, phy_addr, regnum,
ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val);
return ret;
}
-static u32 phywrite(struct zynq_gem_priv *priv, u32 phy_addr,
+static int phywrite(struct zynq_gem_priv *priv, u32 phy_addr,
u32 regnum, u16 data)
{
debug("%s: phy_addr %d, regnum 0x%x, data 0x%x\n", __func__, phy_addr,
static int phy_detection(struct udevice *dev)
{
int i;
- u16 phyreg;
+ u16 phyreg = 0;
struct zynq_gem_priv *priv = dev->priv;
if (priv->phyaddr != -1) {
/* Enable only MDIO bus */
writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s->nwctrl);
- if (priv->interface != PHY_INTERFACE_MODE_SGMII) {
+ if ((priv->interface != PHY_INTERFACE_MODE_SGMII) &&
+ (priv->interface != PHY_INTERFACE_MODE_GMII)) {
ret = phy_detection(dev);
if (ret) {
printf("GEM PHY init failed\n");
priv->phydev->supported &= supported | ADVERTISED_Pause |
ADVERTISED_Asym_Pause;
+ if (priv->max_speed) {
+ ret = phy_set_supported(priv->phydev, priv->max_speed);
+ if (ret)
+ return ret;
+ }
+
priv->phydev->advertising = priv->phydev->supported;
if (priv->phy_of_handle > 0)
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((ulong)dummy_tx_bd, ®s->transmit_q1_ptr);
writel((ulong)dummy_rx_bd, ®s->receive_q1_ptr);
nwconfig = ZYNQ_GEM_NWCFG_INIT;
- if (priv->interface == PHY_INTERFACE_MODE_SGMII) {
+ /*
+ * Set SGMII enable PCS selection only if internal PCS/PMA
+ * core is used and interface is SGMII.
+ */
+ if (priv->interface == PHY_INTERFACE_MODE_SGMII &&
+ priv->int_pcs) {
nwconfig |= ZYNQ_GEM_NWCFG_SGMII_ENBL |
ZYNQ_GEM_NWCFG_PCS_SEL;
#ifdef CONFIG_ARM64
if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
printf("TX buffers exhausted in mid frame\n");
- return wait_for_bit(__func__, ®s->txsr, ZYNQ_GEM_TSR_DONE,
- true, 20000, true);
+ return wait_for_bit_le32(®s->txsr, ZYNQ_GEM_TSR_DONE,
+ true, 20000, true);
}
/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
static int zynq_gem_read_rom_mac(struct udevice *dev)
{
- int retval;
struct eth_pdata *pdata = dev_get_platdata(dev);
- retval = zynq_board_read_rom_ethaddr(pdata->enetaddr);
- if (retval == -ENOSYS)
- retval = 0;
+ if (!pdata)
+ return -ENOSYS;
- return retval;
+ return zynq_board_read_rom_ethaddr(pdata->enetaddr);
}
static int zynq_gem_miiphy_read(struct mii_dev *bus, int addr,
{
struct zynq_gem_priv *priv = bus->priv;
int ret;
- u16 val;
+ u16 val = 0;
ret = phyread(priv, addr, reg, &val);
debug("%s 0x%x, 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val, ret);
/* Align rxbuffers to ARCH_DMA_MINALIGN */
priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN);
+ if (!priv->rxbuffers)
+ return -ENOMEM;
+
memset(priv->rxbuffers, 0, RX_BUF * PKTSIZE_ALIGN);
/* Align bd_space to MMU_SECTION_SHIFT */
bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
+ if (!bd_space)
+ return -ENOMEM;
+
mmu_set_region_dcache_behaviour((phys_addr_t)bd_space,
BD_SPACE, DCACHE_OFF);
int node = dev_of_offset(dev);
const char *phy_mode;
- pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+ pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
/* Hardcode for now */
priv->phyaddr = -1;
}
priv->interface = pdata->phy_interface;
+ priv->max_speed = fdtdec_get_uint(gd->fdt_blob, priv->phy_of_handle,
+ "max-speed", SPEED_1000);
+ priv->int_pcs = fdtdec_get_bool(gd->fdt_blob, node,
+ "is-internal-pcspma");
+
printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
priv->phyaddr, phy_string_for_interface(priv->interface));