]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/net/fm/eth.c
Merge branch 'master' of git://www.denx.de/git/u-boot-imx
[karo-tx-uboot.git] / drivers / net / fm / eth.c
index f7ed850c913a4f77748a1e8d316043eb5088ce2e..f1e39b982a2a01091715581ac7280370a8a41c03 100644 (file)
@@ -1,21 +1,8 @@
 /*
- * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
  *     Dave Liu <daveliu@freescale.com>
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 #include <common.h>
 #include <asm/io.h>
@@ -28,6 +15,7 @@
 #include <phy.h>
 #include <asm/fsl_dtsec.h>
 #include <asm/fsl_tgec.h>
+#include <asm/fsl_memac.h>
 
 #include "fm.h"
 
@@ -45,8 +33,37 @@ static int num_controllers;
                        TBICR_FULL_DUPLEX | TBICR_SPEED1_SET)
 
 /* Configure the TBI for SGMII operation */
-void dtsec_configure_serdes(struct fm_eth *priv)
+static void dtsec_configure_serdes(struct fm_eth *priv)
 {
+#ifdef CONFIG_SYS_FMAN_V3
+       u32 value;
+       struct mii_dev bus;
+       bus.priv = priv->mac->phyregs;
+       bool sgmii_2500 = (priv->enet_if ==
+                       PHY_INTERFACE_MODE_SGMII_2500) ? true : false;
+
+       /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
+       value = PHY_SGMII_IF_MODE_SGMII;
+       if (!sgmii_2500)
+               value |= PHY_SGMII_IF_MODE_AN;
+
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
+
+       /* Dev ability according to SGMII specification */
+       value = PHY_SGMII_DEV_ABILITY_SGMII;
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
+
+       /* Adjust link timer for SGMII  -
+       1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40 */
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x3);
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xd40);
+
+       /* Restart AN */
+       value = PHY_SGMII_CR_DEF_VAL;
+       if (!sgmii_2500)
+               value |= PHY_SGMII_CR_RESET_AN;
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
+#else
        struct dtsec *regs = priv->mac->base;
        struct tsec_mii_mng *phyregs = priv->mac->phyregs;
 
@@ -60,17 +77,21 @@ void dtsec_configure_serdes(struct fm_eth *priv)
                        TBIANA_SGMII_ACK);
        tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0,
                        TBI_CR, TBICR_SETTINGS);
+#endif
 }
 
 static void dtsec_init_phy(struct eth_device *dev)
 {
        struct fm_eth *fm_eth = dev->priv;
-       struct dtsec *regs = (struct dtsec *)fm_eth->mac->base;
+#ifndef CONFIG_SYS_FMAN_V3
+       struct dtsec *regs = (struct dtsec *)CONFIG_SYS_FSL_FM1_DTSEC1_ADDR;
 
        /* Assign a Physical address to the TBI */
        out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+#endif
 
-       if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII)
+       if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII ||
+           fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII_2500)
                dtsec_configure_serdes(fm_eth);
 }
 
@@ -328,7 +349,9 @@ static int fm_eth_startup(struct fm_eth *fm_eth)
        mac->init_mac(mac);
 
        /* For some reason we need to set SPEED_100 */
-       if ((fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII) && mac->set_if_mode)
+       if (((fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII) ||
+            (fm_eth->enet_if == PHY_INTERFACE_MODE_QSGMII)) &&
+             mac->set_if_mode)
                mac->set_if_mode(mac, fm_eth->enet_if, SPEED_100);
 
        /* init bmi rx port, IM mode and disable */
@@ -363,6 +386,9 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
 {
        struct fm_eth *fm_eth;
        struct fsl_enet_mac *mac;
+#ifdef CONFIG_PHYLIB
+       int ret;
+#endif
 
        fm_eth = (struct fm_eth *)dev->priv;
        mac = fm_eth->mac;
@@ -384,7 +410,11 @@ static int fm_eth_open(struct eth_device *dev, bd_t *bd)
        fmc_tx_port_graceful_stop_disable(fm_eth);
 
 #ifdef CONFIG_PHYLIB
-       phy_startup(fm_eth->phydev);
+       ret = phy_startup(fm_eth->phydev);
+       if (ret) {
+               printf("%s: Could not initialize\n", fm_eth->phydev->dev->name);
+               return ret;
+       }
 #else
        fm_eth->phydev->speed = SPEED_1000;
        fm_eth->phydev->link = 1;
@@ -420,7 +450,7 @@ static void fm_eth_halt(struct eth_device *dev)
        phy_shutdown(fm_eth->phydev);
 }
 
-static int fm_eth_send(struct eth_device *dev, volatile void *buf, int len)
+static int fm_eth_send(struct eth_device *dev, void *buf, int len)
 {
        struct fm_eth *fm_eth;
        struct fm_port_global_pram *pram;
@@ -534,6 +564,23 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
 
        num = fm_eth->num;
 
+#ifdef CONFIG_SYS_FMAN_V3
+#ifndef CONFIG_FSL_FM_10GEC_REGULAR_NOTATION
+       if (fm_eth->type == FM_ETH_10G_E) {
+               /* 10GEC1/10GEC2 use mEMAC9/mEMAC10 on T2080/T4240.
+                * 10GEC3/10GEC4 use mEMAC1/mEMAC2 on T2080.
+                * 10GEC1 uses mEMAC1 on T1024.
+                * so it needs to change the num.
+                */
+               if (fm_eth->num >= 2)
+                       num -= 2;
+               else
+                       num += 8;
+       }
+#endif
+       base = &reg->memac[num].fm_memac;
+       phyregs = &reg->memac[num].fm_memac_mdio;
+#else
        /* Get the mac registers base address */
        if (fm_eth->type == FM_ETH_1G_E) {
                base = &reg->mac_1g[num].fm_dtesc;
@@ -542,6 +589,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
                base = &reg->mac_10g[num].fm_10gec;
                phyregs = &reg->mac_10g[num].fm_10gec_mdio;
        }
+#endif
 
        /* alloc mac controller */
        mac = malloc(sizeof(struct fsl_enet_mac));
@@ -552,10 +600,14 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
        /* save the mac to fm_eth struct */
        fm_eth->mac = mac;
 
+#ifdef CONFIG_SYS_FMAN_V3
+       init_memac(mac, base, phyregs, MAX_RXBUF_LEN);
+#else
        if (fm_eth->type == FM_ETH_1G_E)
                init_dtsec(mac, base, phyregs, MAX_RXBUF_LEN);
        else
                init_tgec(mac, base, phyregs, MAX_RXBUF_LEN);
+#endif
 
        return 1;
 }