ltq-atm/ltq-ptm: re-enable/fix reset_ppe() functionality for VR9
[openwrt/staging/wigyori.git] / package / kernel / lantiq / ltq-ptm / src / ifxmips_ptm_vdsl.c
index 1b9b710bfb7359ddb1b10c39c5b72c57982b6aba..9e24c69d943e995c16916e325a0583648a2be8e5 100644 (file)
@@ -32,6 +32,9 @@
 #include <linux/ioctl.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
 
 #include "ifxmips_ptm_vdsl.h"
 #include <lantiq_soc.h>
@@ -73,6 +76,9 @@ static int ptm_stop(struct net_device *);
   static unsigned int ptm_poll(int, unsigned int);
   static int ptm_napi_poll(struct napi_struct *, int);
 static int ptm_hard_start_xmit(struct sk_buff *, struct net_device *);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0))
+static int ptm_change_mtu(struct net_device *, int);
+#endif
 static int ptm_ioctl(struct net_device *, struct ifreq *, int);
 static void ptm_tx_timeout(struct net_device *);
 
@@ -113,13 +119,15 @@ static struct net_device_ops g_ptm_netdev_ops = {
     .ndo_start_xmit      = ptm_hard_start_xmit,
     .ndo_validate_addr   = eth_validate_addr,
     .ndo_set_mac_address = eth_mac_addr,
-    .ndo_change_mtu      = eth_change_mtu,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0))
+    .ndo_change_mtu      = ptm_change_mtu,
+#endif
     .ndo_do_ioctl        = ptm_ioctl,
     .ndo_tx_timeout      = ptm_tx_timeout,
 };
 
 static struct net_device *g_net_dev[1] = {0};
-static char *g_net_dev_name[1] = {"ptm0"};
+static char *g_net_dev_name[1] = {"dsl0"};
 
 static int g_ptm_prio_queue_map[8];
 
@@ -136,7 +144,13 @@ unsigned int ifx_ptm_dbg_enable = DBG_ENABLE_MASK_ERR;
 
 static void ptm_setup(struct net_device *dev, int ndev)
 {
+    netif_carrier_off(dev);
+
     dev->netdev_ops      = &g_ptm_netdev_ops;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0))
+    /* Allow up to 1508 bytes, for RFC4638 */
+    dev->max_mtu         = ETH_DATA_LEN + 8;
+#endif
     netif_napi_add(dev, &g_ptm_priv_data.itf[ndev].napi, ptm_napi_poll, 16);
     dev->watchdog_timeo  = ETH_WATCHDOG_TIMEOUT;
 
@@ -214,7 +228,9 @@ static unsigned int ptm_poll(int ndev, unsigned int work_to_do)
             skb->dev = g_net_dev[0];
             skb->protocol = eth_type_trans(skb, skb->dev);
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0))
             g_net_dev[0]->last_rx = jiffies;
+#endif
 
             netif_receive_skb(skb);
 
@@ -285,7 +301,11 @@ static int ptm_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
     /*  allocate descriptor */
     desc_base = get_tx_desc(0, &f_full);
     if ( f_full ) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
+        netif_trans_update(dev);
+#else
         dev->trans_start = jiffies;
+#endif
         netif_stop_queue(dev);
 
         IFX_REG_W32_MASK(0, 1 << 17, MBOX_IGU1_ISRC);
@@ -344,7 +364,11 @@ static int ptm_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
     wmb();
     *(volatile unsigned int *)desc = *(unsigned int *)&reg_desc;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
+    netif_trans_update(dev);
+#else
     dev->trans_start = jiffies;
+#endif
 
     return 0;
 
@@ -355,6 +379,17 @@ PTM_HARD_START_XMIT_FAIL:
     return 0;
 }
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0))
+static int ptm_change_mtu(struct net_device *dev, int mtu)
+{
+       /* Allow up to 1508 bytes, for RFC4638 */
+        if (mtu < 68 || mtu > ETH_DATA_LEN + 8)
+                return -EINVAL;
+        dev->mtu = mtu;
+        return 0;
+}
+#endif
+
 static int ptm_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
     ASSERT(dev == g_net_dev[0], "incorrect device");
@@ -888,6 +923,8 @@ static inline void clear_tables(void)
 
 static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr)
 {
+       int i;
+
        ASSERT(port_cell != NULL, "port_cell is NULL");
        ASSERT(xdata_addr != NULL, "xdata_addr is NULL");
 
@@ -896,6 +933,9 @@ static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr
 
        g_showtime = 1;
 
+       for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ )
+               netif_carrier_on(g_net_dev[i]);
+
        IFX_REG_W32(0x0F, UTP_CFG);
 
        //#ifdef CONFIG_VR9
