#include <asm/system.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
+#include <asm-generic/errno.h>
#if !defined(CONFIG_PHYLIB)
# error XILINX_GEM_ETHERNET requires PHYLIB
#define ZYNQ_GEM_NWCFG_SPEED1000 0x000000400 /* 1Gbps operation */
#define ZYNQ_GEM_NWCFG_FDEN 0x000000002 /* Full Duplex mode */
#define ZYNQ_GEM_NWCFG_FSREM 0x000020000 /* FCS removal */
-#define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x000080000 /* Div pclk by 32, 80MHz */
-#define ZYNQ_GEM_NWCFG_MDCCLKDIV2 0x0000c0000 /* Div pclk by 48, 120MHz */
+#define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x0000c0000 /* Div pclk by 48, max 120MHz */
#ifdef CONFIG_ARM64
# define ZYNQ_GEM_DBUS_WIDTH (1 << 21) /* 64 bit bus */
ZYNQ_GEM_DMACR_TXSIZE | \
ZYNQ_GEM_DMACR_RXBUF)
+#define ZYNQ_GEM_TSR_DONE 0x00000020 /* Tx done mask */
+
/* Use MII register 1 (MII status register) to detect PHY */
#define PHY_DETECT_REG 1
int phyaddr;
u32 emio;
int init;
+ struct zynq_gem_regs *iobase;
phy_interface_t interface;
struct phy_device *phydev;
struct mii_dev *bus;
};
-static inline int mdio_wait(struct eth_device *dev)
+static inline int mdio_wait(struct zynq_gem_regs *regs)
{
- struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
u32 timeout = 20000;
/* Wait till MDIO interface is ready to accept a new transaction. */
return 0;
}
-static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum,
- u32 op, u16 *data)
+static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
+ u32 op, u16 *data)
{
u32 mgtcr;
- struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
+ struct zynq_gem_regs *regs = priv->iobase;
- if (mdio_wait(dev))
+ if (mdio_wait(regs))
return 1;
/* Construct mgtcr mask for the operation */
/* Write mgtcr and wait for completion */
writel(mgtcr, ®s->phymntnc);
- if (mdio_wait(dev))
+ if (mdio_wait(regs))
return 1;
if (op == ZYNQ_GEM_PHYMNTNC_OP_R_MASK)
return 0;
}
-static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val)
+static u32 phyread(struct zynq_gem_priv *priv, u32 phy_addr,
+ u32 regnum, u16 *val)
{
u32 ret;
- ret = phy_setup_op(dev, phy_addr, regnum,
- ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val);
+ ret = phy_setup_op(priv, phy_addr, regnum,
+ ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val);
if (!ret)
debug("%s: phy_addr %d, regnum 0x%x, val 0x%x\n", __func__,
return ret;
}
-static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data)
+static u32 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,
regnum, data);
- return phy_setup_op(dev, phy_addr, regnum,
- ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data);
+ return phy_setup_op(priv, phy_addr, regnum,
+ ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data);
}
-static void phy_detection(struct eth_device *dev)
+static int phy_detection(struct eth_device *dev)
{
int i;
u16 phyreg;
struct zynq_gem_priv *priv = dev->priv;
if (priv->phyaddr != -1) {
- phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);
+ phyread(priv, priv->phyaddr, PHY_DETECT_REG, &phyreg);
if ((phyreg != 0xFFFF) &&
((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
/* Found a valid PHY address */
debug("Default phy address %d is valid\n",
priv->phyaddr);
- return;
+ return 0;
} else {
debug("PHY address is not setup correctly %d\n",
priv->phyaddr);
if (priv->phyaddr == -1) {
/* detect the PHY address */
for (i = 31; i >= 0; i--) {
- phyread(dev, i, PHY_DETECT_REG, &phyreg);
+ phyread(priv, i, PHY_DETECT_REG, &phyreg);
if ((phyreg != 0xFFFF) &&
((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
/* Found a valid PHY address */
priv->phyaddr = i;
debug("Found valid phy address, %d\n", i);
- return;
+ return 0;
}
}
}
printf("PHY is not detected\n");
+ return -1;
}
static int zynq_gem_setup_mac(struct eth_device *dev)
static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
{
u32 i;
+ int ret;
unsigned long clk_rate = 0;
struct phy_device *phydev;
struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;
priv->init++;
}
- phy_detection(dev);
+ ret = phy_detection(dev);
+ if (ret) {
+ printf("GEM PHY init failed\n");
+ return ret;
+ }
/* interface - look at tsec */
phydev = phy_connect(priv->bus, priv->phyaddr, dev,
clk_rate = ZYNQ_GEM_FREQUENCY_1000;
break;
case SPEED_100:
- clrsetbits_le32(®s->nwcfg, ZYNQ_GEM_NWCFG_SPEED1000,
- ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100);
+ writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100,
+ ®s->nwcfg);
clk_rate = ZYNQ_GEM_FREQUENCY_100;
break;
case SPEED_10:
return 0;
}
+static int wait_for_bit(const char *func, u32 *reg, const u32 mask,
+ bool set, unsigned int timeout)
+{
+ u32 val;
+ unsigned long start = get_timer(0);
+
+ while (1) {
+ val = readl(reg);
+
+ if (!set)
+ val = ~val;
+
+ if ((val & mask) == mask)
+ return 0;
+
+ if (get_timer(start) > timeout)
+ break;
+
+ udelay(1);
+ }
+
+ debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n",
+ func, reg, mask, set);
+
+ return -ETIMEDOUT;
+}
+
static int zynq_gem_send(struct eth_device *dev, void *ptr, int len)
{
u32 addr, size;
if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
printf("TX buffers exhausted in mid frame\n");
- return 0;
+ return wait_for_bit(__func__, ®s->txsr, ZYNQ_GEM_TSR_DONE,
+ true, 20000);
}
/* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */
uchar reg, ushort *val)
{
struct eth_device *dev = eth_get_dev();
+ struct zynq_gem_priv *priv = dev->priv;
int ret;
- ret = phyread(dev, addr, reg, val);
+ ret = phyread(priv, addr, reg, val);
debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val);
return ret;
}
uchar reg, ushort val)
{
struct eth_device *dev = eth_get_dev();
+ struct zynq_gem_priv *priv = dev->priv;
debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val);
- return phywrite(dev, addr, reg, val);
+ return phywrite(priv, addr, reg, val);
}
int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr,
sprintf(dev->name, "Gem.%lx", base_addr);
dev->iobase = base_addr;
+ priv->iobase = (struct zynq_gem_regs *)base_addr;
dev->init = zynq_gem_init;
dev->halt = zynq_gem_halt;