]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/xilinx_axi_emac.c
Merge git://git.denx.de/u-boot-dm
[u-boot] / drivers / net / xilinx_axi_emac.c
index c03f8f730d3a97ec91193e76ad390f02fe552681..25c66c6098b929f42cdb26d1b3e5ddb247bd6896 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#if !defined(CONFIG_PHYLIB)
-# error AXI_ETHERNET requires PHYLIB
-#endif
-
 /* Link setup */
 #define XAE_EMMC_LINKSPEED_MASK        0xC0000000 /* Link speed */
 #define XAE_EMMC_LINKSPD_10    0x00000000 /* Link Speed mask for 10 Mbit */
@@ -221,11 +217,10 @@ static u32 phywrite(struct axidma_priv *priv, u32 phyaddress, u32 registernum,
        return 0;
 }
 
-/* Setting axi emac and phy to proper setting */
-static int setup_phy(struct udevice *dev)
+static int axiemac_phy_init(struct udevice *dev)
 {
        u16 phyreg;
-       u32 i, speed, emmc_reg, ret;
+       u32 i, ret;
        struct axidma_priv *priv = dev_get_priv(dev);
        struct axi_regs *regs = priv->iobase;
        struct phy_device *phydev;
@@ -237,6 +232,9 @@ static int setup_phy(struct udevice *dev)
                        SUPPORTED_1000baseT_Half |
                        SUPPORTED_1000baseT_Full;
 
+       /* Set default MDIO divisor */
+       out_be32(&regs->mdio_mc, XAE_MDIO_DIV_DFT | XAE_MDIO_MC_MDIOEN_MASK);
+
        if (priv->phyaddr == -1) {
                /* Detect the PHY address */
                for (i = 31; i >= 0; i--) {
@@ -253,12 +251,42 @@ static int setup_phy(struct udevice *dev)
        }
 
        /* Interface - look at tsec */
-       phydev = phy_connect(priv->bus, priv->phyaddr, dev, 0);
+       phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
 
        phydev->supported &= supported;
        phydev->advertising = phydev->supported;
        priv->phydev = phydev;
        phy_config(phydev);
+
+       return 0;
+}
+
+/* Setting axi emac and phy to proper setting */
+static int setup_phy(struct udevice *dev)
+{
+       u16 temp;
+       u32 speed, emmc_reg, ret;
+       struct axidma_priv *priv = dev_get_priv(dev);
+       struct axi_regs *regs = priv->iobase;
+       struct phy_device *phydev = priv->phydev;
+
+       if (priv->interface == PHY_INTERFACE_MODE_SGMII) {
+               /*
+                * In SGMII cases the isolate bit might set
+                * after DMA and ethernet resets and hence
+                * check and clear if set.
+                */
+               ret = phyread(priv, priv->phyaddr, MII_BMCR, &temp);
+               if (ret)
+                       return 0;
+               if (temp & BMCR_ISOLATE) {
+                       temp &= ~BMCR_ISOLATE;
+                       ret = phywrite(priv, priv->phyaddr, MII_BMCR, temp);
+                       if (ret)
+                               return 0;
+               }
+       }
+
        if (phy_startup(phydev)) {
                printf("axiemac: could not initialize PHY %s\n",
                       phydev->dev->name);
@@ -302,7 +330,7 @@ static int setup_phy(struct udevice *dev)
 }
 
 /* STOP DMA transfers */
-static void axiemac_halt(struct udevice *dev)
+static void axiemac_stop(struct udevice *dev)
 {
        struct axidma_priv *priv = dev_get_priv(dev);
        u32 temp;
@@ -362,7 +390,7 @@ static int axi_ethernet_init(struct axidma_priv *priv)
        return 0;
 }
 
-static int axiemac_setup_mac(struct udevice *dev)
+static int axiemac_write_hwaddr(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct axidma_priv *priv = dev_get_priv(dev);
@@ -402,7 +430,7 @@ static void axi_dma_init(struct axidma_priv *priv)
                printf("%s: Timeout\n", __func__);
 }
 
-static int axiemac_init(struct udevice *dev)
+static int axiemac_start(struct udevice *dev)
 {
        struct axidma_priv *priv = dev_get_priv(dev);
        struct axi_regs *regs = priv->iobase;
@@ -456,7 +484,7 @@ static int axiemac_init(struct udevice *dev)
 
        /* PHY setup */
        if (!setup_phy(dev)) {
-               axiemac_halt(dev);
+               axiemac_stop(dev);
                return -1;
        }
 
@@ -557,9 +585,14 @@ static int axiemac_recv(struct udevice *dev, int flags, uchar **packetp)
 #ifdef DEBUG
        print_buffer(&rxframe, &rxframe[0], 1, length, 16);
 #endif
-       /* Pass the received frame up for processing */
-       if (length)
-               net_process_received_packet(rxframe, length);
+
+       *packetp = rxframe;
+       return length;
+}
+
+static int axiemac_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+       struct axidma_priv *priv = dev_get_priv(dev);
 
 #ifdef DEBUG
        /* It is useful to clear buffer to be sure that it is consistent */
@@ -615,12 +648,13 @@ static int axi_emac_probe(struct udevice *dev)
        priv->bus->read = axiemac_miiphy_read;
        priv->bus->write = axiemac_miiphy_write;
        priv->bus->priv = priv;
-       strcpy(priv->bus->name, "axi_emac");
 
-       ret = mdio_register(priv->bus);
+       ret = mdio_register_seq(priv->bus, dev->seq);
        if (ret)
                return ret;
 
+       axiemac_phy_init(dev);
+
        return 0;
 }
 
@@ -636,24 +670,26 @@ static int axi_emac_remove(struct udevice *dev)
 }
 
 static const struct eth_ops axi_emac_ops = {
-       .start                  = axiemac_init,
+       .start                  = axiemac_start,
        .send                   = axiemac_send,
        .recv                   = axiemac_recv,
-       .stop                   = axiemac_halt,
-       .write_hwaddr           = axiemac_setup_mac,
+       .free_pkt               = axiemac_free_pkt,
+       .stop                   = axiemac_stop,
+       .write_hwaddr           = axiemac_write_hwaddr,
 };
 
 static int axi_emac_ofdata_to_platdata(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct axidma_priv *priv = dev_get_priv(dev);
+       int node = dev_of_offset(dev);
        int offset = 0;
        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 axi_regs *)pdata->iobase;
 
-       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+       offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
                                       "axistream-connected");
        if (offset <= 0) {
                printf("%s: axistream is not found\n", __func__);
@@ -670,16 +706,15 @@ static int axi_emac_ofdata_to_platdata(struct udevice *dev)
 
        priv->phyaddr = -1;
 
-       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
-                                      "phy-handle");
+       offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
        if (offset > 0)
                priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
 
-       phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+       phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
        if (phy_mode)
                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
        if (pdata->phy_interface == -1) {
-               debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+               printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
                return -EINVAL;
        }
        priv->interface = pdata->phy_interface;