net: spread __net_init, __net_exit
[safe/jmp/linux-2.6] / drivers / net / davinci_emac.c
index 2df8fb0..33c4fe2 100644 (file)
@@ -164,16 +164,14 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 # define EMAC_MBP_MCASTCHAN(ch)                ((ch) & 0x7)
 
 /* EMAC mac_control register */
-#define EMAC_MACCONTROL_TXPTYPE                (0x200)
-#define EMAC_MACCONTROL_TXPACEEN       (0x40)
-#define EMAC_MACCONTROL_MIIEN          (0x20)
-#define EMAC_MACCONTROL_GIGABITEN      (0x80)
-#define EMAC_MACCONTROL_GIGABITEN_SHIFT (7)
-#define EMAC_MACCONTROL_FULLDUPLEXEN   (0x1)
+#define EMAC_MACCONTROL_TXPTYPE                BIT(9)
+#define EMAC_MACCONTROL_TXPACEEN       BIT(6)
+#define EMAC_MACCONTROL_GMIIEN         BIT(5)
+#define EMAC_MACCONTROL_GIGABITEN      BIT(7)
+#define EMAC_MACCONTROL_FULLDUPLEXEN   BIT(0)
 #define EMAC_MACCONTROL_RMIISPEED_MASK BIT(15)
 
 /* GIGABIT MODE related bits */
-#define EMAC_DM646X_MACCONTORL_GMIIEN  BIT(5)
 #define EMAC_DM646X_MACCONTORL_GIG     BIT(7)
 #define EMAC_DM646X_MACCONTORL_GIGFORCE        BIT(17)
 
@@ -192,14 +190,16 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_RX_BUFFER_OFFSET_MASK     (0xFFFF)
 
 /* MAC_IN_VECTOR (0x180) register bit fields */
-#define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT           (0x20000)
-#define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT       (0x10000)
-#define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC         (0x0100)
-#define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC         (0x01)
+#define EMAC_DM644X_MAC_IN_VECTOR_HOST_INT     BIT(17)
+#define EMAC_DM644X_MAC_IN_VECTOR_STATPEND_INT BIT(16)
+#define EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC   BIT(8)
+#define EMAC_DM644X_MAC_IN_VECTOR_TX_INT_VEC   BIT(0)
 
 /** NOTE:: For DM646x the IN_VECTOR has changed */
 #define EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC   BIT(EMAC_DEF_RX_CH)
 #define EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC   BIT(16 + EMAC_DEF_TX_CH)
+#define EMAC_DM646X_MAC_IN_VECTOR_HOST_INT     BIT(26)
+#define EMAC_DM646X_MAC_IN_VECTOR_STATPEND_INT BIT(27)
 
 /* CPPI bit positions */
 #define EMAC_CPPI_SOP_BIT              BIT(31)
@@ -330,6 +330,9 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DM646X_MAC_EOI_C0_RXEN    (0x01)
 #define EMAC_DM646X_MAC_EOI_C0_TXEN    (0x02)
 
+/* EMAC Stats Clear Mask */
+#define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
+
 /** net_buf_obj: EMAC network bufferdata structure
  *
  * EMAC network buffer data structure
@@ -744,8 +747,7 @@ static void emac_update_phystatus(struct emac_priv *priv)
 
        if (priv->speed == SPEED_1000 && (priv->version == EMAC_VERSION_2)) {
                mac_control = emac_read(EMAC_MACCONTROL);
-               mac_control |= (EMAC_DM646X_MACCONTORL_GMIIEN |
-                               EMAC_DM646X_MACCONTORL_GIG |
+               mac_control |= (EMAC_DM646X_MACCONTORL_GIG |
                                EMAC_DM646X_MACCONTORL_GIGFORCE);
        } else {
                /* Clear the GIG bit and GIGFORCE bit */
@@ -1820,11 +1822,19 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
        struct device *emac_dev = &priv->ndev->dev;
        struct sockaddr *sa = addr;
 
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EINVAL;
+
        /* Store mac addr in priv and rx channel and set it in EMAC hw */
        memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
