Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / drivers / net / ucc_geth.c
index 0cf22c4..40c6eba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved.
  *
  * Author: Shlomi Gridish <gridish@freescale.com>
  *        Li Yang <leoli@freescale.com>
@@ -271,7 +271,7 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
                                  u8 num_entries,
                                  u32 thread_size,
                                  u32 thread_alignment,
-                                 enum qe_risc_allocation risc,
+                                 unsigned int risc,
                                  int skip_page_for_first_entry)
 {
        u32 init_enet_offset;
@@ -308,7 +308,7 @@ static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
 static int return_init_enet_entries(struct ucc_geth_private *ugeth,
                                    u32 *p_start,
                                    u8 num_entries,
-                                   enum qe_risc_allocation risc,
+                                   unsigned int risc,
                                    int skip_page_for_first_entry)
 {
        u32 init_enet_offset;
@@ -343,7 +343,7 @@ static int dump_init_enet_entries(struct ucc_geth_private *ugeth,
                                  u32 __iomem *p_start,
                                  u8 num_entries,
                                  u32 thread_size,
-                                 enum qe_risc_allocation risc,
+                                 unsigned int risc,
                                  int skip_page_for_first_entry)
 {
        u32 init_enet_offset;
@@ -1410,6 +1410,9 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
            (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
                upsmr |= UCC_GETH_UPSMR_TBIM;
        }
+       if ((ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII))
+               upsmr |= UCC_GETH_UPSMR_SGMM;
+
        out_be32(&uf_regs->upsmr, upsmr);
 
        /* Disable autonegotiation in tbi mode, because by default it
@@ -1531,6 +1534,49 @@ static void adjust_link(struct net_device *dev)
        spin_unlock_irqrestore(&ugeth->lock, flags);
 }
 
+/* Initialize TBI PHY interface for communicating with the
+ * SERDES lynx PHY on the chip.  We communicate with this PHY
+ * through the MDIO bus on each controller, treating it as a
+ * "normal" PHY at the address found in the UTBIPA register.  We assume
+ * that the UTBIPA register is valid.  Either the MDIO bus code will set
+ * it to a value that doesn't conflict with other PHYs on the bus, or the
+ * value doesn't matter, as there are no other PHYs on the bus.
+ */
+static void uec_configure_serdes(struct net_device *dev)
+{
+       struct ucc_geth_private *ugeth = netdev_priv(dev);
+       struct ucc_geth_info *ug_info = ugeth->ug_info;
+       struct phy_device *tbiphy;
+
+       if (!ug_info->tbi_node) {
+               dev_warn(&dev->dev, "SGMII mode requires that the device "
+                       "tree specify a tbi-handle\n");
+               return;
+       }
+
+       tbiphy = of_phy_find_device(ug_info->tbi_node);
+       if (!tbiphy) {
+               dev_err(&dev->dev, "error: Could not get TBI device\n");
+               return;
+       }
+
+       /*
+        * If the link is already up, we must already be ok, and don't need to
+        * configure and reset the TBI<->SerDes link.  Maybe U-Boot configured
+        * everything for us?  Resetting it takes the link down and requires
+        * several seconds for it to come back.
+        */
+       if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS)
+               return;
+
+       /* Single clk mode, mii mode off(for serdes communication) */
+       phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
+
+       phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
+
+       phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
+}
+
 /* Configure the PHY for dev.
  * returns 0 if success.  -1 if failure
  */
@@ -1554,6 +1600,9 @@ static int init_phy(struct net_device *dev)
                return -ENODEV;
        }
 
+       if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
+               uec_configure_serdes(dev);
+
        phydev->supported &= (ADVERTISED_10baseT_Half |
                                 ADVERTISED_10baseT_Full |
                                 ADVERTISED_100baseT_Half |
@@ -2138,6 +2187,14 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
                return -ENOMEM;
        }
 
+       /* read the number of risc engines, update the riscTx and riscRx
+        * if there are 4 riscs in QE
+        */
+       if (qe_get_num_of_risc() == 4) {
+               ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS;
+               ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS;
+       }
+
        ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
        if (!ugeth->ug_regs) {
                if (netif_msg_probe(ugeth))
@@ -3523,6 +3580,8 @@ static phy_interface_t to_phy_interface(const char *phy_connection_type)
                return PHY_INTERFACE_MODE_RGMII_RXID;
        if (strcasecmp(phy_connection_type, "rtbi") == 0)
                return PHY_INTERFACE_MODE_RTBI;
+       if (strcasecmp(phy_connection_type, "sgmii") == 0)
+               return PHY_INTERFACE_MODE_SGMII;
 
        return PHY_INTERFACE_MODE_MII;
 }
@@ -3567,6 +3626,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
                PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
                PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
                PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
+               PHY_INTERFACE_MODE_SGMII,
        };
 
        ugeth_vdbg("%s: IN", __func__);
@@ -3658,6 +3718,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        }
        ug_info->phy_node = phy;
 
+       /* Find the TBI PHY node.  If it's not there, we don't support SGMII */
+       ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
+
        /* get the phy interface type, or default to MII */
        prop = of_get_property(np, "phy-connection-type", NULL);
        if (!prop) {
@@ -3682,6 +3745,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
                case PHY_INTERFACE_MODE_RGMII_TXID:
                case PHY_INTERFACE_MODE_TBI:
                case PHY_INTERFACE_MODE_RTBI:
+               case PHY_INTERFACE_MODE_SGMII:
                        max_speed = SPEED_1000;
                        break;
                default:
@@ -3698,7 +3762,15 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
                ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT;
                ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT;
                ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4;
-               ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
+
+               /* If QE's snum number is 46 which means we need to support
+                * 4 UECs at 1000Base-T simultaneously, we need to allocate
+                * more Threads to Rx.
+                */
+               if (qe_get_num_of_snums() == 46)
+                       ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6;
+               else
+                       ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
        }
 
        if (netif_msg_probe(&debug))