@@ -909,6 +949,8 @@ static int ptm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr
 
 static int ptm_showtime_exit(void)
 {
+       int i;
+
        if ( !g_showtime )
                return -1;
 
@@ -918,6 +960,9 @@ static int ptm_showtime_exit(void)
 
        IFX_REG_W32(0x00, UTP_CFG);
 
+       for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ )
+               netif_carrier_off(g_net_dev[i]);
+
        g_showtime = 0;
 
        //  TODO: ReTX clean state
@@ -928,9 +973,21 @@ static int ptm_showtime_exit(void)
        return 0;
 }
 
+static const struct of_device_id ltq_ptm_match[] = {
+#ifdef CONFIG_DANUBE
+       { .compatible = "lantiq,ppe-danube", .data = NULL },
+#elif defined CONFIG_AMAZON_SE
+       { .compatible = "lantiq,ppe-ase", .data = NULL },
+#elif defined CONFIG_AR9
+       { .compatible = "lantiq,ppe-arx100", .data = NULL },
+#elif defined CONFIG_VR9
+       { .compatible = "lantiq,ppe-xrx200", .data = NULL },
+#endif
+       {},
+};
+MODULE_DEVICE_TABLE(of, ltq_ptm_match);
 
-
-static int ifx_ptm_init(void)
+static int ltq_ptm_probe(struct platform_device *pdev)
 {
     int ret;
     int i;
@@ -943,7 +1000,7 @@ static int ifx_ptm_init(void)
         goto INIT_PRIV_DATA_FAIL;
     }
 
-    ifx_ptm_init_chip();
+    ifx_ptm_init_chip(pdev);
     ret = init_tables();
     if ( ret != 0 ) {
         err("INIT_TABLES_FAIL");
@@ -951,7 +1008,7 @@ static int ifx_ptm_init(void)
     }
 
     for ( i = 0; i < ARRAY_SIZE(g_net_dev); i++ ) {
-        g_net_dev[i] = alloc_netdev(0, g_net_dev_name[i], ether_setup);
+        g_net_dev[i] = alloc_netdev(0, g_net_dev_name[i], NET_NAME_UNKNOWN, ether_setup);
         if ( g_net_dev[i] == NULL )
             goto ALLOC_NETDEV_FAIL;
         ptm_setup(g_net_dev[i], i);
@@ -964,7 +1021,11 @@ static int ifx_ptm_init(void)
     }
 
     /*  register interrupt handler  */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+    ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, 0, "ptm_mailbox_isr", &g_ptm_priv_data);
+#else
     ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, IRQF_DISABLED, "ptm_mailbox_isr", &g_ptm_priv_data);
+#endif
     if ( ret ) {
         if ( ret == -EBUSY ) {
             err("IRQ may be occupied by other driver, please reconfig to disable it.");
@@ -987,7 +1048,10 @@ static int ifx_ptm_init(void)
     enable_irq(PPE_MAILBOX_IGU1_INT);
 
     ifx_mei_atm_showtime_check(&g_showtime, &port_cell, &g_xdata_addr);
-    
+    if ( g_showtime ) {
+       ptm_showtime_enter(&port_cell, &g_xdata_addr);
+    }
+
     ifx_mei_atm_showtime_enter = ptm_showtime_enter;
     ifx_mei_atm_showtime_exit  = ptm_showtime_exit;
 
@@ -1018,7 +1082,7 @@ INIT_PRIV_DATA_FAIL:
     return ret;
 }
 
-static void __exit ifx_ptm_exit(void)
+static int ltq_ptm_remove(struct platform_device *pdev)
 {
     int i;
        ifx_mei_atm_showtime_enter = NULL;
@@ -1042,6 +1106,8 @@ static void __exit ifx_ptm_exit(void)
     ifx_ptm_uninit_chip();
 
     clear_priv_data();
+
+    return 0;
 }
 
 #ifndef MODULE
@@ -1070,8 +1136,17 @@ static int __init queue_gamma_map_setup(char *line)
     return 0;
 }
 #endif
-module_init(ifx_ptm_init);
-module_exit(ifx_ptm_exit);
+static struct platform_driver ltq_ptm_driver = {
+       .probe = ltq_ptm_probe,
+       .remove = ltq_ptm_remove,
+       .driver = {
+               .name = "ptm",
+               .owner = THIS_MODULE,
+               .of_match_table = ltq_ptm_match,
+       },
+};
+
+module_platform_driver(ltq_ptm_driver);
 #ifndef MODULE
   __setup("wanqos_en=", wanqos_en_setup);
   __setup("queue_gamma_map=", queue_gamma_map_setup);