-       memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
        memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
-       emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+
+       /* If the interface is down - rxch is NULL. */
+       /* MAC address is configured only after the interface is enabled. */
+       if (netif_running(ndev)) {
+               memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
+               emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+       }
 
        if (netif_msg_drv(priv))
                dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n",
@@ -1912,7 +1922,6 @@ static int emac_net_rx_cb(struct emac_priv *priv,
        skb_put(p_skb, net_pkt_list->pkt_length);
        EMAC_CACHE_INVALIDATE((unsigned long)p_skb->data, p_skb->len);
        p_skb->protocol = eth_type_trans(p_skb, priv->ndev);
-       p_skb->dev->last_rx = jiffies;
        netif_receive_skb(p_skb);
        priv->net_dev_stats.rx_bytes += net_pkt_list->pkt_length;
        priv->net_dev_stats.rx_packets++;
@@ -2095,7 +2104,7 @@ static int emac_hw_enable(struct emac_priv *priv)
 
        /* Enable MII */
        val = emac_read(EMAC_MACCONTROL);
-       val |= (EMAC_MACCONTROL_MIIEN);
+       val |= (EMAC_MACCONTROL_GMIIEN);
        emac_write(EMAC_MACCONTROL, val);
 
        /* Enable NAPI and interrupts */
@@ -2127,9 +2136,6 @@ static int emac_poll(struct napi_struct *napi, int budget)
        u32 status = 0;
        u32 num_pkts = 0;
 
-       if (!netif_running(ndev))
-               return 0;
-
        /* Check interrupt vectors and call packet processing */
        status = emac_read(EMAC_MACINVECTOR);
 
@@ -2160,7 +2166,11 @@ static int emac_poll(struct napi_struct *napi, int budget)
                emac_int_enable(priv);
        }
 
