Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-2.6-microblaze.git] / drivers / net / ethernet / microchip / lan966x / lan966x_main.c
index 95830e3..afec115 100644 (file)
@@ -24,9 +24,6 @@
 #define XTR_NOT_READY                  0x07000080U
 #define XTR_VALID_BYTES(x)             (4 - (((x) >> 24) & 3))
 
-#define READL_SLEEP_US                 10
-#define READL_TIMEOUT_US               100000000
-
 #define IO_RANGES 2
 
 static const struct of_device_id lan966x_match[] = {
@@ -43,6 +40,7 @@ struct lan966x_main_io_resource {
 
 static const struct lan966x_main_io_resource lan966x_main_iomap[] =  {
        { TARGET_CPU,                   0xc0000, 0 }, /* 0xe00c0000 */
+       { TARGET_FDMA,                  0xc0400, 0 }, /* 0xe00c0400 */
        { TARGET_ORG,                         0, 1 }, /* 0xe2000000 */
        { TARGET_GCB,                    0x4000, 1 }, /* 0xe2004000 */
        { TARGET_QS,                     0x8000, 1 }, /* 0xe2008000 */
@@ -343,7 +341,10 @@ static int lan966x_port_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        spin_lock(&lan966x->tx_lock);
-       err = lan966x_port_ifh_xmit(skb, ifh, dev);
+       if (port->lan966x->fdma)
+               err = lan966x_fdma_xmit(skb, ifh, dev);
+       else
+               err = lan966x_port_ifh_xmit(skb, ifh, dev);
        spin_unlock(&lan966x->tx_lock);
 
        return err;
@@ -353,12 +354,24 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct lan966x_port *port = netdev_priv(dev);
        struct lan966x *lan966x = port->lan966x;
+       int old_mtu = dev->mtu;
+       int err;
 
        lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu),
               lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
        dev->mtu = new_mtu;
 
-       return 0;
+       if (!lan966x->fdma)
+               return 0;
+
+       err = lan966x_fdma_change_mtu(lan966x);
+       if (err) {
+               lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(old_mtu),
+                      lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
+               dev->mtu = old_mtu;
+       }
+
+       return err;
 }
 
 static int lan966x_mc_unsync(struct net_device *dev, const unsigned char *addr)
@@ -432,8 +445,7 @@ bool lan966x_netdevice_check(const struct net_device *dev)
        return dev->netdev_ops == &lan966x_port_netdev_ops;
 }
 
-static bool lan966x_hw_offload(struct lan966x *lan966x, u32 port,
-                              struct sk_buff *skb)
+bool lan966x_hw_offload(struct lan966x *lan966x, u32 port, struct sk_buff *skb)
 {
        u32 val;
 
@@ -520,7 +532,7 @@ static int lan966x_rx_frame_word(struct lan966x *lan966x, u8 grp, u32 *rval)
        }
 }
 
-static void lan966x_ifh_get_src_port(void *ifh, u64 *src_port)
+void lan966x_ifh_get_src_port(void *ifh, u64 *src_port)
 {
        packing(ifh, src_port, IFH_POS_SRCPORT + IFH_WID_SRCPORT - 1,
                IFH_POS_SRCPORT, IFH_LEN * 4, UNPACK, 0);
@@ -532,7 +544,7 @@ static void lan966x_ifh_get_len(void *ifh, u64 *len)
                IFH_POS_LEN, IFH_LEN * 4, UNPACK, 0);
 }
 
-static void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp)
+void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp)
 {
        packing(ifh, timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1,
                IFH_POS_TIMESTAMP, IFH_LEN * 4, UNPACK, 0);
@@ -652,6 +664,9 @@ static void lan966x_cleanup_ports(struct lan966x *lan966x)
                if (port->dev)
                        unregister_netdev(port->dev);
 
+               if (lan966x->fdma && lan966x->fdma_ndev == port->dev)
+                       lan966x_fdma_netdev_deinit(lan966x, port->dev);
+
                if (port->phylink) {
                        rtnl_lock();
                        lan966x_port_stop(port->dev);
@@ -672,6 +687,9 @@ static void lan966x_cleanup_ports(struct lan966x *lan966x)
                lan966x->ana_irq = -ENXIO;
        }
 
+       if (lan966x->fdma)
+               devm_free_irq(lan966x->dev, lan966x->fdma_irq, lan966x);
+
        if (lan966x->ptp_irq)
                devm_free_irq(lan966x->dev, lan966x->ptp_irq, lan966x);
 }
@@ -802,12 +820,12 @@ static void lan966x_init(struct lan966x *lan966x)
        /* Do byte-swap and expect status after last data word
         * Extraction: Mode: manual extraction) | Byte_swap
         */
-       lan_wr(QS_XTR_GRP_CFG_MODE_SET(1) |
+       lan_wr(QS_XTR_GRP_CFG_MODE_SET(lan966x->fdma ? 2 : 1) |
               QS_XTR_GRP_CFG_BYTE_SWAP_SET(1),
               lan966x, QS_XTR_GRP_CFG(0));
 
        /* Injection: Mode: manual injection | Byte_swap */
-       lan_wr(QS_INJ_GRP_CFG_MODE_SET(1) |
+       lan_wr(QS_INJ_GRP_CFG_MODE_SET(lan966x->fdma ? 2 : 1) |
               QS_INJ_GRP_CFG_BYTE_SWAP_SET(1),
               lan966x, QS_INJ_GRP_CFG(0));
 
@@ -1029,6 +1047,17 @@ static int lan966x_probe(struct platform_device *pdev)
                lan966x->ptp = 1;
        }
 
+       lan966x->fdma_irq = platform_get_irq_byname(pdev, "fdma");
+       if (lan966x->fdma_irq > 0) {
+               err = devm_request_irq(&pdev->dev, lan966x->fdma_irq,
+                                      lan966x_fdma_irq_handler, 0,
+                                      "fdma irq", lan966x);
+               if (err)
+                       return dev_err_probe(&pdev->dev, err, "Unable to use fdma irq");
+
+               lan966x->fdma = true;
+       }
+
        /* init switch */
        lan966x_init(lan966x);
        lan966x_stats_init(lan966x);
@@ -1067,8 +1096,15 @@ static int lan966x_probe(struct platform_device *pdev)
        if (err)
                goto cleanup_fdb;
 
+       err = lan966x_fdma_init(lan966x);
+       if (err)
+               goto cleanup_ptp;
+
        return 0;
 
+cleanup_ptp:
+       lan966x_ptp_deinit(lan966x);
+
 cleanup_fdb:
        lan966x_fdb_deinit(lan966x);
 
@@ -1088,6 +1124,7 @@ static int lan966x_remove(struct platform_device *pdev)
 {
        struct lan966x *lan966x = platform_get_drvdata(pdev);
 
+       lan966x_fdma_deinit(lan966x);
        lan966x_cleanup_ports(lan966x);
 
        cancel_delayed_work_sync(&lan966x->stats_work);