-       if (unlikely(status & EMAC_DM644X_MAC_IN_VECTOR_HOST_INT)) {
+       mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT;
+       if (priv->version == EMAC_VERSION_2)
+               mask = EMAC_DM646X_MAC_IN_VECTOR_HOST_INT;
+
+       if (unlikely(status & mask)) {
                u32 ch, cause;
                dev_err(emac_dev, "DaVinci EMAC: Fatal Hardware Error\n");
                netif_stop_queue(ndev);
@@ -2204,7 +2214,7 @@ void emac_poll_controller(struct net_device *ndev)
        struct emac_priv *priv = netdev_priv(ndev);
 
        emac_int_disable(priv);
-       emac_irq(ndev->irq, priv);
+       emac_irq(ndev->irq, ndev);
        emac_int_enable(priv);
 }
 #endif
@@ -2262,7 +2272,7 @@ static int emac_mii_reset(struct mii_bus *bus)
        unsigned int clk_div;
        int mdio_bus_freq = emac_bus_frequency;
 
-       if (mdio_max_freq & mdio_bus_freq)
+       if (mdio_max_freq && mdio_bus_freq)
                clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
        else
                clk_div = 0xFF;
@@ -2534,40 +2544,49 @@ static int emac_dev_stop(struct net_device *ndev)
 static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
 {
        struct emac_priv *priv = netdev_priv(ndev);
+       u32 mac_control;
+       u32 stats_clear_mask;
 
        /* update emac hardware stats and reset the registers*/
 
+       mac_control = emac_read(EMAC_MACCONTROL);
+
+       if (mac_control & EMAC_MACCONTROL_GMIIEN)
+               stats_clear_mask = EMAC_STATS_CLR_MASK;
+       else
+               stats_clear_mask = 0;
+
        priv->net_dev_stats.multicast += emac_read(EMAC_RXMCASTFRAMES);
-       emac_write(EMAC_RXMCASTFRAMES, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXMCASTFRAMES, stats_clear_mask);
 
        priv->net_dev_stats.collisions += (emac_read(EMAC_TXCOLLISION) +
                                           emac_read(EMAC_TXSINGLECOLL) +
                                           emac_read(EMAC_TXMULTICOLL));
-       emac_write(EMAC_TXCOLLISION, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_TXSINGLECOLL, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_TXMULTICOLL, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXCOLLISION, stats_clear_mask);
+       emac_write(EMAC_TXSINGLECOLL, stats_clear_mask);
+       emac_write(EMAC_TXMULTICOLL, stats_clear_mask);
 
        priv->net_dev_stats.rx_length_errors += (emac_read(EMAC_RXOVERSIZED) +
                                                emac_read(EMAC_RXJABBER) +
                                                emac_read(EMAC_RXUNDERSIZED));
-       emac_write(EMAC_RXOVERSIZED, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXJABBER, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXUNDERSIZED, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXOVERSIZED, stats_clear_mask);
+       emac_write(EMAC_RXJABBER, stats_clear_mask);
+       emac_write(EMAC_RXUNDERSIZED, stats_clear_mask);
 
        priv->net_dev_stats.rx_over_errors += (emac_read(EMAC_RXSOFOVERRUNS) +
                                               emac_read(EMAC_RXMOFOVERRUNS));
-       emac_write(EMAC_RXSOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
-       emac_write(EMAC_RXMOFOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXSOFOVERRUNS, stats_clear_mask);
+       emac_write(EMAC_RXMOFOVERRUNS, stats_clear_mask);
 
        priv->net_dev_stats.rx_fifo_errors += emac_read(EMAC_RXDMAOVERRUNS);
-       emac_write(EMAC_RXDMAOVERRUNS, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_RXDMAOVERRUNS, stats_clear_mask);
 
        priv->net_dev_stats.tx_carrier_errors +=
                emac_read(EMAC_TXCARRIERSENSE);
-       emac_write(EMAC_TXCARRIERSENSE, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask);
 
        priv->net_dev_stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN);
-       emac_write(EMAC_TXUNDERRUN, EMAC_ALL_MULTI_REG_VALUE);
+       emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
 
        return &priv->net_dev_stats;
 }
@@ -2692,6 +2711,8 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        SET_ETHTOOL_OPS(ndev, &ethtool_ops);
        netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
 
+       clk_enable(emac_clk);
+
        /* register the network device */
        SET_NETDEV_DEV(ndev, &pdev->dev);
        rc = register_netdev(ndev);
@@ -2701,7 +2722,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
                goto netdev_reg_err;
        }
 
-       clk_enable(emac_clk);
 
        /* MII/Phy intialisation, mdio bus registration */
        emac_mii = mdiobus_alloc();
@@ -2741,6 +2761,7 @@ mdiobus_quit:
 
 netdev_reg_err:
 mdio_alloc_err:
+       clk_disable(emac_clk);
 no_irq_res:
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, res->end - res->start + 1);
@@ -2784,11 +2805,33 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
        return 0;
 }
 
+static
+int davinci_emac_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev))
+               emac_dev_stop(dev);
+
+       clk_disable(emac_clk);
+
+       return 0;
+}
+
+static int davinci_emac_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       clk_enable(emac_clk);
+
+       if (netif_running(dev))
+               emac_dev_open(dev);
+
+       return 0;
+}
+
 /**
  * davinci_emac_driver: EMAC platform driver structure
- *
- * We implement only probe and remove functions - suspend/resume and
- * others not supported by this module
  */
 static struct platform_driver davinci_emac_driver = {
        .driver = {
@@ -2797,6 +2840,8 @@ static struct platform_driver davinci_emac_driver = {
        },
        .probe = davinci_emac_probe,
        .remove = __devexit_p(davinci_emac_remove),
+       .suspend = davinci_emac_suspend,
+       .resume = davinci_emac_resume,
 };
 
 /**
@@ -2809,7 +2854,7 @@ static int __init davinci_emac_init(void)
 {
        return platform_driver_register(&davinci_emac_driver);
 }
-module_init(davinci_emac_init);
+late_initcall(davinci_emac_init);
 
 /**
  * davinci_emac_exit: EMAC driver module exit