support 3188 vmac
authorhwg <hwg@rock-chips.com>
Fri, 7 Mar 2014 01:12:45 +0000 (09:12 +0800)
committerhwg <hwg@rock-chips.com>
Fri, 7 Mar 2014 01:13:02 +0000 (09:13 +0800)
18 files changed:
arch/arm/boot/dts/rk3188-pinctrl.dtsi
arch/arm/boot/dts/rk3188.dtsi
drivers/net/eth_mac/Kconfig [deleted file]
drivers/net/eth_mac/Makefile [deleted file]
drivers/net/eth_mac/eth_mac.c [deleted file]
drivers/net/eth_mac/eth_mac.h [deleted file]
drivers/net/ethernet/Kconfig [changed mode: 0644->0755]
drivers/net/ethernet/Makefile [changed mode: 0644->0755]
drivers/net/ethernet/rk/Kconfig [new file with mode: 0755]
drivers/net/ethernet/rk/Makefile [new file with mode: 0755]
drivers/net/ethernet/rk/vmac/Kconfig [new file with mode: 0755]
drivers/net/ethernet/rk/vmac/Makefile [new file with mode: 0755]
drivers/net/ethernet/rk/vmac/rk29_vmac.c [new file with mode: 0755]
drivers/net/ethernet/rk/vmac/rk29_vmac.h [new file with mode: 0755]
drivers/net/ethernet/rk/vmac/rk29_vmac_phy.c [new file with mode: 0755]
drivers/net/rk29_vmac.c [deleted file]
drivers/net/rk29_vmac.h [deleted file]
drivers/usb/dwc_otg_310/dwc_otg_hcd_linux.c

index bb46bc6f42311afdef86814f98465b05c2830dd2..694549ca73d7393f1b05d3c84c5715d9edf3edb0 100755 (executable)
                        };
                };
 
+               gpio3_rmii {
+                       rmii_clkoutpin: rmii-clkoutpin {
+                               rockchip,pins = <RMII_CLKOUT>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       rmii_clkinpin: rmii-clkinpin {
+                               rockchip,pins = <RMII_CLKIN>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       rmii_txpins: rmii-txpins {
+                               rockchip,pins = <RMII_TXEN>, <RMII_TXD1>, <RMII_TXD0>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       rmii_rxpins: rmii-rxpins {
+                               rockchip,pins = <RMII_RXD0>, <RMII_RXD1>, <RMII_RXERR>, <RMII_CRS>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+
+                       rmii_mdpins: rmii-mdpins {
+                               rockchip,pins = <RMII_MD>, <RMII_MDCLK>;
+                               rockchip,pull = <VALUE_PULL_DISABLE>;
+                               //rockchip,voltage = <VALUE_VOL_DEFAULT>;
+                               rockchip,drive = <VALUE_DRV_DEFAULT>;
+                               //rockchip,tristate = <VALUE_TRI_DEFAULT>;
+                       };
+               };
+
                gps {
                        gps_mag:gps-mag {
                                rockchip,pins = <GPS_MAG>;
index 79da82eb762139ed3c31af85ca161a6d8426635f..b4834797b70b16123ca256f60318d138acd18c2c 100755 (executable)
                              "hsicphy12m", "hsic_otgphy1";
        };
 
+       vmac@0x10204000 {
+               compatible = "rockchip,vmac";
+               reg = <0x10204000 0x4000>;
+               interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default", "gpio";
+               pinctrl-0 = <&rmii_clkoutpin &rmii_txpins &rmii_rxpins &rmii_mdpins>;
+               pinctrl-1 = <&rmii_clkinpin &rmii_txpins &rmii_rxpins &rmii_mdpins>;
+       };
 };
diff --git a/drivers/net/eth_mac/Kconfig b/drivers/net/eth_mac/Kconfig
deleted file mode 100755 (executable)
index 933563a..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-#      set Ethernet mac source
-#
-choice 
-       prompt "Ethernet mac source"
-       depends on NETDEV_10000 ||NETDEV_1000 ||NET_ETHERNET
-       default ETH_MAC_FROM_RANDOM
-
-       config ETH_MAC_FROM_RANDOM
-               bool "Random Ethernet mac "
-               ---help---
-                  Say Y here if you want to set Random mac to Ethernet mac.
-        
-                  This option alone does not add any kernel code.
-
-                  If you say N, all options in this submenu will be skipped and disabled.      
-
-       config ETH_MAC_FROM_EEPROM
-               bool "Ethernet mac from EEPROM"
-               depends on EEPROM_AT24C16
-               ---help---
-                  Say Y here if you want to set EEPROM mac to Ethernet mac,
-                  when the EEPROM exsits and mac has been written in.
-        
-                  This option alone does not add any kernel code.
-
-                  If you say N, all options in this submenu will be skipped and disabled.      
-
-       config ETH_MAC_FROM_IDB
-               bool "Ethernet mac from IDB"
-               ---help---
-                 Say Y here if you want to set IDB mac to Ethernet mac,
-                 when the IDB mac has been written in.
-               
-                 This option alone does not add any kernel code.
-
-                 If you say N, all options in this submenu will be skipped and disabled.
-
-endchoice
-
-config  PHY_PORT_NUM
-        int "phy port number selected (More than one port on Switch)"
-        depends on RK29_VMAC
-        default 0
-        help
-                 0:phy dev 0:00
-                 1:phy dev 0:01
-                 2:phy dev 0:02
-                      ---More---
-
-
diff --git a/drivers/net/eth_mac/Makefile b/drivers/net/eth_mac/Makefile
deleted file mode 100755 (executable)
index c745b3d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-y  += eth_mac.o
diff --git a/drivers/net/eth_mac/eth_mac.c b/drivers/net/eth_mac/eth_mac.c
deleted file mode 100755 (executable)
index 96f5de4..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*\r
- * Copyright (C) 2010 ROCKCHIP, Inc.\r
- * Author: roger_chen <cz@rock-chips.com>\r
- *\r
- * This program is the virtual flash device \r
- * used to store bd_addr or MAC\r
- *\r
- */\r
-\r
-\r
-#include <linux/module.h>\r
-#include <linux/kernel.h>\r
-#include <linux/errno.h>\r
-#include <linux/miscdevice.h>\r
-#include <linux/fs.h>\r
-#include <linux/platform_device.h>\r
-#include <asm/uaccess.h>\r
-#include <asm/io.h>\r
-#include <linux/fs.h>\r
-#include <linux/slab.h>\r
-#include "eth_mac.h"\r
-\r
-#if 1\r
-#define DBG(x...)   printk("eth_mac:" x)\r
-#else\r
-#define DBG(x...)\r
-#endif\r
-\r
-#define VERSION "0.1"\r
-\r
-#define WLAN_MAC_FILE "/data/misc/wifi/wlan_mac"\r
-\r
-//extern char GetSNSectorInfo(char * pbuf);\r
-\r
-static char GetSNSectorInfoBeforeNandInit(char * pbuf)\r
-{\r
-    char * sn_addr = ioremap(0x10501600,0x200);\r
-    memcpy(pbuf,sn_addr,0x200);\r
-    iounmap(sn_addr);\r
-       //print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 16, 0);\r
-    return 0;\r
-}\r
-\r
-int eth_mac_read_from_IDB(u8 *mac)\r
-{\r
-     int i;\r
-     char *tempBuf = kmalloc(512, GFP_KERNEL);\r
-    \r
-    if(mac == NULL)\r
-        return -EFAULT;\r
-\r
-    GetSNSectorInfoBeforeNandInit(tempBuf);\r
-    /*for (i = 0; i < 512; i++) {\r
-        printk("%02x, ", tempBuf[i]);\r
-               if(((i+1)%16) == 0) printk("\n");\r
-       }*/\r
-\r
-    for (i = 506; i <= 511; i++)\r
-               mac[i-506] = tempBuf[i];\r
-\r
-    kfree(tempBuf);\r
-    \r
-       return 0;\r
-}\r
-\r
-int eth_mac_idb(u8 *eth_mac)\r
-{\r
-       int i;\r
-       int err = 0;\r
-       memset(eth_mac, 0, 6);\r
-       err = eth_mac_read_from_IDB(eth_mac);\r
-       if (err)\r
-               return -1;\r
-       printk("Read the Ethernet MAC address from IDB:");\r
-       for (i = 0; i < 5; i++)\r
-               printk("%2.2x:", eth_mac[i]);\r
-       printk("%2.2x\n", eth_mac[i]);\r
-\r
-       return 0;\r
-}\r
-\r
-/**\r
-*大写转小写\r
-*\r
-*/\r
-static void   to_lower(char   *str) \r
-{ \r
-       int   i=0; \r
-       while(str[i]!=0) \r
-       { \r
-               if((str[i] >= 'A')&&(str[i] <= 'Z')) \r
-                       str[i]+=32; \r
-               i++; \r
-       } \r
-} \r
-\r
-\r
-/**\r
-  *字符串格式转为mac 格式.\r
-  *\r
-  *\r
-  */\r
-static void  trans( char *src ,int * k) \r
-{\r
-    char c;\r
-    int i;\r
-    int temp;\r
-    int temp2;\r
-\r
-    if( (src == NULL) ||(strlen(src) <16 ) ) // 参数检查\r
-    {\r
-      printk( "Arg Error\n" );\r
-      return ;\r
-    }\r
-\r
-    for( i = 0; i < 6; i++ )\r
-    {\r
-      temp = 0;\r
-      temp2 = 0;\r
-      c = *src;\r
-      if( c == ':' ){\r
-               src++;\r
-               c = *src;\r
-       }\r
-      if( c >= 'a' && c <= 'f' )          // 两个字符中的第一个 比如 "0f" ,则表示是字符 '0'\r
-         temp = ( c - 'a' ) + 10; \r
-      else\r
-         temp = ( c - '0' ) ;\r
-      src++;\r
-      \r
-      c = *src;\r
-      if( i == 5){                         //wifi mac 末尾加1\r
-       if(c =='f'){\r
-          c = '0';\r
-       } if (c == '9'){\r
-          c = 'a';\r
-       }else{\r
-          c = c + 1;\r
-       }\r
-      }\r
-      if( c >= 'a' && c <= 'f' )             // 两个字符中的第二个,如 "f8" ,那么表示字符 '8'\r
-         temp2 = ( c - 'a' ) + 10;\r
-      else\r
-         temp2 = ( c - '0' ) ;\r
-\r
-      temp = temp * 16;\r
-      temp += temp2;\r
-      src++;\r
-      *(k+i) = temp;\r
-\r
-    }\r
-\r
-}\r
-\r
-/*int eth_mac_wifi(u8 *eth_mac){\r
-       int i;\r
-       struct  file *file = NULL;\r
-       char wifi_mac[32];\r
-       mm_segment_t old_fs;\r
-       ssize_t ret;\r
-       int maci[6];\r
-\r
-       memset(eth_mac, 0, 6);\r
-       \r
-       file = filp_open(WLAN_MAC_FILE, O_RDWR,0);\r
-       if (IS_ERR(file))\r
-       {\r
-               printk("open %s failed.", WLAN_MAC_FILE);\r
-               return -ENOENT;\r
-       } \r
-\r
-       old_fs = get_fs();\r
-       set_fs(get_ds());\r
-    \r
-       file->f_op->llseek(file,0,0);\r
-       ret = file->f_op->read(file, wifi_mac, 32, &file->f_pos);\r
-    \r
-       set_fs(old_fs);\r
-    \r
-        if(ret > 0){\r
-               //printk("mac read from %s: %s\n", WLAN_MAC_FILE,wifi_mac);\r
-\r
-               to_lower(wifi_mac);\r
-               trans(wifi_mac,maci);\r
-               for (i = 0;i< 6;i++){\r
-                       eth_mac[i] = maci[i];\r
-               }\r
-               \r
-        }\r
-        else if(ret == 0)\r
-               printk("read nothing from %s........\n",WLAN_MAC_FILE);\r
-        else \r
-        {\r
-               printk("read wifi mac error\n");\r
-                return -ENOENT;\r
-        }\r
-\r
-       filp_close(file,NULL);\r
-       return 0;\r
-       \r
-}*/\r
-\r
-\r
-\r
-\r
-\r
diff --git a/drivers/net/eth_mac/eth_mac.h b/drivers/net/eth_mac/eth_mac.h
deleted file mode 100755 (executable)
index 03db627..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _ETH_MAC_H_
-#define _ETH_MAC_H_
-/*
- *  eth_mac/eth_mac.h
- *
- *  Copyright (C) 2001 Russell King.
- *
- * This file is placed under the LGPL.
- *
- *
- * 
- */
-//int eth_mac_read_from_IDB(u8 *mac)
-
-int eth_mac_idb(u8 *eth_mac);
-int eth_mac_wifi(u8 *eth_mac);
-#endif /* _ETH_MAC_H_ */
old mode 100644 (file)
new mode 100755 (executable)
index ed956e0..f651b27
@@ -167,5 +167,6 @@ source "drivers/net/ethernet/via/Kconfig"
 source "drivers/net/ethernet/wiznet/Kconfig"
 source "drivers/net/ethernet/xilinx/Kconfig"
 source "drivers/net/ethernet/xircom/Kconfig"
+source "drivers/net/ethernet/rk/Kconfig"
 
 endif # ETHERNET
old mode 100644 (file)
new mode 100755 (executable)
index 8268d85..b3925e9
@@ -74,3 +74,4 @@ obj-$(CONFIG_NET_VENDOR_VIA) += via/
 obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
 obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
 obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
+obj-$(CONFIG_NET_VENDOR_ROCKCHIP) += rk/
diff --git a/drivers/net/ethernet/rk/Kconfig b/drivers/net/ethernet/rk/Kconfig
new file mode 100755 (executable)
index 0000000..be5f534
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# rockchip device configuration
+#
+
+config NET_VENDOR_ROCKCHIP
+       bool "Rockchip devices"
+       default y
+       depends on HAS_IOMEM
+       ---help---
+         Rockchip devices
+
+if NET_VENDOR_ROCKCHIP
+
+source "drivers/net/ethernet/rk/vmac/Kconfig"
+
+endif # NET_VENDOR_ROCKCHIP
diff --git a/drivers/net/ethernet/rk/Makefile b/drivers/net/ethernet/rk/Makefile
new file mode 100755 (executable)
index 0000000..e36c612
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the rockchip device drivers.
+#
+
+obj-$(CONFIG_RK_VMAC_ETH) += vmac/
diff --git a/drivers/net/ethernet/rk/vmac/Kconfig b/drivers/net/ethernet/rk/vmac/Kconfig
new file mode 100755 (executable)
index 0000000..23f5af8
--- /dev/null
@@ -0,0 +1,10 @@
+config RK_VMAC_ETH
+       bool "Rockchip 10/100 Ethernet driver"
+       depends on HAS_IOMEM && HAS_DMA
+       select NET_CORE
+       select MII
+       select PHYLIB
+       select CRC32
+       ---help---
+         Rockchip 10/100 VMAC Ethernet driver.
+
diff --git a/drivers/net/ethernet/rk/vmac/Makefile b/drivers/net/ethernet/rk/vmac/Makefile
new file mode 100755 (executable)
index 0000000..4de3862
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_RK_VMAC_ETH) += rk29_vmac.o
+obj-$(CONFIG_RK_VMAC_ETH) += rk29_vmac_phy.o
diff --git a/drivers/net/ethernet/rk/vmac/rk29_vmac.c b/drivers/net/ethernet/rk/vmac/rk29_vmac.c
new file mode 100755 (executable)
index 0000000..16e69c4
--- /dev/null
@@ -0,0 +1,1798 @@
+/*\r
+ * linux/arch/arc/drivers/arcvmac.c\r
+ *\r
+ * Copyright (C) 2003-2006 Codito Technologies, for linux-2.4 port\r
+ * Copyright (C) 2006-2007 Celunite Inc, for linux-2.6 port\r
+ * Copyright (C) 2007-2008 Sagem Communications, Fehmi HAFSI\r
+ * Copyright (C) 2009 Sagem Communications, Andreas Fenkart\r
+ * All Rights Reserved.\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *\r
+ * external PHY support based on dnet.c\r
+ * ring management based on bcm63xx_enet.c\r
+ *\r
+ * Authors: amit.bhor@celunite.com, sameer.dhavale@celunite.com\r
+ */\r
+\r
+#define DEBUG\r
+\r
+#include <linux/clk.h>\r
+#include <linux/crc32.h>\r
+#include <linux/delay.h>\r
+#include <linux/dma-mapping.h>\r
+#include <linux/etherdevice.h>\r
+#include <linux/init.h>\r
+#include <linux/io.h>\r
+#include <linux/kernel.h>\r
+#include <linux/module.h>\r
+#include <linux/moduleparam.h>\r
+#include <linux/netdevice.h>\r
+#include <linux/phy.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/slab.h>\r
+#include <linux/types.h>\r
+#include <linux/wakelock.h>\r
+#include <linux/version.h>\r
+#include <linux/gpio.h>\r
+#include <asm/irq.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/completion.h>\r
+#include <linux/of.h>\r
+#include <linux/of_platform.h>\r
+\r
+#include "rk29_vmac.h"\r
+\r
+//static struct wake_lock idlelock; /* add by lyx @ 20110302 */\r
+\r
+/* Register access macros */\r
+#define vmac_writel(port, value, reg)  \\r
+       writel((value), (port)->regs + reg##_OFFSET)\r
+#define vmac_readl(port, reg)  readl((port)->regs + reg##_OFFSET)\r
+\r
+static unsigned char *read_mac_reg(struct net_device *dev,\r
+               unsigned char hwaddr[ETH_ALEN])\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned mac_lo, mac_hi;\r
+\r
+       WARN_ON(!hwaddr);\r
+       mac_lo = vmac_readl(ap, ADDRL);\r
+       mac_hi = vmac_readl(ap, ADDRH);\r
+\r
+       hwaddr[0] = (mac_lo >> 0) & 0xff;\r
+       hwaddr[1] = (mac_lo >> 8) & 0xff;\r
+       hwaddr[2] = (mac_lo >> 16) & 0xff;\r
+       hwaddr[3] = (mac_lo >> 24) & 0xff;\r
+       hwaddr[4] = (mac_hi >> 0) & 0xff;\r
+       hwaddr[5] = (mac_hi >> 8) & 0xff;\r
+       return hwaddr;\r
+}\r
+\r
+static void write_mac_reg(struct net_device *dev, unsigned char* hwaddr)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned mac_lo, mac_hi;\r
+\r
+       mac_lo = hwaddr[3] << 24 | hwaddr[2] << 16 | hwaddr[1] << 8 | hwaddr[0];\r
+       mac_hi = hwaddr[5] << 8 | hwaddr[4];\r
+\r
+       vmac_writel(ap, mac_lo, ADDRL);\r
+       vmac_writel(ap, mac_hi, ADDRH);\r
+}\r
+\r
+static void vmac_mdio_xmit(struct vmac_priv *ap, unsigned val)\r
+{\r
+       init_completion(&ap->mdio_complete);\r
+       vmac_writel(ap, val, MDIO_DATA);\r
+       if(!wait_for_completion_timeout(&ap->mdio_complete, msecs_to_jiffies(1000)))\r
+               printk("Time out for waiting mdio completion\n");\r
+}\r
+\r
+static int vmac_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)\r
+{\r
+       struct vmac_priv *vmac = bus->priv;\r
+       unsigned int val;\r
+       /* only 5 bits allowed for phy-addr and reg_offset */\r
+       WARN_ON(phy_id & ~0x1f || phy_reg & ~0x1f);\r
+\r
+       val = MDIO_BASE | MDIO_OP_READ;\r
+       val |= phy_id << 23 | phy_reg << 18;\r
+       vmac_mdio_xmit(vmac, val);\r
+\r
+       val = vmac_readl(vmac, MDIO_DATA);\r
+       return val & MDIO_DATA_MASK;\r
+}\r
+\r
+static int vmac_mdio_write(struct mii_bus *bus, int phy_id, int phy_reg,\r
+                        u16 value)\r
+{\r
+       struct vmac_priv *vmac = bus->priv;\r
+       unsigned int val;\r
+       /* only 5 bits allowed for phy-addr and reg_offset */\r
+       WARN_ON(phy_id & ~0x1f || phy_reg & ~0x1f);\r
+\r
+       val = MDIO_BASE | MDIO_OP_WRITE;\r
+       val |= phy_id << 23 | phy_reg << 18;\r
+       val |= (value & MDIO_DATA_MASK);\r
+       vmac_mdio_xmit(vmac, val);\r
+       return 0;\r
+}\r
+\r
+static void vmac_handle_link_change(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct phy_device *phydev = ap->phy_dev;\r
+       unsigned long flags;\r
+       int report_change = 0;\r
+       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
+\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+\r
+       if (phydev->duplex != ap->duplex) {\r
+               unsigned tmp;\r
+\r
+               tmp = vmac_readl(ap, CONTROL);\r
+\r
+               if (phydev->duplex)\r
+                       tmp |= ENFL_MASK;\r
+               else\r
+                       tmp &= ~ENFL_MASK;\r
+\r
+               vmac_writel(ap, tmp, CONTROL);\r
+\r
+               ap->duplex = phydev->duplex;\r
+               report_change = 1;\r
+       }\r
+\r
+       if (phydev->speed != ap->speed) {\r
+               ap->speed = phydev->speed;\r
+               report_change = 1;\r
+       }\r
+\r
+       if (pdata && pdata->rmii_speed_switch)\r
+               pdata->rmii_speed_switch(phydev->speed);\r
+\r
+       if (phydev->link != ap->link) {\r
+               ap->link = phydev->link;\r
+               report_change = 1;\r
+       }\r
+\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+\r
+       if (report_change)\r
+               phy_print_status(ap->phy_dev);\r
+}\r
+\r
+static int vmac_mii_probe(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct phy_device *phydev = NULL;       \r
+       //struct clk *sys_clk;\r
+       //unsigned long clock_rate;\r
+       int phy_addr, err;\r
+\r
+\r
+#if defined (CONFIG_PHY_PORT_NUM) && (CONFIG_PHY_PORT_NUM != 0)\r
+        if (ap->mii_bus->phy_map[CONFIG_PHY_PORT_NUM])\r
+            phydev = ap->mii_bus->phy_map[CONFIG_PHY_PORT_NUM];\r
+#else\r
+       /* find the first phy */\r
+       for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {\r
+               if (ap->mii_bus->phy_map[phy_addr]) {\r
+                       phydev = ap->mii_bus->phy_map[phy_addr];\r
+                       break;\r
+               }\r
+       }\r
+#endif\r
+\r
+       if (!phydev) {\r
+               dev_err(&dev->dev, "no PHY found\n");\r
+               return -ENODEV;\r
+       }\r
+\r
+       /* add pin_irq, if avail */\r
+       phydev = phy_connect(dev, dev_name(&phydev->dev),\r
+                       &vmac_handle_link_change,\r
+                       PHY_INTERFACE_MODE_RMII);\r
+       if (IS_ERR(phydev)) {\r
+               err = PTR_ERR(phydev);\r
+               dev_err(&dev->dev, "could not attach to PHY %d\n", err);\r
+               goto err_out;\r
+       }\r
+\r
+       phydev->supported &= PHY_BASIC_FEATURES;\r
+       phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;\r
+\r
+       phydev->advertising = phydev->supported;\r
+\r
+       ap->link = 0;\r
+       ap->speed = 0;\r
+       ap->duplex = -1;\r
+       ap->phy_dev = phydev;\r
+\r
+       return 0;\r
+//err_disconnect:\r
+//     phy_disconnect(phydev);\r
+err_out:\r
+       return err;\r
+}\r
+\r
+static int vmac_mii_init(struct vmac_priv *ap)\r
+{\r
+       int err, i;\r
+\r
+       ap->mii_bus = mdiobus_alloc();\r
+       \r
+       if (ap->mii_bus == NULL)\r
+               return -ENOMEM;\r
+\r
+       ap->mii_bus->name = "vmac_mii_bus";\r
+       ap->mii_bus->read = &vmac_mdio_read;\r
+       ap->mii_bus->write = &vmac_mdio_write;\r
+\r
+       snprintf(ap->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);\r
+\r
+       ap->mii_bus->priv = ap;\r
+\r
+       err = -ENOMEM;\r
+       ap->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);\r
+       if (!ap->mii_bus->irq)\r
+               goto err_out;\r
+\r
+       for (i = 0; i < PHY_MAX_ADDR; i++)\r
+               ap->mii_bus->irq[i] = PHY_POLL;\r
+\r
+#if 0\r
+       /* FIXME: what is it used for? */\r
+       platform_set_drvdata(ap->dev, ap->mii_bus);\r
+#endif\r
+\r
+       err = mdiobus_register(ap->mii_bus);\r
+       if (err)\r
+               goto err_out_free_mdio_irq;\r
+\r
+       err = vmac_mii_probe(ap->dev);\r
+       if (err)\r
+               goto err_out_unregister_bus;\r
+\r
+       return 0;\r
+\r
+err_out_unregister_bus:\r
+       mdiobus_unregister(ap->mii_bus);\r
+err_out_free_mdio_irq:\r
+       kfree(ap->mii_bus->irq);\r
+err_out:\r
+       mdiobus_free(ap->mii_bus);\r
+       ap->mii_bus = NULL;\r
+       return err;\r
+}\r
+\r
+static void vmac_mii_exit(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+\r
+       if (ap->phy_dev)\r
+               phy_disconnect(ap->phy_dev);\r
+       if (ap->mii_bus) {\r
+               mdiobus_unregister(ap->mii_bus);\r
+               kfree(ap->mii_bus->irq);\r
+               mdiobus_free(ap->mii_bus);\r
+               ap->mii_bus = NULL;\r
+       }\r
+}\r
+\r
+static int vmacether_get_settings(struct net_device *dev,\r
+               struct ethtool_cmd *cmd)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct phy_device *phydev = ap->phy_dev;\r
+\r
+       if (!phydev)\r
+               return -ENODEV;\r
+\r
+       return phy_ethtool_gset(phydev, cmd);\r
+}\r
+\r
+static int vmacether_set_settings(struct net_device *dev,\r
+               struct ethtool_cmd *cmd)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct phy_device *phydev = ap->phy_dev;\r
+\r
+       if (!phydev)\r
+               return -ENODEV;\r
+\r
+       return phy_ethtool_sset(phydev, cmd);\r
+}\r
+\r
+static int vmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct phy_device *phydev = ap->phy_dev;\r
+\r
+       if (!netif_running(dev))\r
+               return -EINVAL;\r
+\r
+       if (!phydev)\r
+               return -ENODEV;\r
+\r
+       return phy_mii_ioctl(phydev, rq, cmd);\r
+}\r
+\r
+static void vmacether_get_drvinfo(struct net_device *dev,\r
+               struct ethtool_drvinfo *info)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+\r
+       strlcpy(info->driver, VMAC_NAME, sizeof(info->driver));\r
+       strlcpy(info->version, VMAC_VERSION, sizeof(info->version));\r
+       snprintf(info->bus_info, sizeof(info->bus_info),\r
+                       "platform 0x%x", ap->mem_base);\r
+}\r
+\r
+static int update_error_counters(struct net_device *dev, int status)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       dev_dbg(&ap->pdev->dev, "rx error counter overrun. status = 0x%x\n",\r
+                       status);\r
+\r
+       /* programming error */\r
+       WARN_ON(status & TXCH_MASK);\r
+       WARN_ON(!(status & (MSER_MASK | RXCR_MASK | RXFR_MASK | RXFL_MASK)));\r
+\r
+       if (status & MSER_MASK)\r
+               ap->stats.rx_over_errors += 256; /* ran out of BD */\r
+       if (status & RXCR_MASK)\r
+               ap->stats.rx_crc_errors += 256;\r
+       if (status & RXFR_MASK)\r
+               ap->stats.rx_frame_errors += 256;\r
+       if (status & RXFL_MASK)\r
+               ap->stats.rx_fifo_errors += 256;\r
+\r
+       return 0;\r
+}\r
+\r
+static void update_tx_errors(struct net_device *dev, int status)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+\r
+       if (status & UFLO)\r
+               ap->stats.tx_fifo_errors++;\r
+\r
+       if (ap->duplex)\r
+               return;\r
+\r
+       /* half duplex flags */\r
+       if (status & LTCL)\r
+               ap->stats.tx_window_errors++;\r
+       if (status & RETRY_CT)\r
+               ap->stats.collisions += (status & RETRY_CT) >> 24;\r
+       if (status & DROP)  /* too many retries */\r
+               ap->stats.tx_aborted_errors++;\r
+       if (status & DEFER)\r
+               dev_vdbg(&ap->pdev->dev, "\"defer to traffic\"\n");\r
+       if (status & CARLOSS)\r
+               ap->stats.tx_carrier_errors++;\r
+}\r
+\r
+static int vmac_rx_reclaim_force(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       int ct;\r
+\r
+       ct = 0;\r
+\r
+       dev_dbg(&ap->pdev->dev, "%s need to release %d rx sk_buff\n",\r
+           __func__, fifo_used(&ap->rx_ring));\r
+\r
+       while (!fifo_empty(&ap->rx_ring) && ct++ < ap->rx_ring.size) {\r
+               struct vmac_buffer_desc *desc;\r
+               struct sk_buff *skb;\r
+               int desc_idx;\r
+\r
+               desc_idx = ap->rx_ring.tail;\r
+               desc = &ap->rxbd[desc_idx];\r
+               fifo_inc_tail(&ap->rx_ring);\r
+\r
+               if (!ap->rx_skbuff[desc_idx]) {\r
+                       dev_err(&ap->pdev->dev, "non-populated rx_skbuff found %d\n",\r
+                                       desc_idx);\r
+                       continue;\r
+               }\r
+\r
+               skb = ap->rx_skbuff[desc_idx];\r
+               ap->rx_skbuff[desc_idx] = NULL;\r
+\r
+               dma_unmap_single(&ap->pdev->dev, desc->data, skb->len,\r
+                   DMA_TO_DEVICE);\r
+\r
+               dev_kfree_skb(skb);\r
+       }\r
+\r
+       if (!fifo_empty(&ap->rx_ring)) {\r
+               dev_err(&ap->pdev->dev, "failed to reclaim %d rx sk_buff\n",\r
+                               fifo_used(&ap->rx_ring));\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int vmac_rx_refill(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+\r
+       WARN_ON(fifo_full(&ap->rx_ring));\r
+\r
+       while (!fifo_full(&ap->rx_ring)) {\r
+               struct vmac_buffer_desc *desc;\r
+               struct sk_buff *skb;\r
+               dma_addr_t p;\r
+               int desc_idx;\r
+\r
+               desc_idx = ap->rx_ring.head;\r
+               desc = &ap->rxbd[desc_idx];\r
+\r
+               /* make sure we read the actual descriptor status */\r
+               rmb();\r
+\r
+               if (ap->rx_skbuff[desc_idx]) {\r
+                       /* dropped packet / buffer chaining */\r
+                       fifo_inc_head(&ap->rx_ring);\r
+\r
+                       /* return to DMA */\r
+                       wmb();\r
+                       desc->info = OWN_MASK | ap->rx_skb_size;\r
+                       continue;\r
+               }\r
+\r
+               skb = netdev_alloc_skb(dev, ap->rx_skb_size + 2);\r
+               if (!skb) {\r
+                       dev_info(&ap->pdev->dev, "failed to allocate rx_skb, skb's left %d\n",\r
+                                       fifo_used(&ap->rx_ring));\r
+                       break;\r
+               }\r
+\r
+               /* IP header Alignment (14 byte Ethernet header) */\r
+               skb_reserve(skb, 2);\r
+               WARN_ON(skb->len != 0); /* nothing received yet */\r
+\r
+               ap->rx_skbuff[desc_idx] = skb;\r
+\r
+               p = dma_map_single(&ap->pdev->dev, skb->data, ap->rx_skb_size,\r
+                               DMA_FROM_DEVICE);\r
+\r
+               desc->data = p;\r
+\r
+               wmb();\r
+               desc->info = OWN_MASK | ap->rx_skb_size;\r
+\r
+               fifo_inc_head(&ap->rx_ring);\r
+       }\r
+\r
+       /* If rx ring is still empty, set a timer to try allocating\r
+        * again at a later time. */\r
+       if (fifo_empty(&ap->rx_ring) && netif_running(dev)) {\r
+               dev_warn(&ap->pdev->dev, "unable to refill rx ring\n");\r
+               ap->rx_timeout.expires = jiffies + HZ;\r
+               add_timer(&ap->rx_timeout);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * timer callback to defer refill rx queue in case we're OOM\r
+ */\r
+static void vmac_refill_rx_timer(unsigned long data)\r
+{\r
+       struct net_device *dev;\r
+       struct vmac_priv *ap;\r
+\r
+       dev = (struct net_device *)data;\r
+       ap = netdev_priv(dev);\r
+\r
+       spin_lock(&ap->rx_lock);\r
+       vmac_rx_refill(dev);\r
+       spin_unlock(&ap->rx_lock);\r
+}\r
+\r
+/* merge buffer chaining  */\r
+struct sk_buff *vmac_merge_rx_buffers(struct net_device *dev,\r
+               struct vmac_buffer_desc *after,\r
+               int pkt_len) /* data */\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct sk_buff *merge_skb, *cur_skb;\r
+       struct dma_fifo *rx_ring;\r
+       struct vmac_buffer_desc *desc;\r
+\r
+       rx_ring = &ap->rx_ring;\r
+       desc = &ap->rxbd[rx_ring->tail];\r
+\r
+       WARN_ON(desc == after);\r
+\r
+       /* strip FCS */\r
+       pkt_len -= 4;\r
+\r
+       /* IP header Alignment (14 byte Ethernet header) */\r
+       merge_skb = netdev_alloc_skb(dev, pkt_len + 2);\r
+       if (!merge_skb) {\r
+               dev_err(&ap->pdev->dev, "failed to allocate merged rx_skb, rx skb's left %d\n",\r
+                               fifo_used(rx_ring));\r
+\r
+               return NULL;\r
+       }\r
+\r
+       skb_reserve(merge_skb, 2);\r
+\r
+       while (desc != after && pkt_len) {\r
+               struct vmac_buffer_desc *desc;\r
+               int buf_len, valid;\r
+\r
+               /* desc needs wrapping */\r
+               desc = &ap->rxbd[rx_ring->tail];\r
+               cur_skb = ap->rx_skbuff[rx_ring->tail];\r
+               WARN_ON(!cur_skb);\r
+\r
+               dma_unmap_single(&ap->pdev->dev, desc->data, ap->rx_skb_size,\r
+                               DMA_FROM_DEVICE);\r
+\r
+               /* do not copy FCS */\r
+               buf_len = desc->info & LEN_MASK;\r
+               valid = min(pkt_len, buf_len);\r
+               pkt_len -= valid;\r
+\r
+               memcpy(skb_put(merge_skb, valid), cur_skb->data, valid);\r
+\r
+               fifo_inc_tail(rx_ring);\r
+       }\r
+\r
+       /* merging_pressure++ */\r
+\r
+       if (unlikely(pkt_len != 0))\r
+               dev_err(&ap->pdev->dev, "buffer chaining bytes missing %d\n",\r
+                               pkt_len);\r
+\r
+       WARN_ON(desc != after);\r
+\r
+       return merge_skb;\r
+}\r
+\r
+int vmac_rx_receive(struct net_device *dev, int budget)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct vmac_buffer_desc *first;\r
+       int processed, pkt_len, pkt_err;\r
+       struct dma_fifo lookahead;\r
+\r
+       processed = 0;\r
+\r
+       first = NULL;\r
+       pkt_err = pkt_len = 0;\r
+\r
+       /* look ahead, till packet complete */\r
+       lookahead = ap->rx_ring;\r
+\r
+       do {\r
+               struct vmac_buffer_desc *desc; /* cur_ */\r
+               int desc_idx; /* cur_ */\r
+               struct sk_buff *skb; /* pkt_ */\r
+\r
+               desc_idx = lookahead.tail;\r
+               desc = &ap->rxbd[desc_idx];\r
+\r
+               /* make sure we read the actual descriptor status */\r
+               rmb();\r
+\r
+               /* break if dma ownership belongs to hw */\r
+               if (desc->info & OWN_MASK) {\r
+                       ap->mac_rxring_head = vmac_readl(ap, MAC_RXRING_HEAD);\r
+                       break;\r
+               }\r
+\r
+               if (desc->info & FRST_MASK) {\r
+                       pkt_len = 0;\r
+                       pkt_err = 0;\r
+\r
+                       /* don't free current */\r
+                       ap->rx_ring.tail = lookahead.tail;\r
+                       first = desc;\r
+               }\r
+\r
+               fifo_inc_tail(&lookahead);\r
+\r
+               /* check bd */\r
+\r
+               pkt_len += desc->info & LEN_MASK;\r
+               pkt_err |= (desc->info & BUFF);\r
+\r
+               if (!(desc->info & LAST_MASK))\r
+                       continue;\r
+\r
+               /* received complete packet */\r
+\r
+               if (unlikely(pkt_err || !first)) {\r
+                       /* recycle buffers */\r
+                       ap->rx_ring.tail = lookahead.tail;\r
+                       continue;\r
+               }\r
+\r
+               WARN_ON(!(first->info & FRST_MASK) ||\r
+                               !(desc->info & LAST_MASK));\r
+               WARN_ON(pkt_err);\r
+\r
+               /* -- valid packet -- */\r
+\r
+               if (first != desc) {\r
+                       skb = vmac_merge_rx_buffers(dev, desc, pkt_len);\r
+\r
+                       if (!skb) {\r
+                               /* kill packet */\r
+                               ap->rx_ring.tail = lookahead.tail;\r
+                               ap->rx_merge_error++;\r
+                               continue;\r
+                       }\r
+               } else {\r
+                       dma_unmap_single(&ap->pdev->dev, desc->data,\r
+                                       ap->rx_skb_size, DMA_FROM_DEVICE);\r
+\r
+                       skb = ap->rx_skbuff[desc_idx];\r
+                       ap->rx_skbuff[desc_idx] = NULL;\r
+                       /* desc->data != skb->data => desc->data DMA mapped */\r
+\r
+                       /* strip FCS */\r
+                       skb_put(skb, pkt_len - 4);\r
+               }\r
+\r
+               /* free buffers */\r
+               ap->rx_ring.tail = lookahead.tail;\r
+\r
+               WARN_ON(skb->len != pkt_len - 4);\r
+               processed++;\r
+               skb->dev = dev;\r
+               skb->protocol = eth_type_trans(skb, dev);\r
+               ap->stats.rx_packets++;\r
+               ap->stats.rx_bytes += skb->len;\r
+               dev->last_rx = jiffies;\r
+               netif_rx(skb);\r
+\r
+       } while (!fifo_empty(&lookahead) && (processed < budget));\r
+\r
+       dev_vdbg(&ap->pdev->dev, "processed pkt %d, remaining rx buff %d\n",\r
+                       processed,\r
+                       fifo_used(&ap->rx_ring));\r
+\r
+       if (processed || fifo_empty(&ap->rx_ring))\r
+               vmac_rx_refill(dev);\r
+\r
+       return processed;\r
+}\r
+\r
+static void vmac_toggle_irqmask(struct net_device *dev, int enable, int mask)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned long tmp;\r
+\r
+       tmp = vmac_readl(ap, ENABLE);\r
+       if (enable)\r
+               tmp |= mask;\r
+       else\r
+               tmp &= ~mask;\r
+       vmac_writel(ap, tmp, ENABLE);\r
+}\r
+\r
+static void vmac_toggle_txint(struct net_device *dev, int enable)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+       vmac_toggle_irqmask(dev, enable, TXINT_MASK);\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+}\r
+\r
+static void vmac_toggle_rxint(struct net_device *dev, int enable)\r
+{\r
+       vmac_toggle_irqmask(dev, enable, RXINT_MASK);\r
+}\r
+\r
+static int vmac_poll(struct napi_struct *napi, int budget)\r
+{\r
+       struct vmac_priv *ap;\r
+       struct net_device *dev;\r
+       int rx_work_done;\r
+       unsigned long flags;\r
+\r
+       ap = container_of(napi, struct vmac_priv, napi);\r
+       dev = ap->dev;\r
+\r
+       /* ack interrupt */\r
+       vmac_writel(ap, RXINT_MASK, STAT);\r
+\r
+       spin_lock(&ap->rx_lock);\r
+       rx_work_done = vmac_rx_receive(dev, budget);\r
+       spin_unlock(&ap->rx_lock);\r
+\r
+#ifdef VERBOSE_DEBUG\r
+       if (printk_ratelimit()) {\r
+               dev_vdbg(&ap->pdev->dev, "poll budget %d receive rx_work_done %d\n",\r
+                               budget,\r
+                               rx_work_done);\r
+       }\r
+#endif\r
+\r
+       if (rx_work_done >= budget) {\r
+               /* rx queue is not yet empty/clean */\r
+               return rx_work_done;\r
+       }\r
+\r
+       /* no more packet in rx/tx queue, remove device from poll\r
+        * queue */\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+       napi_complete(napi);\r
+       vmac_toggle_rxint(dev, 1);\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+\r
+       return rx_work_done;\r
+}\r
+\r
+static int vmac_tx_reclaim(struct net_device *dev, int force);\r
+\r
+static irqreturn_t vmac_intr(int irq, void *dev_instance)\r
+{\r
+       struct net_device *dev = dev_instance;\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned int status;\r
+\r
+       spin_lock(&ap->lock);\r
+\r
+       status = vmac_readl(ap, STAT);\r
+       vmac_writel(ap, status, STAT);\r
+\r
+#ifdef DEBUG\r
+       if (unlikely(ap->shutdown))\r
+               dev_err(&ap->pdev->dev, "ISR during close\n");\r
+\r
+       if (unlikely(!status & (RXINT_MASK|MDIO_MASK|ERR_MASK)))\r
+               dev_err(&ap->pdev->dev, "No source of IRQ found\n");\r
+#endif\r
+\r
+       if ((status & RXINT_MASK) &&\r
+                       (ap->mac_rxring_head !=\r
+                        vmac_readl(ap, MAC_RXRING_HEAD))) {\r
+               vmac_toggle_rxint(dev, 0);\r
+               napi_schedule(&ap->napi);\r
+       }\r
+\r
+       if (unlikely(netif_queue_stopped(dev) && (status & TXINT_MASK)))\r
+               vmac_tx_reclaim(dev, 0);\r
+\r
+       if (status & MDIO_MASK)\r
+               complete(&ap->mdio_complete);\r
+\r
+       if (unlikely(status & ERR_MASK))\r
+               update_error_counters(dev, status);\r
+\r
+       spin_unlock(&ap->lock);\r
+\r
+       return IRQ_HANDLED;\r
+}\r
+\r
+static int vmac_tx_reclaim(struct net_device *dev, int force)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       int released = 0;\r
+\r
+       /* buffer chaining not used, see vmac_start_xmit */\r
+\r
+       while (!fifo_empty(&ap->tx_ring)) {\r
+               struct vmac_buffer_desc *desc;\r
+               struct sk_buff *skb;\r
+               int desc_idx;\r
+\r
+               desc_idx = ap->tx_ring.tail;\r
+               desc = &ap->txbd[desc_idx];\r
+\r
+               /* ensure other field of the descriptor were not read\r
+                * before we checked ownership */\r
+               rmb();\r
+\r
+               if ((desc->info & OWN_MASK) && !force)\r
+                       break;\r
+\r
+               if (desc->info & ERR_MSK_TX) {\r
+                       update_tx_errors(dev, desc->info);\r
+                       /* recycle packet, let upper level deal with it */\r
+               }\r
+\r
+               skb = ap->tx_skbuff[desc_idx];\r
+               ap->tx_skbuff[desc_idx] = NULL;\r
+               WARN_ON(!skb);\r
+\r
+               dma_unmap_single(&ap->pdev->dev, desc->data, skb->len,\r
+                               DMA_TO_DEVICE);\r
+\r
+               dev_kfree_skb_any(skb);\r
+\r
+               released++;\r
+               fifo_inc_tail(&ap->tx_ring);\r
+       }\r
+\r
+       if (netif_queue_stopped(dev) && released) {\r
+               netif_wake_queue(dev);\r
+               vmac_toggle_txint(dev, 0);\r
+       }\r
+\r
+       if (unlikely(force && !fifo_empty(&ap->tx_ring))) {\r
+               dev_err(&ap->pdev->dev, "failed to reclaim %d tx sk_buff\n",\r
+                               fifo_used(&ap->tx_ring));\r
+       }\r
+\r
+       return released;\r
+}\r
+\r
+int vmac_start_xmit(struct sk_buff *skb, struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct vmac_buffer_desc *desc;\r
+       unsigned int tmp;\r
+\r
+       /* running under xmit lock */\r
+\r
+       /* no scatter/gatter see features below */\r
+       WARN_ON(skb_shinfo(skb)->nr_frags != 0);\r
+       WARN_ON(skb->len > MAX_TX_BUFFER_LEN);\r
+\r
+       if (unlikely(fifo_full(&ap->tx_ring))) {\r
+               netif_stop_queue(dev);\r
+               vmac_toggle_txint(dev, 1);\r
+               dev_err(&ap->pdev->dev, "xmit called with no tx desc available\n");\r
+               return NETDEV_TX_BUSY;\r
+       }\r
+\r
+       if (unlikely(skb->len < ETH_ZLEN)) {\r
+               struct sk_buff *short_skb;\r
+               short_skb = netdev_alloc_skb(dev, ETH_ZLEN);\r
+               if (!short_skb)\r
+                       return NETDEV_TX_LOCKED;\r
+\r
+               memset(short_skb->data, 0, ETH_ZLEN);\r
+               memcpy(skb_put(short_skb, ETH_ZLEN), skb->data, skb->len);\r
+               dev_kfree_skb(skb);\r
+               skb = short_skb;\r
+       }\r
+\r
+       /* fill descriptor */\r
+       ap->tx_skbuff[ap->tx_ring.head] = skb;\r
+\r
+       desc = &ap->txbd[ap->tx_ring.head];\r
+       desc->data = dma_map_single(&ap->pdev->dev, skb->data, skb->len,\r
+                       DMA_TO_DEVICE);\r
+\r
+       /* dma might already be polling */\r
+       wmb();\r
+       desc->info = OWN_MASK | FRST_MASK | LAST_MASK | skb->len;\r
+       wmb();\r
+\r
+       /* kick tx dma */\r
+       tmp = vmac_readl(ap, STAT);\r
+       vmac_writel(ap, tmp | TXPL_MASK, STAT);\r
+\r
+       ap->stats.tx_packets++;\r
+       ap->stats.tx_bytes += skb->len;\r
+       dev->trans_start = jiffies;\r
+       fifo_inc_head(&ap->tx_ring);\r
+\r
+       /* vmac_tx_reclaim independent of vmac_tx_timeout */\r
+       if (fifo_used(&ap->tx_ring) > 8)\r
+               vmac_tx_reclaim(dev, 0);\r
+\r
+       /* stop queue if no more desc available */\r
+       if (fifo_full(&ap->tx_ring)) {\r
+               netif_stop_queue(dev);\r
+               vmac_toggle_txint(dev, 1);\r
+       }\r
+\r
+       return NETDEV_TX_OK;\r
+}\r
+\r
+static int alloc_buffers(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       int err = -ENOMEM;\r
+       int size;\r
+\r
+       fifo_init(&ap->rx_ring, RX_BDT_LEN);\r
+       fifo_init(&ap->tx_ring, TX_BDT_LEN);\r
+\r
+       /* initialize skb list */\r
+       memset(ap->rx_skbuff, 0, sizeof(ap->rx_skbuff));\r
+       memset(ap->tx_skbuff, 0, sizeof(ap->tx_skbuff));\r
+\r
+       /* allocate DMA received descriptors */\r
+       size = sizeof(*ap->rxbd) * ap->rx_ring.size;\r
+       ap->rxbd = dma_alloc_coherent(&ap->pdev->dev, size,\r
+                       &ap->rxbd_dma,\r
+                       GFP_KERNEL);\r
+       if (ap->rxbd == NULL)\r
+               goto err_out;\r
+\r
+       /* allocate DMA transmit descriptors */\r
+       size = sizeof(*ap->txbd) * ap->tx_ring.size;\r
+       ap->txbd = dma_alloc_coherent(&ap->pdev->dev, size,\r
+                       &ap->txbd_dma,\r
+                       GFP_KERNEL);\r
+       if (ap->txbd == NULL)\r
+               goto err_free_rxbd;\r
+\r
+       /* ensure 8-byte aligned */\r
+       WARN_ON(((int)ap->txbd & 0x7) || ((int)ap->rxbd & 0x7));\r
+\r
+       memset(ap->txbd, 0, sizeof(*ap->txbd) * ap->tx_ring.size);\r
+       memset(ap->rxbd, 0, sizeof(*ap->rxbd) * ap->rx_ring.size);\r
+\r
+       /* allocate rx skb */\r
+       err = vmac_rx_refill(dev);\r
+       if (err)\r
+               goto err_free_txbd;\r
+\r
+       return 0;\r
+\r
+err_free_txbd:\r
+       dma_free_coherent(&ap->pdev->dev, sizeof(*ap->txbd) * ap->tx_ring.size,\r
+                       ap->txbd, ap->txbd_dma);\r
+err_free_rxbd:\r
+       dma_free_coherent(&ap->pdev->dev, sizeof(*ap->rxbd) * ap->rx_ring.size,\r
+                       ap->rxbd, ap->rxbd_dma);\r
+err_out:\r
+       return err;\r
+}\r
+\r
+static int free_buffers(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+\r
+       /* free skbuff */\r
+       vmac_tx_reclaim(dev, 1);\r
+       vmac_rx_reclaim_force(dev);\r
+\r
+       /* free DMA ring */\r
+       dma_free_coherent(&ap->pdev->dev, sizeof(ap->txbd) * ap->tx_ring.size,\r
+                       ap->txbd, ap->txbd_dma);\r
+       dma_free_coherent(&ap->pdev->dev, sizeof(ap->rxbd) * ap->rx_ring.size,\r
+                       ap->rxbd, ap->rxbd_dma);\r
+\r
+       return 0;\r
+}\r
+\r
+static int vmac_hw_init(struct net_device *dev)\r
+{\r
+       struct vmac_priv *priv = netdev_priv(dev);\r
+\r
+       /* clear IRQ mask */\r
+       vmac_writel(priv, 0, ENABLE);\r
+\r
+       /* clear pending IRQ */\r
+       vmac_writel(priv, 0xffffffff, STAT);\r
+\r
+       /* Initialize logical address filter */\r
+       vmac_writel(priv, 0x0, LAFL);\r
+       vmac_writel(priv, 0x0, LAFH);\r
+\r
+       return 0;\r
+}\r
+\r
+#ifdef DEBUG\r
+static int vmac_register_print(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+\r
+       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ID", vmac_readl(ap, ID));\r
+       printk("func::%s vmac register %s value = 0x%x\n", __func__, "STAT", vmac_readl(ap, STAT));\r
+       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ENABLE", vmac_readl(ap, ENABLE));\r
+       printk("func::%s vmac register %s value = 0x%x\n", __func__, "CONTROL", vmac_readl(ap, CONTROL));\r
+       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ADDRL", vmac_readl(ap, ADDRL));\r
+       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ADDRH", vmac_readl(ap, ADDRH));\r
+       \r
+       return 0;\r
+}\r
+#endif\r
+\r
+int vmac_open(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct phy_device *phydev;\r
+       unsigned int temp;\r
+       int err = 0;\r
+       struct clk *mac_clk = NULL;\r
+       struct clk *mac_parent = NULL;\r
+       struct clk *arm_clk = NULL;\r
+       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
+       unsigned char current_mac[6];\r
+       int ret = 0;\r
+       struct pinctrl_state *clkout_state;\r
+\r
+       printk("enter func %s...\n", __func__);\r
+\r
+       if (ap == NULL)\r
+               return -ENODEV;\r
+\r
+       wake_lock_timeout(&ap->resume_lock, 5*HZ);\r
+\r
+       ap->shutdown = 0;\r
+       \r
+       // switch to rmii\r
+       printk("ap->pdev->dev.pins->p = %p\n", ap->pdev->dev.pins->p);\r
+       clkout_state = pinctrl_lookup_state(ap->pdev->dev.pins->p, "default");\r
+       if (IS_ERR(clkout_state)) {\r
+               dev_err(&ap->pdev->dev, "no clkout pinctrl state\n");\r
+               goto err_out;\r
+       }\r
+       \r
+       printk("in pinctrl_select_state.\n");\r
+       pinctrl_select_state(ap->pdev->dev.pins->p, clkout_state);\r
+               \r
+       //set rmii ref clock 50MHz\r
+       mac_clk = devm_clk_get(&ap->pdev->dev, "clk_mac");\r
+       /*if (IS_ERR(mac_clk))\r
+               mac_clk = NULL;\r
+       arm_clk = clk_get(NULL, "arm_pll");\r
+       if (IS_ERR(arm_clk))\r
+               arm_clk = NULL;\r
+       if (mac_clk) {\r
+               mac_parent = clk_get_parent(mac_clk);\r
+               if (IS_ERR(mac_parent))\r
+                       mac_parent = NULL;\r
+       }\r
+       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
+               wake_lock(&idlelock);\r
+\r
+        if(pdata && pdata->rmii_extclk_sel && pdata->rmii_extclk_sel())\r
+        {\r
+            struct clk * mac_clkin = NULL;\r
+            mac_clkin = clk_get(NULL, "rmii_clkin");\r
+            if (IS_ERR(mac_clkin)) {\r
+                pr_err("mac_clkin get fail\n");\r
+            }\r
+            clk_set_parent(mac_clk, mac_clkin); \r
+        }*/\r
+        \r
+       clk_set_rate(mac_clk, 50000000);\r
+       clk_prepare_enable(mac_clk);\r
+       //clk_enable(clk_get(NULL,"mii_rx"));\r
+       //clk_enable(clk_get(NULL,"mii_tx"));\r
+       //clk_enable(clk_get(NULL,"hclk_mac"));\r
+\r
+       //phy power on\r
+       if (pdata && pdata->rmii_power_control)\r
+               pdata->rmii_power_control(1);\r
+\r
+       msleep(1000);\r
+\r
+       vmac_hw_init(dev);\r
+\r
+//$_rbox_$_modify_$_chenxiao\r
+       if (is_valid_ether_addr(dev->dev_addr)){\r
+               strlcpy(current_mac,dev->dev_addr,6);\r
+       }\r
+\r
+#ifdef CONFIG_ETH_MAC_FROM_EEPROM\r
+       ret = eeprom_read_data(0,dev->dev_addr,6);\r
+       if (ret != 6){\r
+               printk("read mac from Eeprom fail.\n");\r
+       }else {\r
+               if (is_valid_ether_addr(dev->dev_addr)){\r
+                       printk("eth_mac_from_eeprom***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
+                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
+                                               dev->dev_addr[4],dev->dev_addr[5] );\r
+               }\r
+       }\r
+#endif\r
+\r
+#ifdef CONFIG_ETH_MAC_FROM_IDB\r
+       err = eth_mac_idb(dev->dev_addr);\r
+       if (err) {\r
+               printk("read mac from IDB fail.\n");\r
+       } else {\r
+               if (is_valid_ether_addr(dev->dev_addr)) {\r
+                       printk("eth_mac_from_idb***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
+                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
+                                               dev->dev_addr[4],dev->dev_addr[5] );\r
+               }\r
+       }\r
+#endif\r
+\r
+#ifdef CONFIG_ETH_MAC_FROM_WIFI_MAC\r
+       err = eth_mac_wifi(dev->dev_addr);\r
+       if (err) {\r
+               printk("read mac from Wifi  fail.\n");\r
+       } else {\r
+               if (is_valid_ether_addr(dev->dev_addr)) {\r
+                       printk("eth_mac_from_wifi_mac***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
+                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
+                                               dev->dev_addr[4],dev->dev_addr[5] );\r
+               }\r
+       }\r
+#endif\r
+\r
+#ifdef CONFIG_ETH_MAC_FROM_SECURE_CHIP\r
+\r
+#endif\r
+         \r
+\r
+       if (!is_valid_ether_addr(dev->dev_addr)) {\r
+               strlcpy(dev->dev_addr,current_mac,6);\r
+               printk("eth_mac_from_RANDOM***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
+                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
+                                               dev->dev_addr[4],dev->dev_addr[5] );\r
+       }\r
+//add end      \r
+\r
+       /* mac address changed? */\r
+       write_mac_reg(dev, dev->dev_addr);\r
+\r
+       err = alloc_buffers(dev);\r
+       if (err)\r
+               goto err_out;\r
+\r
+       err = request_irq(dev->irq, &vmac_intr, 0, dev->name, dev);\r
+       if (err) {\r
+               dev_err(&ap->pdev->dev, "Unable to request IRQ %d (error %d)\n",\r
+                               dev->irq, err);\r
+               goto err_free_buffers;\r
+       }\r
+\r
+       /* install DMA ring pointers */\r
+       vmac_writel(ap, ap->rxbd_dma, RXRINGPTR);\r
+       vmac_writel(ap, ap->txbd_dma, TXRINGPTR);\r
+\r
+       /* set poll rate to 1 ms */\r
+       vmac_writel(ap, POLLRATE_TIME, POLLRATE);\r
+\r
+       /* make sure we enable napi before rx interrupt  */\r
+       napi_enable(&ap->napi);\r
+\r
+       /* IRQ mask */\r
+       temp = RXINT_MASK | ERR_MASK | TXCH_MASK | MDIO_MASK;\r
+       vmac_writel(ap, temp, ENABLE);\r
+\r
+       /* Set control */\r
+       temp = (RX_BDT_LEN << 24) | (TX_BDT_LEN << 16) | TXRN_MASK | RXRN_MASK;\r
+       vmac_writel(ap, temp, CONTROL);\r
+\r
+       /* enable, after all other bits are set */\r
+       vmac_writel(ap, temp | EN_MASK, CONTROL);\r
+       \r
+       netif_start_queue(dev);\r
+       netif_carrier_off(dev);\r
+\r
+#ifdef DEBUG\r
+       vmac_register_print(dev);\r
+#endif\r
+\r
+       /* register the PHY board fixup, if needed */\r
+       err = vmac_mii_init(ap);\r
+       if (err)\r
+               goto err_free_irq;\r
+\r
+       /* schedule a link state check */\r
+       phy_start(ap->phy_dev);\r
+\r
+       phydev = ap->phy_dev;\r
+       dev_info(&ap->pdev->dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",\r
+              phydev->drv->name, dev_name(&phydev->dev), phydev->irq);\r
+\r
+       ap->suspending = 0;\r
+       ap->open_flag = 1;\r
+\r
+       return 0;\r
+\r
+err_free_irq:\r
+       free_irq(dev->irq, dev);\r
+err_free_buffers:\r
+       free_buffers(dev);\r
+err_out:       \r
+       //if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
+       //      wake_unlock(&idlelock);\r
+\r
+       return err;\r
+}\r
+\r
+int vmac_close(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned int temp;\r
+       struct clk *mac_clk = NULL;\r
+       struct clk *arm_clk = NULL;\r
+       struct clk *mac_parent = NULL;\r
+       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
+\r
+       printk("enter func %s...\n", __func__);\r
+       \r
+       if (ap->suspending == 1) \r
+               return 0;\r
+\r
+       ap->open_flag = 0;\r
+\r
+       netif_stop_queue(dev);\r
+       napi_disable(&ap->napi);\r
+\r
+       /* stop running transfers */\r
+       temp = vmac_readl(ap, CONTROL);\r
+       temp &= ~(TXRN_MASK | RXRN_MASK);\r
+       vmac_writel(ap, temp, CONTROL);\r
+\r
+       del_timer_sync(&ap->rx_timeout);\r
+\r
+       /* disable phy */\r
+       phy_stop(ap->phy_dev);\r
+       vmac_mii_exit(dev);\r
+       netif_carrier_off(dev);\r
+\r
+       /* disable interrupts */\r
+       vmac_writel(ap, 0, ENABLE);\r
+       free_irq(dev->irq, dev);\r
+\r
+       /* turn off vmac */\r
+       vmac_writel(ap, 0, CONTROL);\r
+       /* vmac_reset_hw(vmac) */\r
+\r
+       ap->shutdown = 1;\r
+       wmb();\r
+\r
+       free_buffers(dev);\r
+\r
+       //phy power off\r
+       if (pdata && pdata->rmii_power_control)\r
+               pdata->rmii_power_control(0);\r
+\r
+       //clock close\r
+       /*mac_clk = clk_get(NULL, "mac_ref_div");\r
+       if (IS_ERR(mac_clk))\r
+               mac_clk = NULL;\r
+       if (mac_clk) {\r
+               mac_parent = clk_get_parent(mac_clk);\r
+               if (IS_ERR(mac_parent))\r
+                       mac_parent = NULL;\r
+       }\r
+       arm_clk = clk_get(NULL, "arm_pll");\r
+       if (IS_ERR(arm_clk))\r
+               arm_clk = NULL;\r
+\r
+       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
+               wake_unlock(&idlelock);*/\r
+       \r
+       clk_disable(clk_get(&ap->pdev->dev,"clk_mac"));\r
+       //clk_disable(clk_get(NULL,"mii_tx"));\r
+       //clk_disable(clk_get(NULL,"hclk_mac"));\r
+       //clk_disable(clk_get(NULL,"clk_mac_pll"));\r
+\r
+       return 0;\r
+}\r
+\r
+int vmac_shutdown(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned int temp;\r
+       \r
+       printk("enter func %s...\n", __func__);\r
+\r
+       netif_stop_queue(dev);\r
+       napi_disable(&ap->napi);\r
+\r
+       /* stop running transfers */\r
+       temp = vmac_readl(ap, CONTROL);\r
+       temp &= ~(TXRN_MASK | RXRN_MASK);\r
+       vmac_writel(ap, temp, CONTROL);\r
+\r
+       del_timer_sync(&ap->rx_timeout);\r
+\r
+       /* disable phy */\r
+       phy_stop(ap->phy_dev);\r
+       vmac_mii_exit(dev);\r
+       netif_carrier_off(dev);\r
+\r
+       /* disable interrupts */\r
+       vmac_writel(ap, 0, ENABLE);\r
+       free_irq(dev->irq, dev);\r
+\r
+       /* turn off vmac */\r
+       vmac_writel(ap, 0, CONTROL);\r
+       /* vmac_reset_hw(vmac) */\r
+\r
+       ap->shutdown = 1;\r
+       wmb();\r
+\r
+       free_buffers(dev);\r
+\r
+       return 0;\r
+}\r
+\r
+void vmac_update_stats(struct vmac_priv *ap)\r
+{\r
+       struct net_device_stats *_stats = &ap->stats;\r
+       unsigned long miss, rxerr;\r
+       unsigned long rxfram, rxcrc, rxoflow;\r
+\r
+       /* compare with /proc/net/dev,\r
+        * see net/core/dev.c:dev_seq_printf_stats */\r
+\r
+       /* rx stats */\r
+       rxerr = vmac_readl(ap, RXERR);\r
+       miss = vmac_readl(ap, MISS);\r
+\r
+       rxcrc = (rxerr & RXERR_CRC);\r
+       rxfram = (rxerr & RXERR_FRM) >> 8;\r
+       rxoflow = (rxerr & RXERR_OFLO) >> 16;\r
+\r
+       _stats->rx_length_errors = 0;\r
+       _stats->rx_over_errors += miss;\r
+       _stats->rx_crc_errors += rxcrc;\r
+       _stats->rx_frame_errors += rxfram;\r
+       _stats->rx_fifo_errors += rxoflow;\r
+       _stats->rx_missed_errors = 0;\r
+\r
+       /* TODO check rx_dropped/rx_errors/tx_dropped/tx_errors have not\r
+        * been updated elsewhere */\r
+       _stats->rx_dropped = _stats->rx_over_errors +\r
+               _stats->rx_fifo_errors +\r
+               ap->rx_merge_error;\r
+\r
+       _stats->rx_errors = _stats->rx_length_errors + _stats->rx_crc_errors +\r
+               _stats->rx_frame_errors +\r
+               _stats->rx_missed_errors +\r
+               _stats->rx_dropped;\r
+\r
+       /* tx stats */\r
+       _stats->tx_dropped = 0; /* otherwise queue stopped */\r
+\r
+       _stats->tx_errors = _stats->tx_aborted_errors +\r
+               _stats->tx_carrier_errors +\r
+               _stats->tx_fifo_errors +\r
+               _stats->tx_heartbeat_errors +\r
+               _stats->tx_window_errors +\r
+               _stats->tx_dropped +\r
+               ap->tx_timeout_error;\r
+}\r
+\r
+struct net_device_stats *vmac_stats(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+       vmac_update_stats(ap);\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+\r
+       return &ap->stats;\r
+}\r
+\r
+void vmac_tx_timeout(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned int status;\r
+       unsigned long flags;\r
+\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+\r
+       /* queue did not progress for timeo jiffies */\r
+       WARN_ON(!netif_queue_stopped(dev));\r
+       WARN_ON(!fifo_full(&ap->tx_ring));\r
+\r
+       /* TX IRQ lost? */\r
+       status = vmac_readl(ap, STAT);\r
+       if (status & TXINT_MASK) {\r
+               dev_err(&ap->pdev->dev, "lost tx interrupt, IRQ mask %x\n",\r
+                               vmac_readl(ap, ENABLE));\r
+               vmac_writel(ap, TXINT_MASK, STAT);\r
+       }\r
+\r
+       /* TODO RX/MDIO/ERR as well? */\r
+\r
+       vmac_tx_reclaim(dev, 0);\r
+       if (fifo_full(&ap->tx_ring))\r
+               dev_err(&ap->pdev->dev, "DMA state machine not active\n");\r
+\r
+       /* We can accept TX packets again */\r
+       ap->tx_timeout_error++;\r
+       dev->trans_start = jiffies;\r
+       netif_wake_queue(dev);\r
+\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+}\r
+\r
+static void create_multicast_filter(struct net_device *dev,\r
+       unsigned long *bitmask)\r
+{\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
+       struct netdev_hw_addr *ha;\r
+       unsigned long crc;\r
+       char *addrs;\r
+       struct netdev_hw_addr_list *list = &dev->dev_addrs;\r
+       \r
+       //printk("-----------------func %s-------------------\n", __func__);\r
+\r
+       WARN_ON(dev->mc_count == 0);\r
+       WARN_ON(dev->flags & IFF_ALLMULTI);\r
+\r
+       bitmask[0] = bitmask[1] = 0;\r
+\r
+       list_for_each_entry(ha, &list->list, list) {\r
+               addrs = ha->addr;\r
+\r
+               /* skip non-multicast addresses */\r
+               if (!(*addrs & 1))\r
+                       continue;\r
+\r
+               crc = ether_crc_le(ETH_ALEN, addrs);\r
+               set_bit(crc >> 26, bitmask);\r
+               \r
+       }\r
+#else\r
+       struct netdev_hw_addr *ha;\r
+       unsigned long crc;\r
+       char *addrs;\r
+\r
+       WARN_ON(netdev_mc_count(dev) == 0);\r
+       WARN_ON(dev->flags & IFF_ALLMULTI);\r
+\r
+       bitmask[0] = bitmask[1] = 0;\r
+\r
+       netdev_for_each_mc_addr(ha, dev) {\r
+               addrs = ha->addr;\r
+\r
+               /* skip non-multicast addresses */\r
+               if (!(*addrs & 1))\r
+                       continue;\r
+\r
+               crc = ether_crc_le(ETH_ALEN, addrs);\r
+               set_bit(crc >> 26, bitmask);\r
+       }\r
+#endif\r
+}\r
+static void vmac_set_multicast_list(struct net_device *dev)\r
+{\r
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned long flags, bitmask[2];\r
+       int promisc, reg;\r
+\r
+       //printk("-----------------func %s-------------------\n", __func__);\r
+\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+\r
+       promisc = !!(dev->flags & IFF_PROMISC);\r
+       reg = vmac_readl(ap, CONTROL);\r
+       if (promisc != !!(reg & PROM_MASK)) {\r
+               reg ^= PROM_MASK;\r
+               vmac_writel(ap, reg, CONTROL);\r
+       }\r
+\r
+       if (dev->flags & IFF_ALLMULTI)\r
+               memset(bitmask, 1, sizeof(bitmask));\r
+       else if (dev->mc_count == 0)\r
+               memset(bitmask, 0, sizeof(bitmask));\r
+       else\r
+               create_multicast_filter(dev, bitmask);\r
+\r
+       vmac_writel(ap, bitmask[0], LAFL);\r
+       vmac_writel(ap, bitmask[1], LAFH);\r
+\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+#else\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       unsigned long flags, bitmask[2];\r
+       int promisc, reg;\r
+\r
+       spin_lock_irqsave(&ap->lock, flags);\r
+\r
+       promisc = !!(dev->flags & IFF_PROMISC);\r
+       reg = vmac_readl(ap, CONTROL);\r
+       if (promisc != !!(reg & PROM_MASK)) {\r
+               reg ^= PROM_MASK;\r
+               vmac_writel(ap, reg, CONTROL);\r
+       }\r
+\r
+       if (dev->flags & IFF_ALLMULTI)\r
+               memset(bitmask, 1, sizeof(bitmask));\r
+       else if (netdev_mc_count(dev) == 0)\r
+               memset(bitmask, 0, sizeof(bitmask));\r
+       else\r
+               create_multicast_filter(dev, bitmask);\r
+\r
+       vmac_writel(ap, bitmask[0], LAFL);\r
+       vmac_writel(ap, bitmask[1], LAFH);\r
+\r
+       spin_unlock_irqrestore(&ap->lock, flags);\r
+#endif\r
+}\r
+\r
+static struct ethtool_ops vmac_ethtool_ops = {\r
+       .get_settings           = vmacether_get_settings,\r
+       .set_settings           = vmacether_set_settings,\r
+       .get_drvinfo            = vmacether_get_drvinfo,\r
+       .get_link               = ethtool_op_get_link,\r
+};\r
+\r
+static const struct net_device_ops vmac_netdev_ops = {\r
+       .ndo_open               = vmac_open,\r
+       .ndo_stop               = vmac_close,\r
+       .ndo_get_stats          = vmac_stats,\r
+       .ndo_start_xmit         = vmac_start_xmit,\r
+       .ndo_do_ioctl           = vmac_ioctl,\r
+       .ndo_set_mac_address    = eth_mac_addr,\r
+       .ndo_tx_timeout         = vmac_tx_timeout,\r
+       //.ndo_set_multicast_list = vmac_set_multicast_list,\r
+       .ndo_validate_addr      = eth_validate_addr,\r
+       .ndo_change_mtu         = eth_change_mtu,\r
+};\r
+\r
+static int vmac_probe(struct platform_device *pdev)\r
+{\r
+       struct net_device *dev;\r
+       struct vmac_priv *ap;\r
+       struct resource *res;\r
+       unsigned int mem_base, mem_size, irq;\r
+       int err;\r
+       struct rk29_vmac_platform_data *pdata;\r
+       struct device_node *np = pdev->dev.of_node;\r
+       \r
+       printk("vmac_probe.\n");\r
+       dev_dbg(&pdev->dev, "vmac_probe 1.\n");\r
+       \r
+       pdev->dev.platform_data = &board_vmac_data;\r
+       pdata = pdev->dev.platform_data;\r
+\r
+       dev = alloc_etherdev(sizeof(*ap));\r
+       if (!dev) {\r
+               dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");\r
+               return -ENOMEM;\r
+       }\r
+\r
+       ap = netdev_priv(dev);\r
+\r
+       err = -ENODEV;\r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       if (!res) {\r
+               dev_err(&pdev->dev, "no mmio resource defined\n");\r
+               goto err_out;\r
+       }\r
+       mem_base = res->start;\r
+       mem_size = resource_size(res);\r
+       irq = platform_get_irq(pdev, 0);\r
+\r
+       /*err = -EBUSY;\r
+       if (!devm_request_mem_region(&pdev->dev, mem_base, mem_size, VMAC_NAME)) {\r
+               dev_err(&pdev->dev, "no memory region available\n");\r
+               goto err_out;\r
+       }*/\r
+\r
+       err = -ENOMEM;\r
+       ap->regs = devm_ioremap_resource(&pdev->dev, res);\r
+       if (!ap->regs) {\r
+               dev_err(&pdev->dev, "failed to map registers, aborting.\n");\r
+               goto err_out_release_mem;\r
+       }\r
+       \r
+       printk("mem_base = 0x%08x, mem_size = 0x%08x, irq = %d, regs = 0x%08x\n", \r
+               mem_base, mem_size, irq, ap->regs);\r
+\r
+       /* no checksum support, hence no scatter/gather */\r
+       dev->features |= NETIF_F_HIGHDMA;\r
+\r
+       spin_lock_init(&ap->lock);\r
+\r
+       SET_NETDEV_DEV(dev, &pdev->dev);\r
+       ap->dev = dev;\r
+       ap->pdev = pdev;\r
+\r
+       /* init rx timeout (used for oom) */\r
+       init_timer(&ap->rx_timeout);\r
+       ap->rx_timeout.function = vmac_refill_rx_timer;\r
+       ap->rx_timeout.data = (unsigned long)dev;\r
+\r
+       netif_napi_add(dev, &ap->napi, vmac_poll, 2);\r
+       dev->netdev_ops = &vmac_netdev_ops;\r
+       dev->ethtool_ops = &vmac_ethtool_ops;\r
+       dev->irq = irq;\r
+\r
+       dev->flags |= IFF_MULTICAST;////////////////////\r
+\r
+       dev->base_addr = (unsigned long)ap->regs;\r
+       ap->mem_base = mem_base;\r
+\r
+       /* prevent buffer chaining, favor speed over space */\r
+       ap->rx_skb_size = ETH_FRAME_LEN + VMAC_BUFFER_PAD;\r
+\r
+       /* private struct functional */\r
+\r
+       /* mac address intialize, set vmac_open  */\r
+       read_mac_reg(dev, dev->dev_addr);\r
+\r
+       if (!is_valid_ether_addr(dev->dev_addr))\r
+               random_ether_addr(dev->dev_addr);\r
+\r
+       err = register_netdev(dev);\r
+       if (err) {\r
+               dev_err(&pdev->dev, "Cannot register net device, aborting.\n");\r
+               goto err_out_iounmap;\r
+       }\r
+\r
+       dev_info(&pdev->dev, "ARC VMAC at 0x%08x irq %d %pM\n", mem_base,\r
+           dev->irq, dev->dev_addr);\r
+       platform_set_drvdata(pdev, dev);\r
+\r
+       ap->suspending = 0;\r
+       ap->open_flag = 0;\r
+       //wake_lock_init(&idlelock, WAKE_LOCK_IDLE, "vmac");\r
+       wake_lock_init(&ap->resume_lock, WAKE_LOCK_SUSPEND, "vmac_resume");\r
+\r
+       //config rk29 vmac as rmii, 100MHz \r
+       if (pdata && pdata->vmac_register_set)\r
+               pdata->vmac_register_set();\r
+\r
+       //power gpio init, phy power off default for power reduce\r
+       if (pdata && pdata->rmii_io_init)\r
+               pdata->rmii_io_init();\r
+\r
+       return 0;\r
+\r
+err_out_iounmap:\r
+       iounmap(ap->regs);\r
+err_out_release_mem:\r
+       release_mem_region(mem_base, mem_size);\r
+err_out:\r
+       free_netdev(dev);\r
+       return err;\r
+}\r
+\r
+static int vmac_remove(struct platform_device *pdev)\r
+{\r
+       struct net_device *dev;\r
+       struct vmac_priv *ap;\r
+       struct resource *res;\r
+       struct rk29_vmac_platform_data *pdata = pdev->dev.platform_data;\r
+\r
+       //wake_lock_destroy(&idlelock);\r
+\r
+       //power gpio deinit, phy power off\r
+       if (pdata && pdata->rmii_io_deinit)\r
+               pdata->rmii_io_deinit();\r
+\r
+       dev = platform_get_drvdata(pdev);\r
+       if (!dev) {\r
+               dev_err(&pdev->dev, "%s no valid dev found\n", __func__);\r
+               return 0;\r
+       }\r
+\r
+       ap = netdev_priv(dev);\r
+\r
+       /* MAC */\r
+       unregister_netdev(dev);\r
+       iounmap(ap->regs);\r
+\r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       release_mem_region(res->start, resource_size(res));\r
+\r
+       platform_set_drvdata(pdev, NULL);\r
+       free_netdev(dev);\r
+       return 0;\r
+}\r
+\r
+static void rk29_vmac_power_off(struct net_device *dev)\r
+{\r
+       struct vmac_priv *ap = netdev_priv(dev);\r
+       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
+\r
+       printk("enter func %s...\n", __func__);\r
+\r
+       //phy power off\r
+       if (pdata && pdata->rmii_power_control)\r
+               pdata->rmii_power_control(0);\r
+\r
+       //clock close\r
+       clk_disable(clk_get(&ap->pdev->dev,"clk_mac"));\r
+       //clk_disable(clk_get(NULL,"mii_tx"));\r
+       //clk_disable(clk_get(NULL,"hclk_mac"));\r
+       //clk_disable(clk_get(NULL,"clk_mac_pll"));\r
+\r
+}\r
+\r
+static int\r
+rk29_vmac_suspend(struct device *dev)\r
+{\r
+       struct platform_device *pdev = to_platform_device(dev);\r
+       struct net_device *ndev = platform_get_drvdata(pdev);\r
+       struct vmac_priv *ap = netdev_priv(ndev);\r
+       \r
+       if (ndev) {\r
+               if (ap->open_flag == 1) {\r
+                       netif_stop_queue(ndev);\r
+                       netif_device_detach(ndev);\r
+                       if (ap->suspending == 0) {\r
+//$_rbox_$_modify_$_chenzhi: for ethernet sleep\r
+#if 0\r
+                               vmac_shutdown(ndev);\r
+                               rk29_vmac_power_off(ndev);\r
+#endif\r
+                               ap->suspending = 1;\r
+                       }\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int\r
+rk29_vmac_resume(struct device *dev)\r
+{\r
+       struct platform_device *pdev = to_platform_device(dev);\r
+       struct net_device *ndev = platform_get_drvdata(pdev);\r
+       struct vmac_priv *ap = netdev_priv(ndev);\r
+       \r
+       if (ndev) {\r
+               if (ap->open_flag == 1) {\r
+                       netif_device_attach(ndev);\r
+                       netif_start_queue(ndev);\r
+//$_rbox_$_modify_$_chenzhi: \r
+//$_rbox_$_modify_$_begin\r
+                       if (ap->suspending == 1) {\r
+                               ap->suspending = 0;\r
+                       }\r
+//$_rbox_$_modify_$_end\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+static struct dev_pm_ops rk29_vmac_pm_ops = {\r
+       .suspend        = rk29_vmac_suspend,\r
+       .resume         = rk29_vmac_resume,\r
+};\r
+\r
+static const struct of_device_id rockchip_vmac_of_match[] = {\r
+       { .compatible = "rockchip,vmac", .data = NULL, },\r
+       {},\r
+};\r
+MODULE_DEVICE_TABLE(of, rockchip_vmac_of_match);\r
+\r
+static struct platform_driver rockchip_vmac_driver = {\r
+       .probe          = vmac_probe,\r
+       .remove         = vmac_remove,\r
+       .driver         = {\r
+               .owner  = THIS_MODULE,\r
+               .name   = "rockchip,vmac",\r
+               .pm     = &rk29_vmac_pm_ops,\r
+               .of_match_table = of_match_ptr(rockchip_vmac_of_match),\r
+       },\r
+};\r
+\r
+static int __init vmac_init(void)\r
+{\r
+       printk("vmac_init.\n");\r
+       return platform_driver_register(&rockchip_vmac_driver);\r
+}\r
+\r
+static void __exit vmac_exit(void)\r
+{\r
+       platform_driver_unregister(&rockchip_vmac_driver);\r
+}\r
+\r
+module_init(vmac_init);\r
+module_exit(vmac_exit);\r
+\r
+MODULE_LICENSE("GPL");\r
+MODULE_DESCRIPTION("RK29 VMAC Ethernet driver");\r
+MODULE_AUTHOR("amit.bhor@celunite.com, sameer.dhavale@celunite.com, andreas.fenkart@streamunlimited.com");\r
diff --git a/drivers/net/ethernet/rk/vmac/rk29_vmac.h b/drivers/net/ethernet/rk/vmac/rk29_vmac.h
new file mode 100755 (executable)
index 0000000..a6cf94e
--- /dev/null
@@ -0,0 +1,287 @@
+/*\r
+ * linux/arch/arc/drivers/arcvmac.h\r
+ *\r
+ * Copyright (C) 2003-2006 Codito Technologies, for linux-2.4 port\r
+ * Copyright (C) 2006-2007 Celunite Inc, for linux-2.6 port\r
+ * Copyright (C) 2007-2008 Sagem Communications, Fehmi HAFSI\r
+ * Copyright (C) 2009 Sagem Communications, Andreas Fenkart\r
+ * All Rights Reserved.\r
+ *\r
+ This program is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+ * Authors: amit.bhor@celunite.com, sameer.dhavale@celunite.com\r
+ */\r
+\r
+#ifndef _ARCVMAC_H\r
+#define _ARCVMAC_H\r
+\r
+#define VMAC_NAME              "rockchip,vmac"\r
+#define VMAC_VERSION           "1.0"\r
+\r
+/* Buffer descriptors */\r
+#ifdef CONFIG_ARCH_RK29\r
+#define TX_BDT_LEN             16    /* Number of receive BD's */\r
+#else\r
+#define TX_BDT_LEN             255   /* Number of receive BD's */\r
+#endif\r
+#define RX_BDT_LEN             255   /* Number of transmit BD's */\r
+\r
+/* BD poll rate, in 1024 cycles. @100Mhz: x * 1024 cy * 10ns = 1ms */\r
+#define POLLRATE_TIME          200\r
+\r
+/* next power of two, bigger than ETH_FRAME_LEN + VLAN  */\r
+#define MAX_RX_BUFFER_LEN      0x800   /* 2^11 = 2048 = 0x800 */\r
+#define MAX_TX_BUFFER_LEN      0x800   /* 2^11 = 2048 = 0x800 */\r
+\r
+/* 14 bytes of ethernet header, 4 bytes VLAN, FCS,\r
+ * plus extra pad to prevent buffer chaining of\r
+ * maximum sized ethernet packets (1514 bytes) */\r
+#define        VMAC_BUFFER_PAD         (ETH_HLEN + 4 + ETH_FCS_LEN + 4)\r
+\r
+/* VMAC register definitions, offsets in the ref manual are in bytes */\r
+#define ID_OFFSET              (0x00/0x4)\r
+#define STAT_OFFSET            (0x04/0x4)\r
+#define ENABLE_OFFSET          (0x08/0x4)\r
+#define CONTROL_OFFSET         (0x0c/0x4)\r
+#define POLLRATE_OFFSET                (0x10/0x4)\r
+#define RXERR_OFFSET           (0x14/0x4)\r
+#define MISS_OFFSET            (0x18/0x4)\r
+#define TXRINGPTR_OFFSET       (0x1c/0x4)\r
+#define RXRINGPTR_OFFSET       (0x20/0x4)\r
+#define ADDRL_OFFSET           (0x24/0x4)\r
+#define ADDRH_OFFSET           (0x28/0x4)\r
+#define LAFL_OFFSET            (0x2c/0x4)\r
+#define LAFH_OFFSET            (0x30/0x4)\r
+#define MDIO_DATA_OFFSET       (0x34/0x4)\r
+#define MAC_TXRING_HEAD_OFFSET (0x38/0x4)\r
+#define MAC_RXRING_HEAD_OFFSET (0x3C/0x4)\r
+\r
+/* STATUS and ENABLE register bit masks */\r
+#define TXINT_MASK             (1<<0)  /* Transmit interrupt */\r
+#define RXINT_MASK             (1<<1)  /* Receive interrupt */\r
+#define ERR_MASK               (1<<2)  /* Error interrupt */\r
+#define TXCH_MASK              (1<<3)  /* Transmit chaining error interrupt */\r
+#define MSER_MASK              (1<<4)  /* Missed packet counter error */\r
+#define RXCR_MASK              (1<<8)  /* RXCRCERR counter rolled over  */\r
+#define RXFR_MASK              (1<<9)  /* RXFRAMEERR counter rolled over */\r
+#define RXFL_MASK              (1<<10) /* RXOFLOWERR counter rolled over */\r
+#define MDIO_MASK              (1<<12) /* MDIO complete */\r
+#define TXPL_MASK              (1<<31) /* TXPOLL */\r
+\r
+/* CONTROL register bitmasks */\r
+#define EN_MASK                        (1<<0)  /* VMAC enable */\r
+#define TXRN_MASK              (1<<3)  /* TX enable */\r
+#define RXRN_MASK              (1<<4)  /* RX enable */\r
+#define DSBC_MASK              (1<<8)  /* Disable receive broadcast */\r
+#define ENFL_MASK              (1<<10) /* Enable Full Duplex */            ///////\r
+#define PROM_MASK              (1<<11) /* Promiscuous mode */\r
+\r
+/* RXERR register bitmasks */\r
+#define RXERR_CRC              0x000000ff\r
+#define RXERR_FRM              0x0000ff00\r
+#define RXERR_OFLO             0x00ff0000 /* fifo overflow */\r
+\r
+/* MDIO data register bit masks */\r
+#define MDIO_SFD               0xC0000000\r
+#define MDIO_OP                        0x30000000\r
+#define MDIO_ID_MASK           0x0F800000\r
+#define MDIO_REG_MASK          0x007C0000\r
+#define MDIO_TA                        0x00030000\r
+#define MDIO_DATA_MASK         0x0000FFFF\r
+\r
+#define MDIO_BASE              0x40020000\r
+#define MDIO_OP_READ           0x20000000\r
+#define MDIO_OP_WRITE          0x10000000\r
+\r
+/* Buffer descriptor INFO bit masks */\r
+#define OWN_MASK               (1<<31) /* ownership of buffer, 0 CPU, 1 DMA */\r
+#define BUFF                   (1<<30) /* buffer invalid, rx */\r
+#define UFLO                   (1<<29) /* underflow, tx */\r
+#define LTCL                   (1<<28) /* late collision, tx  */\r
+#define RETRY_CT               (0xf<<24)  /* tx */\r
+#define DROP                   (1<<23) /* drop, more than 16 retries, tx */\r
+#define DEFER                  (1<<22) /* traffic on the wire, tx */\r
+#define CARLOSS                        (1<<21) /* carrier loss while transmission, tx, rx? */\r
+/* 20:19 reserved */\r
+#define ADCR                   (1<<18) /* add crc, ignored if not disaddcrc */\r
+#define LAST_MASK              (1<<17) /* Last buffer in chain */\r
+#define FRST_MASK              (1<<16) /* First buffer in chain */\r
+/* 15:11 reserved */\r
+#define LEN_MASK               0x000007FF\r
+\r
+#define ERR_MSK_TX             0x3fe00000 /* UFLO | LTCL | RTRY | DROP | DEFER | CRLS */\r
+\r
+\r
+/* arcvmac private data structures */\r
+struct vmac_buffer_desc {\r
+       unsigned int info;\r
+       dma_addr_t data;\r
+};\r
+\r
+struct dma_fifo {\r
+       int head; /* head */\r
+       int tail; /* tail */\r
+       int size;\r
+};\r
+\r
+struct vmac_priv {\r
+       struct net_device *dev;\r
+       struct platform_device *pdev;\r
+       struct net_device_stats stats;\r
+\r
+       spinlock_t lock; /* TODO revisit */\r
+       struct completion mdio_complete;\r
+\r
+       /* base address of register set */\r
+       int *regs;\r
+       unsigned int mem_base;\r
+\r
+       /* DMA ring buffers */\r
+       struct vmac_buffer_desc *rxbd;\r
+       dma_addr_t rxbd_dma;\r
+\r
+       struct vmac_buffer_desc *txbd;\r
+       dma_addr_t txbd_dma;\r
+\r
+       /* socket buffers */\r
+       struct sk_buff *rx_skbuff[RX_BDT_LEN];\r
+       struct sk_buff *tx_skbuff[TX_BDT_LEN];\r
+       int rx_skb_size;\r
+\r
+       /* skb / dma desc managing */\r
+       struct dma_fifo rx_ring;\r
+       struct dma_fifo tx_ring;\r
+\r
+       /* descriptor last polled/processed by the VMAC */\r
+       unsigned long mac_rxring_head;\r
+       /* used when rx skb allocation failed, so we defer rx queue\r
+        * refill */\r
+       struct timer_list rx_timeout;\r
+\r
+       /* lock rx_timeout against rx normal operation */\r
+       spinlock_t rx_lock;\r
+\r
+       struct napi_struct napi;\r
+\r
+       /* rx buffer chaining */\r
+       int rx_merge_error;\r
+       int tx_timeout_error;\r
+\r
+       /* PHY stuff */\r
+       struct mii_bus *mii_bus;\r
+       struct phy_device *phy_dev;\r
+\r
+       int link;\r
+       int speed;\r
+       int duplex;\r
+\r
+       int open_flag;\r
+       int suspending;\r
+       struct wake_lock resume_lock;\r
+\r
+       /* debug */\r
+       int shutdown;\r
+};\r
+\r
+/* DMA ring management */\r
+\r
+/* for a fifo with size n,\r
+ * - [0..n] fill levels are n + 1 states\r
+ * - there are only n different deltas (head - tail) values\r
+ * => not all fill levels can be represented with head, tail\r
+ *    pointers only\r
+ * we give up the n fill level, aka fifo full */\r
+\r
+/* sacrifice one elt as a sentinel */\r
+static inline int fifo_used(struct dma_fifo *f);\r
+static inline int fifo_inc_ct(int ct, int size);\r
+static inline void fifo_dump(struct dma_fifo *fifo);\r
+\r
+static inline int fifo_empty(struct dma_fifo *f)\r
+{\r
+       return (f->head == f->tail);\r
+}\r
+\r
+static inline int fifo_free(struct dma_fifo *f)\r
+{\r
+       int free;\r
+\r
+       free = f->tail - f->head;\r
+       if (free <= 0)\r
+               free += f->size;\r
+\r
+       return free;\r
+}\r
+\r
+static inline int fifo_used(struct dma_fifo *f)\r
+{\r
+       int used;\r
+\r
+       used = f->head - f->tail;\r
+       if (used < 0)\r
+               used += f->size;\r
+\r
+       return used;\r
+}\r
+\r
+static inline int fifo_full(struct dma_fifo *f)\r
+{\r
+       return (fifo_used(f) + 1) == f->size;\r
+}\r
+\r
+/* manipulate */\r
+static inline void fifo_init(struct dma_fifo *fifo, int size)\r
+{\r
+       fifo->size = size;\r
+       fifo->head = fifo->tail = 0; /* empty */\r
+}\r
+\r
+static inline void fifo_inc_head(struct dma_fifo *fifo)\r
+{\r
+       BUG_ON(fifo_full(fifo));\r
+       fifo->head = fifo_inc_ct(fifo->head, fifo->size);\r
+}\r
+\r
+static inline void fifo_inc_tail(struct dma_fifo *fifo)\r
+{\r
+       BUG_ON(fifo_empty(fifo));\r
+       fifo->tail = fifo_inc_ct(fifo->tail, fifo->size);\r
+}\r
+\r
+/* internal funcs */\r
+static inline void fifo_dump(struct dma_fifo *fifo)\r
+{\r
+       printk(KERN_INFO "fifo: head %d, tail %d, size %d\n", fifo->head,\r
+                       fifo->tail,\r
+                       fifo->size);\r
+}\r
+\r
+static inline int fifo_inc_ct(int ct, int size)\r
+{\r
+       return (++ct == size) ? 0 : ct;\r
+}\r
+\r
+/*vmac*/\r
+struct rk29_vmac_platform_data {\r
+    int (*vmac_register_set)(void);\r
+    int (*rmii_io_init)(void);\r
+    int (*rmii_io_deinit)(void);\r
+    int (*rmii_power_control)(int enable);\r
+    int(*rmii_speed_switch)(int speed);\r
+};\r
+\r
+extern struct rk29_vmac_platform_data board_vmac_data;\r
+\r
+#endif   /* _ARCVMAC_H */\r
diff --git a/drivers/net/ethernet/rk/vmac/rk29_vmac_phy.c b/drivers/net/ethernet/rk/vmac/rk29_vmac_phy.c
new file mode 100755 (executable)
index 0000000..2adb9f9
--- /dev/null
@@ -0,0 +1,109 @@
+
+#include <linux/clk.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/wakelock.h>
+#include <linux/version.h>
+#include <linux/gpio.h>
+#include <asm/irq.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+
+#include "../../../../../arch/arm/mach-rockchip/iomap.h"
+#include "../../../../../arch/arm/mach-rockchip/grf.h"
+
+#include "rk29_vmac.h"
+
+#define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
+#define grf_writel(v, offset)  do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
+
+static int rk30_vmac_register_set(void)
+{
+       //config rk30 vmac as rmii
+       writel_relaxed(0x3 << 16 | 0x2, RK_GRF_VIRT + RK3188_GRF_SOC_CON1);
+       return 0;
+}
+
+static int rk30_rmii_io_init(void)
+{
+       int err;
+       long val;
+       printk("enter %s ",__func__);
+
+       //rk3188 gpio3 and sdio drive strength , 
+       val = grf_readl(RK3188_GRF_IO_CON3);
+       grf_writel(val|(0x0f<<16)|0x0f, RK3188_GRF_IO_CON3);
+         
+       //phy power gpio
+       /*err = gpio_request(PHY_PWR_EN_GPIO, "phy_power_en");
+       if (err) {
+             printk("request phy power en pin faile ! \n");
+               return -1;
+       }
+       //phy power down
+       gpio_direction_output(PHY_PWR_EN_GPIO, !PHY_PWR_EN_VALUE);
+       gpio_set_value(PHY_PWR_EN_GPIO, !PHY_PWR_EN_VALUE);*/
+
+       return 0;
+}
+
+static int rk30_rmii_io_deinit(void)
+{
+       //phy power down
+       printk("enter %s ",__func__);
+       //gpio_direction_output(PHY_PWR_EN_GPIO, !PHY_PWR_EN_VALUE);
+       //gpio_set_value(PHY_PWR_EN_GPIO, !PHY_PWR_EN_VALUE);
+       //free
+       //gpio_free(PHY_PWR_EN_GPIO);
+       return 0;
+}
+
+static int rk30_rmii_power_control(int enable)
+{
+      printk("enter %s ,enable = %d ",__func__,enable);
+       if (enable) {
+               //enable phy power
+               printk("power on phy\n");
+       
+               //gpio_direction_output(PHY_PWR_EN_GPIO, PHY_PWR_EN_VALUE);
+               //gpio_set_value(PHY_PWR_EN_GPIO, PHY_PWR_EN_VALUE);
+
+               //gpio reset            
+       }else {
+               //gpio_direction_output(PHY_PWR_EN_GPIO, !PHY_PWR_EN_VALUE);
+               //gpio_set_value(PHY_PWR_EN_GPIO, !PHY_PWR_EN_VALUE);
+       }
+       return 0;
+}
+
+#define BIT_EMAC_SPEED_100M      (1 << 1)
+#define BIT_EMAC_SPEED_10M       (0 << 1)
+static int rk29_vmac_speed_switch(int speed)
+{
+       //printk("%s--speed=%d\n", __FUNCTION__, speed);
+       if (10 == speed) {
+           writel_relaxed((2<<16)|BIT_EMAC_SPEED_10M, RK_GRF_VIRT + RK3188_GRF_SOC_CON1);
+       } else {
+           writel_relaxed((2<<16)|BIT_EMAC_SPEED_100M, RK_GRF_VIRT + RK3188_GRF_SOC_CON1);
+       }
+}
+
+struct rk29_vmac_platform_data board_vmac_data = {
+       .vmac_register_set = rk30_vmac_register_set,
+       .rmii_io_init = rk30_rmii_io_init,
+       .rmii_io_deinit = rk30_rmii_io_deinit,
+       .rmii_power_control = rk30_rmii_power_control,
+       .rmii_speed_switch = rk29_vmac_speed_switch,
+};
diff --git a/drivers/net/rk29_vmac.c b/drivers/net/rk29_vmac.c
deleted file mode 100755 (executable)
index 8a134a5..0000000
+++ /dev/null
@@ -1,1794 +0,0 @@
-/*\r
- * linux/arch/arc/drivers/arcvmac.c\r
- *\r
- * Copyright (C) 2003-2006 Codito Technologies, for linux-2.4 port\r
- * Copyright (C) 2006-2007 Celunite Inc, for linux-2.6 port\r
- * Copyright (C) 2007-2008 Sagem Communications, Fehmi HAFSI\r
- * Copyright (C) 2009 Sagem Communications, Andreas Fenkart\r
- * All Rights Reserved.\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- *\r
- * external PHY support based on dnet.c\r
- * ring management based on bcm63xx_enet.c\r
- *\r
- * Authors: amit.bhor@celunite.com, sameer.dhavale@celunite.com\r
- */\r
-\r
-//#define DEBUG\r
-\r
-#include <linux/clk.h>\r
-#include <linux/crc32.h>\r
-#include <linux/delay.h>\r
-#include <linux/dma-mapping.h>\r
-#include <linux/etherdevice.h>\r
-#include <linux/init.h>\r
-#include <linux/io.h>\r
-#include <linux/kernel.h>\r
-#include <linux/module.h>\r
-#include <linux/moduleparam.h>\r
-#include <linux/netdevice.h>\r
-#include <linux/phy.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/slab.h>\r
-#include <linux/types.h>\r
-#include <linux/wakelock.h>\r
-#include <linux/version.h>\r
-\r
-#include <mach/iomux.h>\r
-#include <mach/gpio.h>\r
-#include <mach/cru.h>\r
-#include <mach/board.h>\r
-\r
-#include "rk29_vmac.h"\r
-#include "eth_mac/eth_mac.h"\r
-\r
-static struct wake_lock idlelock; /* add by lyx @ 20110302 */\r
-\r
-/* Register access macros */\r
-#define vmac_writel(port, value, reg)  \\r
-       writel((value), (port)->regs + reg##_OFFSET)\r
-#define vmac_readl(port, reg)  readl((port)->regs + reg##_OFFSET)\r
-\r
-static unsigned char *read_mac_reg(struct net_device *dev,\r
-               unsigned char hwaddr[ETH_ALEN])\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned mac_lo, mac_hi;\r
-\r
-       WARN_ON(!hwaddr);\r
-       mac_lo = vmac_readl(ap, ADDRL);\r
-       mac_hi = vmac_readl(ap, ADDRH);\r
-\r
-       hwaddr[0] = (mac_lo >> 0) & 0xff;\r
-       hwaddr[1] = (mac_lo >> 8) & 0xff;\r
-       hwaddr[2] = (mac_lo >> 16) & 0xff;\r
-       hwaddr[3] = (mac_lo >> 24) & 0xff;\r
-       hwaddr[4] = (mac_hi >> 0) & 0xff;\r
-       hwaddr[5] = (mac_hi >> 8) & 0xff;\r
-       return hwaddr;\r
-}\r
-\r
-static void write_mac_reg(struct net_device *dev, unsigned char* hwaddr)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned mac_lo, mac_hi;\r
-\r
-       mac_lo = hwaddr[3] << 24 | hwaddr[2] << 16 | hwaddr[1] << 8 | hwaddr[0];\r
-       mac_hi = hwaddr[5] << 8 | hwaddr[4];\r
-\r
-       vmac_writel(ap, mac_lo, ADDRL);\r
-       vmac_writel(ap, mac_hi, ADDRH);\r
-}\r
-\r
-static void vmac_mdio_xmit(struct vmac_priv *ap, unsigned val)\r
-{\r
-       init_completion(&ap->mdio_complete);\r
-       vmac_writel(ap, val, MDIO_DATA);\r
-       if(!wait_for_completion_timeout(&ap->mdio_complete, msecs_to_jiffies(1000)))\r
-               printk("Time out for waiting mdio completion\n");\r
-}\r
-\r
-static int vmac_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)\r
-{\r
-       struct vmac_priv *vmac = bus->priv;\r
-       unsigned int val;\r
-       /* only 5 bits allowed for phy-addr and reg_offset */\r
-       WARN_ON(phy_id & ~0x1f || phy_reg & ~0x1f);\r
-\r
-       val = MDIO_BASE | MDIO_OP_READ;\r
-       val |= phy_id << 23 | phy_reg << 18;\r
-       vmac_mdio_xmit(vmac, val);\r
-\r
-       val = vmac_readl(vmac, MDIO_DATA);\r
-       return val & MDIO_DATA_MASK;\r
-}\r
-\r
-static int vmac_mdio_write(struct mii_bus *bus, int phy_id, int phy_reg,\r
-                        u16 value)\r
-{\r
-       struct vmac_priv *vmac = bus->priv;\r
-       unsigned int val;\r
-       /* only 5 bits allowed for phy-addr and reg_offset */\r
-       WARN_ON(phy_id & ~0x1f || phy_reg & ~0x1f);\r
-\r
-       val = MDIO_BASE | MDIO_OP_WRITE;\r
-       val |= phy_id << 23 | phy_reg << 18;\r
-       val |= (value & MDIO_DATA_MASK);\r
-       vmac_mdio_xmit(vmac, val);\r
-       return 0;\r
-}\r
-\r
-static void vmac_handle_link_change(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct phy_device *phydev = ap->phy_dev;\r
-       unsigned long flags;\r
-       int report_change = 0;\r
-       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
-\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-\r
-       if (phydev->duplex != ap->duplex) {\r
-               unsigned tmp;\r
-\r
-               tmp = vmac_readl(ap, CONTROL);\r
-\r
-               if (phydev->duplex)\r
-                       tmp |= ENFL_MASK;\r
-               else\r
-                       tmp &= ~ENFL_MASK;\r
-\r
-               vmac_writel(ap, tmp, CONTROL);\r
-\r
-               ap->duplex = phydev->duplex;\r
-               report_change = 1;\r
-       }\r
-\r
-       if (phydev->speed != ap->speed) {\r
-               ap->speed = phydev->speed;\r
-               report_change = 1;\r
-       }\r
-\r
-       if (pdata && pdata->rmii_speed_switch)\r
-               pdata->rmii_speed_switch(phydev->speed);\r
-\r
-       if (phydev->link != ap->link) {\r
-               ap->link = phydev->link;\r
-               report_change = 1;\r
-       }\r
-\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-\r
-       if (report_change)\r
-               phy_print_status(ap->phy_dev);\r
-}\r
-\r
-static int __devinit vmac_mii_probe(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct phy_device *phydev = NULL;       \r
-       //struct clk *sys_clk;\r
-       //unsigned long clock_rate;\r
-       int phy_addr, err;\r
-\r
-\r
-#if defined (CONFIG_PHY_PORT_NUM) && (CONFIG_PHY_PORT_NUM != 0)\r
-        if (ap->mii_bus->phy_map[CONFIG_PHY_PORT_NUM])\r
-            phydev = ap->mii_bus->phy_map[CONFIG_PHY_PORT_NUM];\r
-#else\r
-       /* find the first phy */\r
-       for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {\r
-               if (ap->mii_bus->phy_map[phy_addr]) {\r
-                       phydev = ap->mii_bus->phy_map[phy_addr];\r
-                       break;\r
-               }\r
-       }\r
-#endif\r
-\r
-       if (!phydev) {\r
-               dev_err(&dev->dev, "no PHY found\n");\r
-               return -ENODEV;\r
-       }\r
-\r
-       /* add pin_irq, if avail */\r
-       phydev = phy_connect(dev, dev_name(&phydev->dev),\r
-                       &vmac_handle_link_change, 0,\r
-                       //PHY_INTERFACE_MODE_MII);\r
-                       PHY_INTERFACE_MODE_RMII);//????????\r
-       if (IS_ERR(phydev)) {\r
-               err = PTR_ERR(phydev);\r
-               dev_err(&dev->dev, "could not attach to PHY %d\n", err);\r
-               goto err_out;\r
-       }\r
-\r
-       phydev->supported &= PHY_BASIC_FEATURES;\r
-       phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause;\r
-\r
-#if 0\r
-       sys_clk = clk_get(NULL, "mac_ref");////////\r
-       if (IS_ERR(sys_clk)) {\r
-               err = PTR_ERR(sys_clk);\r
-               goto err_disconnect;\r
-       }\r
-       \r
-       clk_set_rate(sys_clk,50000000);\r
-       clock_rate = clk_get_rate(sys_clk);\r
-       clk_put(sys_clk);\r
-       \r
-       printk("%s::%d --mac clock = %d\n",__func__, __LINE__, clock_rate);\r
-       dev_dbg(&ap->pdev->dev, "clk_get: dev_name : %s %lu\n",\r
-                       dev_name(&ap->pdev->dev),\r
-                       clock_rate);\r
-\r
-       if (clock_rate < 25000000)\r
-               phydev->supported &= ~(SUPPORTED_100baseT_Half |\r
-                               SUPPORTED_100baseT_Full);\r
-#endif\r
-\r
-       phydev->advertising = phydev->supported;\r
-\r
-       ap->link = 0;\r
-       ap->speed = 0;\r
-       ap->duplex = -1;\r
-       ap->phy_dev = phydev;\r
-\r
-       return 0;\r
-//err_disconnect:\r
-//     phy_disconnect(phydev);\r
-err_out:\r
-       return err;\r
-}\r
-\r
-static int __devinit vmac_mii_init(struct vmac_priv *ap)\r
-{\r
-       int err, i;\r
-\r
-       ap->mii_bus = mdiobus_alloc();\r
-       \r
-       if (ap->mii_bus == NULL)\r
-               return -ENOMEM;\r
-\r
-       ap->mii_bus->name = "vmac_mii_bus";\r
-       ap->mii_bus->read = &vmac_mdio_read;\r
-       ap->mii_bus->write = &vmac_mdio_write;\r
-\r
-       snprintf(ap->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);\r
-\r
-       ap->mii_bus->priv = ap;\r
-\r
-       err = -ENOMEM;\r
-       ap->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);\r
-       if (!ap->mii_bus->irq)\r
-               goto err_out;\r
-\r
-       for (i = 0; i < PHY_MAX_ADDR; i++)\r
-               ap->mii_bus->irq[i] = PHY_POLL;\r
-\r
-#if 0\r
-       /* FIXME: what is it used for? */\r
-       platform_set_drvdata(ap->dev, ap->mii_bus);\r
-#endif\r
-\r
-       err = mdiobus_register(ap->mii_bus);\r
-       if (err)\r
-               goto err_out_free_mdio_irq;\r
-\r
-       err = vmac_mii_probe(ap->dev);\r
-       if (err)\r
-               goto err_out_unregister_bus;\r
-\r
-       return 0;\r
-\r
-err_out_unregister_bus:\r
-       mdiobus_unregister(ap->mii_bus);\r
-err_out_free_mdio_irq:\r
-       kfree(ap->mii_bus->irq);\r
-err_out:\r
-       mdiobus_free(ap->mii_bus);\r
-       ap->mii_bus = NULL;\r
-       return err;\r
-}\r
-\r
-static void vmac_mii_exit(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-\r
-       if (ap->phy_dev)\r
-               phy_disconnect(ap->phy_dev);\r
-       if (ap->mii_bus) {\r
-               mdiobus_unregister(ap->mii_bus);\r
-               kfree(ap->mii_bus->irq);\r
-               mdiobus_free(ap->mii_bus);\r
-               ap->mii_bus = NULL;\r
-       }\r
-}\r
-\r
-static int vmacether_get_settings(struct net_device *dev,\r
-               struct ethtool_cmd *cmd)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct phy_device *phydev = ap->phy_dev;\r
-\r
-       if (!phydev)\r
-               return -ENODEV;\r
-\r
-       return phy_ethtool_gset(phydev, cmd);\r
-}\r
-\r
-static int vmacether_set_settings(struct net_device *dev,\r
-               struct ethtool_cmd *cmd)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct phy_device *phydev = ap->phy_dev;\r
-\r
-       if (!phydev)\r
-               return -ENODEV;\r
-\r
-       return phy_ethtool_sset(phydev, cmd);\r
-}\r
-\r
-static int vmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct phy_device *phydev = ap->phy_dev;\r
-\r
-       if (!netif_running(dev))\r
-               return -EINVAL;\r
-\r
-       if (!phydev)\r
-               return -ENODEV;\r
-\r
-       return phy_mii_ioctl(phydev, rq, cmd);\r
-}\r
-\r
-static void vmacether_get_drvinfo(struct net_device *dev,\r
-               struct ethtool_drvinfo *info)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-\r
-       strlcpy(info->driver, VMAC_NAME, sizeof(info->driver));\r
-       strlcpy(info->version, VMAC_VERSION, sizeof(info->version));\r
-       snprintf(info->bus_info, sizeof(info->bus_info),\r
-                       "platform 0x%x", ap->mem_base);\r
-}\r
-\r
-static int update_error_counters(struct net_device *dev, int status)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       dev_dbg(&ap->pdev->dev, "rx error counter overrun. status = 0x%x\n",\r
-                       status);\r
-\r
-       /* programming error */\r
-       WARN_ON(status & TXCH_MASK);\r
-       WARN_ON(!(status & (MSER_MASK | RXCR_MASK | RXFR_MASK | RXFL_MASK)));\r
-\r
-       if (status & MSER_MASK)\r
-               ap->stats.rx_over_errors += 256; /* ran out of BD */\r
-       if (status & RXCR_MASK)\r
-               ap->stats.rx_crc_errors += 256;\r
-       if (status & RXFR_MASK)\r
-               ap->stats.rx_frame_errors += 256;\r
-       if (status & RXFL_MASK)\r
-               ap->stats.rx_fifo_errors += 256;\r
-\r
-       return 0;\r
-}\r
-\r
-static void update_tx_errors(struct net_device *dev, int status)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-\r
-       if (status & UFLO)\r
-               ap->stats.tx_fifo_errors++;\r
-\r
-       if (ap->duplex)\r
-               return;\r
-\r
-       /* half duplex flags */\r
-       if (status & LTCL)\r
-               ap->stats.tx_window_errors++;\r
-       if (status & RETRY_CT)\r
-               ap->stats.collisions += (status & RETRY_CT) >> 24;\r
-       if (status & DROP)  /* too many retries */\r
-               ap->stats.tx_aborted_errors++;\r
-       if (status & DEFER)\r
-               dev_vdbg(&ap->pdev->dev, "\"defer to traffic\"\n");\r
-       if (status & CARLOSS)\r
-               ap->stats.tx_carrier_errors++;\r
-}\r
-\r
-static int vmac_rx_reclaim_force(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       int ct;\r
-\r
-       ct = 0;\r
-\r
-       dev_dbg(&ap->pdev->dev, "%s need to release %d rx sk_buff\n",\r
-           __func__, fifo_used(&ap->rx_ring));\r
-\r
-       while (!fifo_empty(&ap->rx_ring) && ct++ < ap->rx_ring.size) {\r
-               struct vmac_buffer_desc *desc;\r
-               struct sk_buff *skb;\r
-               int desc_idx;\r
-\r
-               desc_idx = ap->rx_ring.tail;\r
-               desc = &ap->rxbd[desc_idx];\r
-               fifo_inc_tail(&ap->rx_ring);\r
-\r
-               if (!ap->rx_skbuff[desc_idx]) {\r
-                       dev_err(&ap->pdev->dev, "non-populated rx_skbuff found %d\n",\r
-                                       desc_idx);\r
-                       continue;\r
-               }\r
-\r
-               skb = ap->rx_skbuff[desc_idx];\r
-               ap->rx_skbuff[desc_idx] = NULL;\r
-\r
-               dma_unmap_single(&ap->pdev->dev, desc->data, skb->len,\r
-                   DMA_TO_DEVICE);\r
-\r
-               dev_kfree_skb(skb);\r
-       }\r
-\r
-       if (!fifo_empty(&ap->rx_ring)) {\r
-               dev_err(&ap->pdev->dev, "failed to reclaim %d rx sk_buff\n",\r
-                               fifo_used(&ap->rx_ring));\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-static int vmac_rx_refill(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-\r
-       WARN_ON(fifo_full(&ap->rx_ring));\r
-\r
-       while (!fifo_full(&ap->rx_ring)) {\r
-               struct vmac_buffer_desc *desc;\r
-               struct sk_buff *skb;\r
-               dma_addr_t p;\r
-               int desc_idx;\r
-\r
-               desc_idx = ap->rx_ring.head;\r
-               desc = &ap->rxbd[desc_idx];\r
-\r
-               /* make sure we read the actual descriptor status */\r
-               rmb();\r
-\r
-               if (ap->rx_skbuff[desc_idx]) {\r
-                       /* dropped packet / buffer chaining */\r
-                       fifo_inc_head(&ap->rx_ring);\r
-\r
-                       /* return to DMA */\r
-                       wmb();\r
-                       desc->info = OWN_MASK | ap->rx_skb_size;\r
-                       continue;\r
-               }\r
-\r
-               skb = netdev_alloc_skb(dev, ap->rx_skb_size + 2);\r
-               if (!skb) {\r
-                       dev_info(&ap->pdev->dev, "failed to allocate rx_skb, skb's left %d\n",\r
-                                       fifo_used(&ap->rx_ring));\r
-                       break;\r
-               }\r
-\r
-               /* IP header Alignment (14 byte Ethernet header) */\r
-               skb_reserve(skb, 2);\r
-               WARN_ON(skb->len != 0); /* nothing received yet */\r
-\r
-               ap->rx_skbuff[desc_idx] = skb;\r
-\r
-               p = dma_map_single(&ap->pdev->dev, skb->data, ap->rx_skb_size,\r
-                               DMA_FROM_DEVICE);\r
-\r
-               desc->data = p;\r
-\r
-               wmb();\r
-               desc->info = OWN_MASK | ap->rx_skb_size;\r
-\r
-               fifo_inc_head(&ap->rx_ring);\r
-       }\r
-\r
-       /* If rx ring is still empty, set a timer to try allocating\r
-        * again at a later time. */\r
-       if (fifo_empty(&ap->rx_ring) && netif_running(dev)) {\r
-               dev_warn(&ap->pdev->dev, "unable to refill rx ring\n");\r
-               ap->rx_timeout.expires = jiffies + HZ;\r
-               add_timer(&ap->rx_timeout);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-/*\r
- * timer callback to defer refill rx queue in case we're OOM\r
- */\r
-static void vmac_refill_rx_timer(unsigned long data)\r
-{\r
-       struct net_device *dev;\r
-       struct vmac_priv *ap;\r
-\r
-       dev = (struct net_device *)data;\r
-       ap = netdev_priv(dev);\r
-\r
-       spin_lock(&ap->rx_lock);\r
-       vmac_rx_refill(dev);\r
-       spin_unlock(&ap->rx_lock);\r
-}\r
-\r
-/* merge buffer chaining  */\r
-struct sk_buff *vmac_merge_rx_buffers(struct net_device *dev,\r
-               struct vmac_buffer_desc *after,\r
-               int pkt_len) /* data */\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct sk_buff *merge_skb, *cur_skb;\r
-       struct dma_fifo *rx_ring;\r
-       struct vmac_buffer_desc *desc;\r
-\r
-       rx_ring = &ap->rx_ring;\r
-       desc = &ap->rxbd[rx_ring->tail];\r
-\r
-       WARN_ON(desc == after);\r
-\r
-       /* strip FCS */\r
-       pkt_len -= 4;\r
-\r
-       /* IP header Alignment (14 byte Ethernet header) */\r
-       merge_skb = netdev_alloc_skb(dev, pkt_len + 2);\r
-       if (!merge_skb) {\r
-               dev_err(&ap->pdev->dev, "failed to allocate merged rx_skb, rx skb's left %d\n",\r
-                               fifo_used(rx_ring));\r
-\r
-               return NULL;\r
-       }\r
-\r
-       skb_reserve(merge_skb, 2);\r
-\r
-       while (desc != after && pkt_len) {\r
-               struct vmac_buffer_desc *desc;\r
-               int buf_len, valid;\r
-\r
-               /* desc needs wrapping */\r
-               desc = &ap->rxbd[rx_ring->tail];\r
-               cur_skb = ap->rx_skbuff[rx_ring->tail];\r
-               WARN_ON(!cur_skb);\r
-\r
-               dma_unmap_single(&ap->pdev->dev, desc->data, ap->rx_skb_size,\r
-                               DMA_FROM_DEVICE);\r
-\r
-               /* do not copy FCS */\r
-               buf_len = desc->info & LEN_MASK;\r
-               valid = min(pkt_len, buf_len);\r
-               pkt_len -= valid;\r
-\r
-               memcpy(skb_put(merge_skb, valid), cur_skb->data, valid);\r
-\r
-               fifo_inc_tail(rx_ring);\r
-       }\r
-\r
-       /* merging_pressure++ */\r
-\r
-       if (unlikely(pkt_len != 0))\r
-               dev_err(&ap->pdev->dev, "buffer chaining bytes missing %d\n",\r
-                               pkt_len);\r
-\r
-       WARN_ON(desc != after);\r
-\r
-       return merge_skb;\r
-}\r
-\r
-int vmac_rx_receive(struct net_device *dev, int budget)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct vmac_buffer_desc *first;\r
-       int processed, pkt_len, pkt_err;\r
-       struct dma_fifo lookahead;\r
-\r
-       processed = 0;\r
-\r
-       first = NULL;\r
-       pkt_err = pkt_len = 0;\r
-\r
-       /* look ahead, till packet complete */\r
-       lookahead = ap->rx_ring;\r
-\r
-       do {\r
-               struct vmac_buffer_desc *desc; /* cur_ */\r
-               int desc_idx; /* cur_ */\r
-               struct sk_buff *skb; /* pkt_ */\r
-\r
-               desc_idx = lookahead.tail;\r
-               desc = &ap->rxbd[desc_idx];\r
-\r
-               /* make sure we read the actual descriptor status */\r
-               rmb();\r
-\r
-               /* break if dma ownership belongs to hw */\r
-               if (desc->info & OWN_MASK) {\r
-                       ap->mac_rxring_head = vmac_readl(ap, MAC_RXRING_HEAD);\r
-                       break;\r
-               }\r
-\r
-               if (desc->info & FRST_MASK) {\r
-                       pkt_len = 0;\r
-                       pkt_err = 0;\r
-\r
-                       /* don't free current */\r
-                       ap->rx_ring.tail = lookahead.tail;\r
-                       first = desc;\r
-               }\r
-\r
-               fifo_inc_tail(&lookahead);\r
-\r
-               /* check bd */\r
-\r
-               pkt_len += desc->info & LEN_MASK;\r
-               pkt_err |= (desc->info & BUFF);\r
-\r
-               if (!(desc->info & LAST_MASK))\r
-                       continue;\r
-\r
-               /* received complete packet */\r
-\r
-               if (unlikely(pkt_err || !first)) {\r
-                       /* recycle buffers */\r
-                       ap->rx_ring.tail = lookahead.tail;\r
-                       continue;\r
-               }\r
-\r
-               WARN_ON(!(first->info & FRST_MASK) ||\r
-                               !(desc->info & LAST_MASK));\r
-               WARN_ON(pkt_err);\r
-\r
-               /* -- valid packet -- */\r
-\r
-               if (first != desc) {\r
-                       skb = vmac_merge_rx_buffers(dev, desc, pkt_len);\r
-\r
-                       if (!skb) {\r
-                               /* kill packet */\r
-                               ap->rx_ring.tail = lookahead.tail;\r
-                               ap->rx_merge_error++;\r
-                               continue;\r
-                       }\r
-               } else {\r
-                       dma_unmap_single(&ap->pdev->dev, desc->data,\r
-                                       ap->rx_skb_size, DMA_FROM_DEVICE);\r
-\r
-                       skb = ap->rx_skbuff[desc_idx];\r
-                       ap->rx_skbuff[desc_idx] = NULL;\r
-                       /* desc->data != skb->data => desc->data DMA mapped */\r
-\r
-                       /* strip FCS */\r
-                       skb_put(skb, pkt_len - 4);\r
-               }\r
-\r
-               /* free buffers */\r
-               ap->rx_ring.tail = lookahead.tail;\r
-\r
-               WARN_ON(skb->len != pkt_len - 4);\r
-               processed++;\r
-               skb->dev = dev;\r
-               skb->protocol = eth_type_trans(skb, dev);\r
-               ap->stats.rx_packets++;\r
-               ap->stats.rx_bytes += skb->len;\r
-               dev->last_rx = jiffies;\r
-               netif_rx(skb);\r
-\r
-       } while (!fifo_empty(&lookahead) && (processed < budget));\r
-\r
-       dev_vdbg(&ap->pdev->dev, "processed pkt %d, remaining rx buff %d\n",\r
-                       processed,\r
-                       fifo_used(&ap->rx_ring));\r
-\r
-       if (processed || fifo_empty(&ap->rx_ring))\r
-               vmac_rx_refill(dev);\r
-\r
-       return processed;\r
-}\r
-\r
-static void vmac_toggle_irqmask(struct net_device *dev, int enable, int mask)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned long tmp;\r
-\r
-       tmp = vmac_readl(ap, ENABLE);\r
-       if (enable)\r
-               tmp |= mask;\r
-       else\r
-               tmp &= ~mask;\r
-       vmac_writel(ap, tmp, ENABLE);\r
-}\r
-\r
-static void vmac_toggle_txint(struct net_device *dev, int enable)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-       vmac_toggle_irqmask(dev, enable, TXINT_MASK);\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-}\r
-\r
-static void vmac_toggle_rxint(struct net_device *dev, int enable)\r
-{\r
-       vmac_toggle_irqmask(dev, enable, RXINT_MASK);\r
-}\r
-\r
-static int vmac_poll(struct napi_struct *napi, int budget)\r
-{\r
-       struct vmac_priv *ap;\r
-       struct net_device *dev;\r
-       int rx_work_done;\r
-       unsigned long flags;\r
-\r
-       ap = container_of(napi, struct vmac_priv, napi);\r
-       dev = ap->dev;\r
-\r
-       /* ack interrupt */\r
-       vmac_writel(ap, RXINT_MASK, STAT);\r
-\r
-       spin_lock(&ap->rx_lock);\r
-       rx_work_done = vmac_rx_receive(dev, budget);\r
-       spin_unlock(&ap->rx_lock);\r
-\r
-#ifdef VERBOSE_DEBUG\r
-       if (printk_ratelimit()) {\r
-               dev_vdbg(&ap->pdev->dev, "poll budget %d receive rx_work_done %d\n",\r
-                               budget,\r
-                               rx_work_done);\r
-       }\r
-#endif\r
-\r
-       if (rx_work_done >= budget) {\r
-               /* rx queue is not yet empty/clean */\r
-               return rx_work_done;\r
-       }\r
-\r
-       /* no more packet in rx/tx queue, remove device from poll\r
-        * queue */\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-       napi_complete(napi);\r
-       vmac_toggle_rxint(dev, 1);\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-\r
-       return rx_work_done;\r
-}\r
-\r
-static int vmac_tx_reclaim(struct net_device *dev, int force);\r
-\r
-static irqreturn_t vmac_intr(int irq, void *dev_instance)\r
-{\r
-       struct net_device *dev = dev_instance;\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned int status;\r
-\r
-       spin_lock(&ap->lock);\r
-\r
-       status = vmac_readl(ap, STAT);\r
-       vmac_writel(ap, status, STAT);\r
-\r
-#ifdef DEBUG\r
-       if (unlikely(ap->shutdown))\r
-               dev_err(&ap->pdev->dev, "ISR during close\n");\r
-\r
-       if (unlikely(!status & (RXINT_MASK|MDIO_MASK|ERR_MASK)))\r
-               dev_err(&ap->pdev->dev, "No source of IRQ found\n");\r
-#endif\r
-\r
-       if ((status & RXINT_MASK) &&\r
-                       (ap->mac_rxring_head !=\r
-                        vmac_readl(ap, MAC_RXRING_HEAD))) {\r
-               vmac_toggle_rxint(dev, 0);\r
-               napi_schedule(&ap->napi);\r
-       }\r
-\r
-       if (unlikely(netif_queue_stopped(dev) && (status & TXINT_MASK)))\r
-               vmac_tx_reclaim(dev, 0);\r
-\r
-       if (status & MDIO_MASK)\r
-               complete(&ap->mdio_complete);\r
-\r
-       if (unlikely(status & ERR_MASK))\r
-               update_error_counters(dev, status);\r
-\r
-       spin_unlock(&ap->lock);\r
-\r
-       return IRQ_HANDLED;\r
-}\r
-\r
-static int vmac_tx_reclaim(struct net_device *dev, int force)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       int released = 0;\r
-\r
-       /* buffer chaining not used, see vmac_start_xmit */\r
-\r
-       while (!fifo_empty(&ap->tx_ring)) {\r
-               struct vmac_buffer_desc *desc;\r
-               struct sk_buff *skb;\r
-               int desc_idx;\r
-\r
-               desc_idx = ap->tx_ring.tail;\r
-               desc = &ap->txbd[desc_idx];\r
-\r
-               /* ensure other field of the descriptor were not read\r
-                * before we checked ownership */\r
-               rmb();\r
-\r
-               if ((desc->info & OWN_MASK) && !force)\r
-                       break;\r
-\r
-               if (desc->info & ERR_MSK_TX) {\r
-                       update_tx_errors(dev, desc->info);\r
-                       /* recycle packet, let upper level deal with it */\r
-               }\r
-\r
-               skb = ap->tx_skbuff[desc_idx];\r
-               ap->tx_skbuff[desc_idx] = NULL;\r
-               WARN_ON(!skb);\r
-\r
-               dma_unmap_single(&ap->pdev->dev, desc->data, skb->len,\r
-                               DMA_TO_DEVICE);\r
-\r
-               dev_kfree_skb_any(skb);\r
-\r
-               released++;\r
-               fifo_inc_tail(&ap->tx_ring);\r
-       }\r
-\r
-       if (netif_queue_stopped(dev) && released) {\r
-               netif_wake_queue(dev);\r
-               vmac_toggle_txint(dev, 0);\r
-       }\r
-\r
-       if (unlikely(force && !fifo_empty(&ap->tx_ring))) {\r
-               dev_err(&ap->pdev->dev, "failed to reclaim %d tx sk_buff\n",\r
-                               fifo_used(&ap->tx_ring));\r
-       }\r
-\r
-       return released;\r
-}\r
-\r
-int vmac_start_xmit(struct sk_buff *skb, struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct vmac_buffer_desc *desc;\r
-       unsigned int tmp;\r
-\r
-       /* running under xmit lock */\r
-\r
-       /* no scatter/gatter see features below */\r
-       WARN_ON(skb_shinfo(skb)->nr_frags != 0);\r
-       WARN_ON(skb->len > MAX_TX_BUFFER_LEN);\r
-\r
-       if (unlikely(fifo_full(&ap->tx_ring))) {\r
-               netif_stop_queue(dev);\r
-               vmac_toggle_txint(dev, 1);\r
-               dev_err(&ap->pdev->dev, "xmit called with no tx desc available\n");\r
-               return NETDEV_TX_BUSY;\r
-       }\r
-\r
-       if (unlikely(skb->len < ETH_ZLEN)) {\r
-               struct sk_buff *short_skb;\r
-               short_skb = netdev_alloc_skb(dev, ETH_ZLEN);\r
-               if (!short_skb)\r
-                       return NETDEV_TX_LOCKED;\r
-\r
-               memset(short_skb->data, 0, ETH_ZLEN);\r
-               memcpy(skb_put(short_skb, ETH_ZLEN), skb->data, skb->len);\r
-               dev_kfree_skb(skb);\r
-               skb = short_skb;\r
-       }\r
-\r
-       /* fill descriptor */\r
-       ap->tx_skbuff[ap->tx_ring.head] = skb;\r
-\r
-       desc = &ap->txbd[ap->tx_ring.head];\r
-       desc->data = dma_map_single(&ap->pdev->dev, skb->data, skb->len,\r
-                       DMA_TO_DEVICE);\r
-\r
-       /* dma might already be polling */\r
-       wmb();\r
-       desc->info = OWN_MASK | FRST_MASK | LAST_MASK | skb->len;\r
-       wmb();\r
-\r
-       /* kick tx dma */\r
-       tmp = vmac_readl(ap, STAT);\r
-       vmac_writel(ap, tmp | TXPL_MASK, STAT);\r
-\r
-       ap->stats.tx_packets++;\r
-       ap->stats.tx_bytes += skb->len;\r
-       dev->trans_start = jiffies;\r
-       fifo_inc_head(&ap->tx_ring);\r
-\r
-       /* vmac_tx_reclaim independent of vmac_tx_timeout */\r
-       if (fifo_used(&ap->tx_ring) > 8)\r
-               vmac_tx_reclaim(dev, 0);\r
-\r
-       /* stop queue if no more desc available */\r
-       if (fifo_full(&ap->tx_ring)) {\r
-               netif_stop_queue(dev);\r
-               vmac_toggle_txint(dev, 1);\r
-       }\r
-\r
-       return NETDEV_TX_OK;\r
-}\r
-\r
-static int alloc_buffers(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       int err = -ENOMEM;\r
-       int size;\r
-\r
-       fifo_init(&ap->rx_ring, RX_BDT_LEN);\r
-       fifo_init(&ap->tx_ring, TX_BDT_LEN);\r
-\r
-       /* initialize skb list */\r
-       memset(ap->rx_skbuff, 0, sizeof(ap->rx_skbuff));\r
-       memset(ap->tx_skbuff, 0, sizeof(ap->tx_skbuff));\r
-\r
-       /* allocate DMA received descriptors */\r
-       size = sizeof(*ap->rxbd) * ap->rx_ring.size;\r
-       ap->rxbd = dma_alloc_coherent(&ap->pdev->dev, size,\r
-                       &ap->rxbd_dma,\r
-                       GFP_KERNEL);\r
-       if (ap->rxbd == NULL)\r
-               goto err_out;\r
-\r
-       /* allocate DMA transmit descriptors */\r
-       size = sizeof(*ap->txbd) * ap->tx_ring.size;\r
-       ap->txbd = dma_alloc_coherent(&ap->pdev->dev, size,\r
-                       &ap->txbd_dma,\r
-                       GFP_KERNEL);\r
-       if (ap->txbd == NULL)\r
-               goto err_free_rxbd;\r
-\r
-       /* ensure 8-byte aligned */\r
-       WARN_ON(((int)ap->txbd & 0x7) || ((int)ap->rxbd & 0x7));\r
-\r
-       memset(ap->txbd, 0, sizeof(*ap->txbd) * ap->tx_ring.size);\r
-       memset(ap->rxbd, 0, sizeof(*ap->rxbd) * ap->rx_ring.size);\r
-\r
-       /* allocate rx skb */\r
-       err = vmac_rx_refill(dev);\r
-       if (err)\r
-               goto err_free_txbd;\r
-\r
-       return 0;\r
-\r
-err_free_txbd:\r
-       dma_free_coherent(&ap->pdev->dev, sizeof(*ap->txbd) * ap->tx_ring.size,\r
-                       ap->txbd, ap->txbd_dma);\r
-err_free_rxbd:\r
-       dma_free_coherent(&ap->pdev->dev, sizeof(*ap->rxbd) * ap->rx_ring.size,\r
-                       ap->rxbd, ap->rxbd_dma);\r
-err_out:\r
-       return err;\r
-}\r
-\r
-static int free_buffers(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-\r
-       /* free skbuff */\r
-       vmac_tx_reclaim(dev, 1);\r
-       vmac_rx_reclaim_force(dev);\r
-\r
-       /* free DMA ring */\r
-       dma_free_coherent(&ap->pdev->dev, sizeof(ap->txbd) * ap->tx_ring.size,\r
-                       ap->txbd, ap->txbd_dma);\r
-       dma_free_coherent(&ap->pdev->dev, sizeof(ap->rxbd) * ap->rx_ring.size,\r
-                       ap->rxbd, ap->rxbd_dma);\r
-\r
-       return 0;\r
-}\r
-\r
-static int vmac_hw_init(struct net_device *dev)\r
-{\r
-       struct vmac_priv *priv = netdev_priv(dev);\r
-\r
-       /* clear IRQ mask */\r
-       vmac_writel(priv, 0, ENABLE);\r
-\r
-       /* clear pending IRQ */\r
-       vmac_writel(priv, 0xffffffff, STAT);\r
-\r
-       /* Initialize logical address filter */\r
-       vmac_writel(priv, 0x0, LAFL);\r
-       vmac_writel(priv, 0x0, LAFH);\r
-\r
-       return 0;\r
-}\r
-\r
-#ifdef DEBUG\r
-static int vmac_register_print(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-\r
-       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ID", vmac_readl(ap, ID));\r
-       printk("func::%s vmac register %s value = 0x%x\n", __func__, "STAT", vmac_readl(ap, STAT));\r
-       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ENABLE", vmac_readl(ap, ENABLE));\r
-       printk("func::%s vmac register %s value = 0x%x\n", __func__, "CONTROL", vmac_readl(ap, CONTROL));\r
-       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ADDRL", vmac_readl(ap, ADDRL));\r
-       printk("func::%s vmac register %s value = 0x%x\n", __func__, "ADDRH", vmac_readl(ap, ADDRH));\r
-       \r
-       return 0;\r
-}\r
-#endif\r
-\r
-int vmac_open(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct phy_device *phydev;\r
-       unsigned int temp;\r
-       int err = 0;\r
-       struct clk *mac_clk = NULL;\r
-       struct clk *mac_parent = NULL;\r
-       struct clk *arm_clk = NULL;\r
-       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
-       unsigned char current_mac[6];\r
-       int ret = 0;\r
-\r
-       printk("enter func %s...\n", __func__);\r
-\r
-       if (ap == NULL)\r
-               return -ENODEV;\r
-\r
-       wake_lock_timeout(&ap->resume_lock, 5*HZ);\r
-\r
-       ap->shutdown = 0;\r
-               \r
-       //set rmii ref clock 50MHz\r
-       mac_clk = clk_get(NULL, "mac_ref");\r
-       if (IS_ERR(mac_clk))\r
-               mac_clk = NULL;\r
-       arm_clk = clk_get(NULL, "arm_pll");\r
-       if (IS_ERR(arm_clk))\r
-               arm_clk = NULL;\r
-       if (mac_clk) {\r
-               mac_parent = clk_get_parent(mac_clk);\r
-               if (IS_ERR(mac_parent))\r
-                       mac_parent = NULL;\r
-       }\r
-       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
-               wake_lock(&idlelock);\r
-\r
-        if(pdata && pdata->rmii_extclk_sel && pdata->rmii_extclk_sel())\r
-        {\r
-            struct clk * mac_clkin = NULL;\r
-            mac_clkin = clk_get(NULL, "rmii_clkin");\r
-            if (IS_ERR(mac_clkin)) {\r
-                pr_err("mac_clkin get fail\n");\r
-            }\r
-            clk_set_parent(mac_clk, mac_clkin); \r
-        }\r
-        \r
-       clk_set_rate(mac_clk, 50000000);\r
-       clk_enable(mac_clk);\r
-       clk_enable(clk_get(NULL,"mii_rx"));\r
-       clk_enable(clk_get(NULL,"mii_tx"));\r
-       clk_enable(clk_get(NULL,"hclk_mac"));\r
-       clk_enable(clk_get(NULL,"mac_ref"));\r
-\r
-       //phy power on\r
-       if (pdata && pdata->rmii_power_control)\r
-               pdata->rmii_power_control(1);\r
-\r
-       msleep(1000);\r
-\r
-       vmac_hw_init(dev);\r
-\r
-//$_rbox_$_modify_$_chenxiao\r
-       if (is_valid_ether_addr(dev->dev_addr)){\r
-               strlcpy(current_mac,dev->dev_addr,6);\r
-       }\r
-\r
-#ifdef CONFIG_ETH_MAC_FROM_EEPROM\r
-       ret = eeprom_read_data(0,dev->dev_addr,6);\r
-       if (ret != 6){\r
-               printk("read mac from Eeprom fail.\n");\r
-       }else {\r
-               if (is_valid_ether_addr(dev->dev_addr)){\r
-                       printk("eth_mac_from_eeprom***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
-                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
-                                               dev->dev_addr[4],dev->dev_addr[5] );\r
-               }\r
-       }\r
-#endif\r
-\r
-#ifdef CONFIG_ETH_MAC_FROM_IDB\r
-       err = eth_mac_idb(dev->dev_addr);\r
-       if (err) {\r
-               printk("read mac from IDB fail.\n");\r
-       } else {\r
-               if (is_valid_ether_addr(dev->dev_addr)) {\r
-                       printk("eth_mac_from_idb***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
-                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
-                                               dev->dev_addr[4],dev->dev_addr[5] );\r
-               }\r
-       }\r
-#endif\r
-\r
-#ifdef CONFIG_ETH_MAC_FROM_WIFI_MAC\r
-       err = eth_mac_wifi(dev->dev_addr);\r
-       if (err) {\r
-               printk("read mac from Wifi  fail.\n");\r
-       } else {\r
-               if (is_valid_ether_addr(dev->dev_addr)) {\r
-                       printk("eth_mac_from_wifi_mac***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
-                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
-                                               dev->dev_addr[4],dev->dev_addr[5] );\r
-               }\r
-       }\r
-#endif\r
-\r
-#ifdef CONFIG_ETH_MAC_FROM_SECURE_CHIP\r
-\r
-#endif\r
-         \r
-\r
-       if (!is_valid_ether_addr(dev->dev_addr)) {\r
-               strlcpy(dev->dev_addr,current_mac,6);\r
-               printk("eth_mac_from_RANDOM***********:%X:%X:%X:%X:%X:%X\n",dev->dev_addr[0],\r
-                                               dev->dev_addr[1],dev->dev_addr[2],dev->dev_addr[3],\r
-                                               dev->dev_addr[4],dev->dev_addr[5] );\r
-       }\r
-//add end      \r
-\r
-       /* mac address changed? */\r
-       write_mac_reg(dev, dev->dev_addr);\r
-\r
-       err = alloc_buffers(dev);\r
-       if (err)\r
-               goto err_out;\r
-\r
-       err = request_irq(dev->irq, &vmac_intr, 0, dev->name, dev);\r
-       if (err) {\r
-               dev_err(&ap->pdev->dev, "Unable to request IRQ %d (error %d)\n",\r
-                               dev->irq, err);\r
-               goto err_free_buffers;\r
-       }\r
-\r
-       /* install DMA ring pointers */\r
-       vmac_writel(ap, ap->rxbd_dma, RXRINGPTR);\r
-       vmac_writel(ap, ap->txbd_dma, TXRINGPTR);\r
-\r
-       /* set poll rate to 1 ms */\r
-       vmac_writel(ap, POLLRATE_TIME, POLLRATE);\r
-\r
-       /* make sure we enable napi before rx interrupt  */\r
-       napi_enable(&ap->napi);\r
-\r
-       /* IRQ mask */\r
-       temp = RXINT_MASK | ERR_MASK | TXCH_MASK | MDIO_MASK;\r
-       vmac_writel(ap, temp, ENABLE);\r
-\r
-       /* Set control */\r
-       temp = (RX_BDT_LEN << 24) | (TX_BDT_LEN << 16) | TXRN_MASK | RXRN_MASK;\r
-       vmac_writel(ap, temp, CONTROL);\r
-\r
-       /* enable, after all other bits are set */\r
-       vmac_writel(ap, temp | EN_MASK, CONTROL);\r
-       \r
-       netif_start_queue(dev);\r
-       netif_carrier_off(dev);\r
-\r
-#ifdef DEBUG\r
-       vmac_register_print(dev);\r
-#endif\r
-\r
-       /* register the PHY board fixup, if needed */\r
-       err = vmac_mii_init(ap);\r
-       if (err)\r
-               goto err_free_irq;\r
-\r
-       /* schedule a link state check */\r
-       phy_start(ap->phy_dev);\r
-\r
-       phydev = ap->phy_dev;\r
-       dev_info(&ap->pdev->dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",\r
-              phydev->drv->name, dev_name(&phydev->dev), phydev->irq);\r
-\r
-       ap->suspending = 0;\r
-       ap->open_flag = 1;\r
-\r
-       return 0;\r
-\r
-err_free_irq:\r
-       free_irq(dev->irq, dev);\r
-err_free_buffers:\r
-       free_buffers(dev);\r
-err_out:       \r
-       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
-               wake_unlock(&idlelock);\r
-\r
-       return err;\r
-}\r
-\r
-int vmac_close(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned int temp;\r
-       struct clk *mac_clk = NULL;\r
-       struct clk *arm_clk = NULL;\r
-       struct clk *mac_parent = NULL;\r
-       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
-\r
-       printk("enter func %s...\n", __func__);\r
-       \r
-       if (ap->suspending == 1) \r
-               return 0;\r
-\r
-       ap->open_flag = 0;\r
-\r
-       netif_stop_queue(dev);\r
-       napi_disable(&ap->napi);\r
-\r
-       /* stop running transfers */\r
-       temp = vmac_readl(ap, CONTROL);\r
-       temp &= ~(TXRN_MASK | RXRN_MASK);\r
-       vmac_writel(ap, temp, CONTROL);\r
-\r
-       del_timer_sync(&ap->rx_timeout);\r
-\r
-       /* disable phy */\r
-       phy_stop(ap->phy_dev);\r
-       vmac_mii_exit(dev);\r
-       netif_carrier_off(dev);\r
-\r
-       /* disable interrupts */\r
-       vmac_writel(ap, 0, ENABLE);\r
-       free_irq(dev->irq, dev);\r
-\r
-       /* turn off vmac */\r
-       vmac_writel(ap, 0, CONTROL);\r
-       /* vmac_reset_hw(vmac) */\r
-\r
-       ap->shutdown = 1;\r
-       wmb();\r
-\r
-       free_buffers(dev);\r
-\r
-       //phy power off\r
-       if (pdata && pdata->rmii_power_control)\r
-               pdata->rmii_power_control(0);\r
-\r
-       //clock close\r
-       mac_clk = clk_get(NULL, "mac_ref_div");\r
-       if (IS_ERR(mac_clk))\r
-               mac_clk = NULL;\r
-       if (mac_clk) {\r
-               mac_parent = clk_get_parent(mac_clk);\r
-               if (IS_ERR(mac_parent))\r
-                       mac_parent = NULL;\r
-       }\r
-       arm_clk = clk_get(NULL, "arm_pll");\r
-       if (IS_ERR(arm_clk))\r
-               arm_clk = NULL;\r
-\r
-       if (arm_clk && mac_parent && (arm_clk == mac_parent))\r
-               wake_unlock(&idlelock);\r
-       \r
-       clk_disable(mac_clk);\r
-       clk_disable(clk_get(NULL,"mii_rx"));\r
-       clk_disable(clk_get(NULL,"mii_tx"));\r
-       clk_disable(clk_get(NULL,"hclk_mac"));\r
-       clk_disable(clk_get(NULL,"mac_ref"));\r
-\r
-       return 0;\r
-}\r
-\r
-int vmac_shutdown(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned int temp;\r
-       \r
-       printk("enter func %s...\n", __func__);\r
-\r
-       netif_stop_queue(dev);\r
-       napi_disable(&ap->napi);\r
-\r
-       /* stop running transfers */\r
-       temp = vmac_readl(ap, CONTROL);\r
-       temp &= ~(TXRN_MASK | RXRN_MASK);\r
-       vmac_writel(ap, temp, CONTROL);\r
-\r
-       del_timer_sync(&ap->rx_timeout);\r
-\r
-       /* disable phy */\r
-       phy_stop(ap->phy_dev);\r
-       vmac_mii_exit(dev);\r
-       netif_carrier_off(dev);\r
-\r
-       /* disable interrupts */\r
-       vmac_writel(ap, 0, ENABLE);\r
-       free_irq(dev->irq, dev);\r
-\r
-       /* turn off vmac */\r
-       vmac_writel(ap, 0, CONTROL);\r
-       /* vmac_reset_hw(vmac) */\r
-\r
-       ap->shutdown = 1;\r
-       wmb();\r
-\r
-       free_buffers(dev);\r
-\r
-       return 0;\r
-}\r
-\r
-void vmac_update_stats(struct vmac_priv *ap)\r
-{\r
-       struct net_device_stats *_stats = &ap->stats;\r
-       unsigned long miss, rxerr;\r
-       unsigned long rxfram, rxcrc, rxoflow;\r
-\r
-       /* compare with /proc/net/dev,\r
-        * see net/core/dev.c:dev_seq_printf_stats */\r
-\r
-       /* rx stats */\r
-       rxerr = vmac_readl(ap, RXERR);\r
-       miss = vmac_readl(ap, MISS);\r
-\r
-       rxcrc = (rxerr & RXERR_CRC);\r
-       rxfram = (rxerr & RXERR_FRM) >> 8;\r
-       rxoflow = (rxerr & RXERR_OFLO) >> 16;\r
-\r
-       _stats->rx_length_errors = 0;\r
-       _stats->rx_over_errors += miss;\r
-       _stats->rx_crc_errors += rxcrc;\r
-       _stats->rx_frame_errors += rxfram;\r
-       _stats->rx_fifo_errors += rxoflow;\r
-       _stats->rx_missed_errors = 0;\r
-\r
-       /* TODO check rx_dropped/rx_errors/tx_dropped/tx_errors have not\r
-        * been updated elsewhere */\r
-       _stats->rx_dropped = _stats->rx_over_errors +\r
-               _stats->rx_fifo_errors +\r
-               ap->rx_merge_error;\r
-\r
-       _stats->rx_errors = _stats->rx_length_errors + _stats->rx_crc_errors +\r
-               _stats->rx_frame_errors +\r
-               _stats->rx_missed_errors +\r
-               _stats->rx_dropped;\r
-\r
-       /* tx stats */\r
-       _stats->tx_dropped = 0; /* otherwise queue stopped */\r
-\r
-       _stats->tx_errors = _stats->tx_aborted_errors +\r
-               _stats->tx_carrier_errors +\r
-               _stats->tx_fifo_errors +\r
-               _stats->tx_heartbeat_errors +\r
-               _stats->tx_window_errors +\r
-               _stats->tx_dropped +\r
-               ap->tx_timeout_error;\r
-}\r
-\r
-struct net_device_stats *vmac_stats(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-       vmac_update_stats(ap);\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-\r
-       return &ap->stats;\r
-}\r
-\r
-void vmac_tx_timeout(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned int status;\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-\r
-       /* queue did not progress for timeo jiffies */\r
-       WARN_ON(!netif_queue_stopped(dev));\r
-       WARN_ON(!fifo_full(&ap->tx_ring));\r
-\r
-       /* TX IRQ lost? */\r
-       status = vmac_readl(ap, STAT);\r
-       if (status & TXINT_MASK) {\r
-               dev_err(&ap->pdev->dev, "lost tx interrupt, IRQ mask %x\n",\r
-                               vmac_readl(ap, ENABLE));\r
-               vmac_writel(ap, TXINT_MASK, STAT);\r
-       }\r
-\r
-       /* TODO RX/MDIO/ERR as well? */\r
-\r
-       vmac_tx_reclaim(dev, 0);\r
-       if (fifo_full(&ap->tx_ring))\r
-               dev_err(&ap->pdev->dev, "DMA state machine not active\n");\r
-\r
-       /* We can accept TX packets again */\r
-       ap->tx_timeout_error++;\r
-       dev->trans_start = jiffies;\r
-       netif_wake_queue(dev);\r
-\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-}\r
-\r
-static void create_multicast_filter(struct net_device *dev,\r
-       unsigned long *bitmask)\r
-{\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
-       struct netdev_hw_addr *ha;\r
-       unsigned long crc;\r
-       char *addrs;\r
-       struct netdev_hw_addr_list *list = &dev->dev_addrs;\r
-       \r
-       //printk("-----------------func %s-------------------\n", __func__);\r
-\r
-       WARN_ON(dev->mc_count == 0);\r
-       WARN_ON(dev->flags & IFF_ALLMULTI);\r
-\r
-       bitmask[0] = bitmask[1] = 0;\r
-\r
-       list_for_each_entry(ha, &list->list, list) {\r
-               addrs = ha->addr;\r
-\r
-               /* skip non-multicast addresses */\r
-               if (!(*addrs & 1))\r
-                       continue;\r
-\r
-               crc = ether_crc_le(ETH_ALEN, addrs);\r
-               set_bit(crc >> 26, bitmask);\r
-               \r
-       }\r
-#else\r
-       struct netdev_hw_addr *ha;\r
-       unsigned long crc;\r
-       char *addrs;\r
-\r
-       WARN_ON(netdev_mc_count(dev) == 0);\r
-       WARN_ON(dev->flags & IFF_ALLMULTI);\r
-\r
-       bitmask[0] = bitmask[1] = 0;\r
-\r
-       netdev_for_each_mc_addr(ha, dev) {\r
-               addrs = ha->addr;\r
-\r
-               /* skip non-multicast addresses */\r
-               if (!(*addrs & 1))\r
-                       continue;\r
-\r
-               crc = ether_crc_le(ETH_ALEN, addrs);\r
-               set_bit(crc >> 26, bitmask);\r
-       }\r
-#endif\r
-}\r
-static void vmac_set_multicast_list(struct net_device *dev)\r
-{\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned long flags, bitmask[2];\r
-       int promisc, reg;\r
-\r
-       //printk("-----------------func %s-------------------\n", __func__);\r
-\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-\r
-       promisc = !!(dev->flags & IFF_PROMISC);\r
-       reg = vmac_readl(ap, CONTROL);\r
-       if (promisc != !!(reg & PROM_MASK)) {\r
-               reg ^= PROM_MASK;\r
-               vmac_writel(ap, reg, CONTROL);\r
-       }\r
-\r
-       if (dev->flags & IFF_ALLMULTI)\r
-               memset(bitmask, 1, sizeof(bitmask));\r
-       else if (dev->mc_count == 0)\r
-               memset(bitmask, 0, sizeof(bitmask));\r
-       else\r
-               create_multicast_filter(dev, bitmask);\r
-\r
-       vmac_writel(ap, bitmask[0], LAFL);\r
-       vmac_writel(ap, bitmask[1], LAFH);\r
-\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-#else\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       unsigned long flags, bitmask[2];\r
-       int promisc, reg;\r
-\r
-       spin_lock_irqsave(&ap->lock, flags);\r
-\r
-       promisc = !!(dev->flags & IFF_PROMISC);\r
-       reg = vmac_readl(ap, CONTROL);\r
-       if (promisc != !!(reg & PROM_MASK)) {\r
-               reg ^= PROM_MASK;\r
-               vmac_writel(ap, reg, CONTROL);\r
-       }\r
-\r
-       if (dev->flags & IFF_ALLMULTI)\r
-               memset(bitmask, 1, sizeof(bitmask));\r
-       else if (netdev_mc_count(dev) == 0)\r
-               memset(bitmask, 0, sizeof(bitmask));\r
-       else\r
-               create_multicast_filter(dev, bitmask);\r
-\r
-       vmac_writel(ap, bitmask[0], LAFL);\r
-       vmac_writel(ap, bitmask[1], LAFH);\r
-\r
-       spin_unlock_irqrestore(&ap->lock, flags);\r
-#endif\r
-}\r
-\r
-static struct ethtool_ops vmac_ethtool_ops = {\r
-       .get_settings           = vmacether_get_settings,\r
-       .set_settings           = vmacether_set_settings,\r
-       .get_drvinfo            = vmacether_get_drvinfo,\r
-       .get_link               = ethtool_op_get_link,\r
-};\r
-\r
-static const struct net_device_ops vmac_netdev_ops = {\r
-       .ndo_open               = vmac_open,\r
-       .ndo_stop               = vmac_close,\r
-       .ndo_get_stats          = vmac_stats,\r
-       .ndo_start_xmit         = vmac_start_xmit,\r
-       .ndo_do_ioctl           = vmac_ioctl,\r
-       .ndo_set_mac_address    = eth_mac_addr,\r
-       .ndo_tx_timeout         = vmac_tx_timeout,\r
-       .ndo_set_multicast_list = vmac_set_multicast_list,\r
-       .ndo_validate_addr      = eth_validate_addr,\r
-       .ndo_change_mtu         = eth_change_mtu,\r
-};\r
-\r
-static int __devinit vmac_probe(struct platform_device *pdev)\r
-{\r
-       struct net_device *dev;\r
-       struct vmac_priv *ap;\r
-       struct resource *res;\r
-       unsigned int mem_base, mem_size, irq;\r
-       int err;\r
-       struct rk29_vmac_platform_data *pdata = pdev->dev.platform_data;\r
-\r
-       dev = alloc_etherdev(sizeof(*ap));\r
-       if (!dev) {\r
-               dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n");\r
-               return -ENOMEM;\r
-       }\r
-\r
-       ap = netdev_priv(dev);\r
-\r
-       err = -ENODEV;\r
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-       if (!res) {\r
-               dev_err(&pdev->dev, "no mmio resource defined\n");\r
-               goto err_out;\r
-       }\r
-       mem_base = res->start;\r
-       mem_size = resource_size(res);\r
-       irq = platform_get_irq(pdev, 0);\r
-\r
-       err = -EBUSY;\r
-       if (!request_mem_region(mem_base, mem_size, VMAC_NAME)) {\r
-               dev_err(&pdev->dev, "no memory region available\n");\r
-               goto err_out;\r
-       }\r
-\r
-       err = -ENOMEM;\r
-       ap->regs = ioremap(mem_base, mem_size);\r
-       if (!ap->regs) {\r
-               dev_err(&pdev->dev, "failed to map registers, aborting.\n");\r
-               goto err_out_release_mem;\r
-       }\r
-\r
-       /* no checksum support, hence no scatter/gather */\r
-       dev->features |= NETIF_F_HIGHDMA;\r
-\r
-       spin_lock_init(&ap->lock);\r
-\r
-       SET_NETDEV_DEV(dev, &pdev->dev);\r
-       ap->dev = dev;\r
-       ap->pdev = pdev;\r
-\r
-       /* init rx timeout (used for oom) */\r
-       init_timer(&ap->rx_timeout);\r
-       ap->rx_timeout.function = vmac_refill_rx_timer;\r
-       ap->rx_timeout.data = (unsigned long)dev;\r
-\r
-       netif_napi_add(dev, &ap->napi, vmac_poll, 2);\r
-       dev->netdev_ops = &vmac_netdev_ops;\r
-       dev->ethtool_ops = &vmac_ethtool_ops;\r
-       dev->irq = irq;\r
-\r
-       dev->flags |= IFF_MULTICAST;////////////////////\r
-\r
-       dev->base_addr = (unsigned long)ap->regs;\r
-       ap->mem_base = mem_base;\r
-\r
-       /* prevent buffer chaining, favor speed over space */\r
-       ap->rx_skb_size = ETH_FRAME_LEN + VMAC_BUFFER_PAD;\r
-\r
-       /* private struct functional */\r
-\r
-       /* mac address intialize, set vmac_open  */\r
-       read_mac_reg(dev, dev->dev_addr);\r
-\r
-       if (!is_valid_ether_addr(dev->dev_addr))\r
-               random_ether_addr(dev->dev_addr);\r
-\r
-       err = register_netdev(dev);\r
-       if (err) {\r
-               dev_err(&pdev->dev, "Cannot register net device, aborting.\n");\r
-               goto err_out_iounmap;\r
-       }\r
-\r
-       dev_info(&pdev->dev, "ARC VMAC at 0x%08x irq %d %pM\n", mem_base,\r
-           dev->irq, dev->dev_addr);\r
-       platform_set_drvdata(pdev, dev);\r
-\r
-       ap->suspending = 0;\r
-       ap->open_flag = 0;\r
-       wake_lock_init(&idlelock, WAKE_LOCK_IDLE, "vmac");\r
-       wake_lock_init(&ap->resume_lock, WAKE_LOCK_SUSPEND, "vmac_resume");\r
-\r
-       //config rk29 vmac as rmii, 100MHz \r
-       if (pdata && pdata->vmac_register_set)\r
-               pdata->vmac_register_set();\r
-\r
-       //power gpio init, phy power off default for power reduce\r
-       if (pdata && pdata->rmii_io_init)\r
-               pdata->rmii_io_init();\r
-\r
-       return 0;\r
-\r
-err_out_iounmap:\r
-       iounmap(ap->regs);\r
-err_out_release_mem:\r
-       release_mem_region(mem_base, mem_size);\r
-err_out:\r
-       free_netdev(dev);\r
-       return err;\r
-}\r
-\r
-static int __devexit vmac_remove(struct platform_device *pdev)\r
-{\r
-       struct net_device *dev;\r
-       struct vmac_priv *ap;\r
-       struct resource *res;\r
-       struct rk29_vmac_platform_data *pdata = pdev->dev.platform_data;\r
-\r
-       wake_lock_destroy(&idlelock);\r
-\r
-       //power gpio deinit, phy power off\r
-       if (pdata && pdata->rmii_io_deinit)\r
-               pdata->rmii_io_deinit();\r
-\r
-       dev = platform_get_drvdata(pdev);\r
-       if (!dev) {\r
-               dev_err(&pdev->dev, "%s no valid dev found\n", __func__);\r
-               return 0;\r
-       }\r
-\r
-       ap = netdev_priv(dev);\r
-\r
-       /* MAC */\r
-       unregister_netdev(dev);\r
-       iounmap(ap->regs);\r
-\r
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-       release_mem_region(res->start, resource_size(res));\r
-\r
-       platform_set_drvdata(pdev, NULL);\r
-       free_netdev(dev);\r
-       return 0;\r
-}\r
-\r
-static void rk29_vmac_power_off(struct net_device *dev)\r
-{\r
-       struct vmac_priv *ap = netdev_priv(dev);\r
-       struct rk29_vmac_platform_data *pdata = ap->pdev->dev.platform_data;\r
-\r
-       printk("enter func %s...\n", __func__);\r
-\r
-       //phy power off\r
-       if (pdata && pdata->rmii_power_control)\r
-               pdata->rmii_power_control(0);\r
-\r
-       //clock close\r
-       clk_disable(clk_get(NULL, "mac_ref_div"));\r
-       clk_disable(clk_get(NULL,"mii_rx"));\r
-       clk_disable(clk_get(NULL,"mii_tx"));\r
-       clk_disable(clk_get(NULL,"hclk_mac"));\r
-       clk_disable(clk_get(NULL,"mac_ref"));\r
-\r
-}\r
-\r
-static int\r
-rk29_vmac_suspend(struct device *dev)\r
-{\r
-       struct platform_device *pdev = to_platform_device(dev);\r
-       struct net_device *ndev = platform_get_drvdata(pdev);\r
-       struct vmac_priv *ap = netdev_priv(ndev);\r
-       \r
-       if (ndev) {\r
-               if (ap->open_flag == 1) {\r
-                       netif_stop_queue(ndev);\r
-                       netif_device_detach(ndev);\r
-                       if (ap->suspending == 0) {\r
-//$_rbox_$_modify_$_chenzhi: for ethernet sleep\r
-#if 0\r
-                               vmac_shutdown(ndev);\r
-                               rk29_vmac_power_off(ndev);\r
-#endif\r
-                               ap->suspending = 1;\r
-                       }\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-static int\r
-rk29_vmac_resume(struct device *dev)\r
-{\r
-       struct platform_device *pdev = to_platform_device(dev);\r
-       struct net_device *ndev = platform_get_drvdata(pdev);\r
-       struct vmac_priv *ap = netdev_priv(ndev);\r
-       \r
-       if (ndev) {\r
-               if (ap->open_flag == 1) {\r
-                       netif_device_attach(ndev);\r
-                       netif_start_queue(ndev);\r
-//$_rbox_$_modify_$_chenzhi: \r
-//$_rbox_$_modify_$_begin\r
-                       if (ap->suspending == 1) {\r
-                               ap->suspending = 0;\r
-                       }\r
-//$_rbox_$_modify_$_end\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-static struct dev_pm_ops rk29_vmac_pm_ops = {\r
-       .suspend        = rk29_vmac_suspend,\r
-       .resume         = rk29_vmac_resume,\r
-};\r
-\r
-\r
-static struct platform_driver rk29_vmac_driver = {\r
-       .probe          = vmac_probe,\r
-       .remove         = __devexit_p(vmac_remove),\r
-       .driver         = {\r
-               .name           = "rk29 vmac",\r
-               .owner   = THIS_MODULE,\r
-               .pm  = &rk29_vmac_pm_ops,\r
-       },\r
-};\r
-\r
-static int __init vmac_init(void)\r
-{\r
-       return platform_driver_register(&rk29_vmac_driver);\r
-}\r
-\r
-static void __exit vmac_exit(void)\r
-{\r
-       platform_driver_unregister(&rk29_vmac_driver);\r
-}\r
-\r
-module_init(vmac_init);\r
-module_exit(vmac_exit);\r
-\r
-MODULE_LICENSE("GPL");\r
-MODULE_DESCRIPTION("RK29 VMAC Ethernet driver");\r
-MODULE_AUTHOR("amit.bhor@celunite.com, sameer.dhavale@celunite.com, andreas.fenkart@streamunlimited.com");\r
diff --git a/drivers/net/rk29_vmac.h b/drivers/net/rk29_vmac.h
deleted file mode 100755 (executable)
index 25692a0..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/*\r
- * linux/arch/arc/drivers/arcvmac.h\r
- *\r
- * Copyright (C) 2003-2006 Codito Technologies, for linux-2.4 port\r
- * Copyright (C) 2006-2007 Celunite Inc, for linux-2.6 port\r
- * Copyright (C) 2007-2008 Sagem Communications, Fehmi HAFSI\r
- * Copyright (C) 2009 Sagem Communications, Andreas Fenkart\r
- * All Rights Reserved.\r
- *\r
- This program is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published by\r
- the Free Software Foundation; either version 2 of the License, or\r
- (at your option) any later version.\r
-\r
- This program is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with this program; if not, write to the Free Software\r
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
- * Authors: amit.bhor@celunite.com, sameer.dhavale@celunite.com\r
- */\r
-\r
-#ifndef _ARCVMAC_H\r
-#define _ARCVMAC_H\r
-\r
-#define VMAC_NAME              "rk29 vmac"\r
-#define VMAC_VERSION           "1.0"\r
-\r
-/* Buffer descriptors */\r
-#ifdef CONFIG_ARCH_RK29\r
-#define TX_BDT_LEN             16    /* Number of receive BD's */\r
-#else\r
-#define TX_BDT_LEN             255   /* Number of receive BD's */\r
-#endif\r
-#define RX_BDT_LEN             255   /* Number of transmit BD's */\r
-\r
-/* BD poll rate, in 1024 cycles. @100Mhz: x * 1024 cy * 10ns = 1ms */\r
-#define POLLRATE_TIME          200\r
-\r
-/* next power of two, bigger than ETH_FRAME_LEN + VLAN  */\r
-#define MAX_RX_BUFFER_LEN      0x800   /* 2^11 = 2048 = 0x800 */\r
-#define MAX_TX_BUFFER_LEN      0x800   /* 2^11 = 2048 = 0x800 */\r
-\r
-/* 14 bytes of ethernet header, 4 bytes VLAN, FCS,\r
- * plus extra pad to prevent buffer chaining of\r
- * maximum sized ethernet packets (1514 bytes) */\r
-#define        VMAC_BUFFER_PAD         (ETH_HLEN + 4 + ETH_FCS_LEN + 4)\r
-\r
-/* VMAC register definitions, offsets in the ref manual are in bytes */\r
-#define ID_OFFSET              (0x00/0x4)\r
-#define STAT_OFFSET            (0x04/0x4)\r
-#define ENABLE_OFFSET          (0x08/0x4)\r
-#define CONTROL_OFFSET         (0x0c/0x4)\r
-#define POLLRATE_OFFSET                (0x10/0x4)\r
-#define RXERR_OFFSET           (0x14/0x4)\r
-#define MISS_OFFSET            (0x18/0x4)\r
-#define TXRINGPTR_OFFSET       (0x1c/0x4)\r
-#define RXRINGPTR_OFFSET       (0x20/0x4)\r
-#define ADDRL_OFFSET           (0x24/0x4)\r
-#define ADDRH_OFFSET           (0x28/0x4)\r
-#define LAFL_OFFSET            (0x2c/0x4)\r
-#define LAFH_OFFSET            (0x30/0x4)\r
-#define MDIO_DATA_OFFSET       (0x34/0x4)\r
-#define MAC_TXRING_HEAD_OFFSET (0x38/0x4)\r
-#define MAC_RXRING_HEAD_OFFSET (0x3C/0x4)\r
-\r
-/* STATUS and ENABLE register bit masks */\r
-#define TXINT_MASK             (1<<0)  /* Transmit interrupt */\r
-#define RXINT_MASK             (1<<1)  /* Receive interrupt */\r
-#define ERR_MASK               (1<<2)  /* Error interrupt */\r
-#define TXCH_MASK              (1<<3)  /* Transmit chaining error interrupt */\r
-#define MSER_MASK              (1<<4)  /* Missed packet counter error */\r
-#define RXCR_MASK              (1<<8)  /* RXCRCERR counter rolled over  */\r
-#define RXFR_MASK              (1<<9)  /* RXFRAMEERR counter rolled over */\r
-#define RXFL_MASK              (1<<10) /* RXOFLOWERR counter rolled over */\r
-#define MDIO_MASK              (1<<12) /* MDIO complete */\r
-#define TXPL_MASK              (1<<31) /* TXPOLL */\r
-\r
-/* CONTROL register bitmasks */\r
-#define EN_MASK                        (1<<0)  /* VMAC enable */\r
-#define TXRN_MASK              (1<<3)  /* TX enable */\r
-#define RXRN_MASK              (1<<4)  /* RX enable */\r
-#define DSBC_MASK              (1<<8)  /* Disable receive broadcast */\r
-#define ENFL_MASK              (1<<10) /* Enable Full Duplex */            ///////\r
-#define PROM_MASK              (1<<11) /* Promiscuous mode */\r
-\r
-/* RXERR register bitmasks */\r
-#define RXERR_CRC              0x000000ff\r
-#define RXERR_FRM              0x0000ff00\r
-#define RXERR_OFLO             0x00ff0000 /* fifo overflow */\r
-\r
-/* MDIO data register bit masks */\r
-#define MDIO_SFD               0xC0000000\r
-#define MDIO_OP                        0x30000000\r
-#define MDIO_ID_MASK           0x0F800000\r
-#define MDIO_REG_MASK          0x007C0000\r
-#define MDIO_TA                        0x00030000\r
-#define MDIO_DATA_MASK         0x0000FFFF\r
-\r
-#define MDIO_BASE              0x40020000\r
-#define MDIO_OP_READ           0x20000000\r
-#define MDIO_OP_WRITE          0x10000000\r
-\r
-/* Buffer descriptor INFO bit masks */\r
-#define OWN_MASK               (1<<31) /* ownership of buffer, 0 CPU, 1 DMA */\r
-#define BUFF                   (1<<30) /* buffer invalid, rx */\r
-#define UFLO                   (1<<29) /* underflow, tx */\r
-#define LTCL                   (1<<28) /* late collision, tx  */\r
-#define RETRY_CT               (0xf<<24)  /* tx */\r
-#define DROP                   (1<<23) /* drop, more than 16 retries, tx */\r
-#define DEFER                  (1<<22) /* traffic on the wire, tx */\r
-#define CARLOSS                        (1<<21) /* carrier loss while transmission, tx, rx? */\r
-/* 20:19 reserved */\r
-#define ADCR                   (1<<18) /* add crc, ignored if not disaddcrc */\r
-#define LAST_MASK              (1<<17) /* Last buffer in chain */\r
-#define FRST_MASK              (1<<16) /* First buffer in chain */\r
-/* 15:11 reserved */\r
-#define LEN_MASK               0x000007FF\r
-\r
-#define ERR_MSK_TX             0x3fe00000 /* UFLO | LTCL | RTRY | DROP | DEFER | CRLS */\r
-\r
-\r
-/* arcvmac private data structures */\r
-struct vmac_buffer_desc {\r
-       unsigned int info;\r
-       dma_addr_t data;\r
-};\r
-\r
-struct dma_fifo {\r
-       int head; /* head */\r
-       int tail; /* tail */\r
-       int size;\r
-};\r
-\r
-struct vmac_priv {\r
-       struct net_device *dev;\r
-       struct platform_device *pdev;\r
-       struct net_device_stats stats;\r
-\r
-       spinlock_t lock; /* TODO revisit */\r
-       struct completion mdio_complete;\r
-\r
-       /* base address of register set */\r
-       int *regs;\r
-       unsigned int mem_base;\r
-\r
-       /* DMA ring buffers */\r
-       struct vmac_buffer_desc *rxbd;\r
-       dma_addr_t rxbd_dma;\r
-\r
-       struct vmac_buffer_desc *txbd;\r
-       dma_addr_t txbd_dma;\r
-\r
-       /* socket buffers */\r
-       struct sk_buff *rx_skbuff[RX_BDT_LEN];\r
-       struct sk_buff *tx_skbuff[TX_BDT_LEN];\r
-       int rx_skb_size;\r
-\r
-       /* skb / dma desc managing */\r
-       struct dma_fifo rx_ring;\r
-       struct dma_fifo tx_ring;\r
-\r
-       /* descriptor last polled/processed by the VMAC */\r
-       unsigned long mac_rxring_head;\r
-       /* used when rx skb allocation failed, so we defer rx queue\r
-        * refill */\r
-       struct timer_list rx_timeout;\r
-\r
-       /* lock rx_timeout against rx normal operation */\r
-       spinlock_t rx_lock;\r
-\r
-       struct napi_struct napi;\r
-\r
-       /* rx buffer chaining */\r
-       int rx_merge_error;\r
-       int tx_timeout_error;\r
-\r
-       /* PHY stuff */\r
-       struct mii_bus *mii_bus;\r
-       struct phy_device *phy_dev;\r
-\r
-       int link;\r
-       int speed;\r
-       int duplex;\r
-\r
-       int open_flag;\r
-       int suspending;\r
-       struct wake_lock resume_lock;\r
-\r
-       /* debug */\r
-       int shutdown;\r
-};\r
-\r
-/* DMA ring management */\r
-\r
-/* for a fifo with size n,\r
- * - [0..n] fill levels are n + 1 states\r
- * - there are only n different deltas (head - tail) values\r
- * => not all fill levels can be represented with head, tail\r
- *    pointers only\r
- * we give up the n fill level, aka fifo full */\r
-\r
-/* sacrifice one elt as a sentinel */\r
-static inline int fifo_used(struct dma_fifo *f);\r
-static inline int fifo_inc_ct(int ct, int size);\r
-static inline void fifo_dump(struct dma_fifo *fifo);\r
-\r
-static inline int fifo_empty(struct dma_fifo *f)\r
-{\r
-       return (f->head == f->tail);\r
-}\r
-\r
-static inline int fifo_free(struct dma_fifo *f)\r
-{\r
-       int free;\r
-\r
-       free = f->tail - f->head;\r
-       if (free <= 0)\r
-               free += f->size;\r
-\r
-       return free;\r
-}\r
-\r
-static inline int fifo_used(struct dma_fifo *f)\r
-{\r
-       int used;\r
-\r
-       used = f->head - f->tail;\r
-       if (used < 0)\r
-               used += f->size;\r
-\r
-       return used;\r
-}\r
-\r
-static inline int fifo_full(struct dma_fifo *f)\r
-{\r
-       return (fifo_used(f) + 1) == f->size;\r
-}\r
-\r
-/* manipulate */\r
-static inline void fifo_init(struct dma_fifo *fifo, int size)\r
-{\r
-       fifo->size = size;\r
-       fifo->head = fifo->tail = 0; /* empty */\r
-}\r
-\r
-static inline void fifo_inc_head(struct dma_fifo *fifo)\r
-{\r
-       BUG_ON(fifo_full(fifo));\r
-       fifo->head = fifo_inc_ct(fifo->head, fifo->size);\r
-}\r
-\r
-static inline void fifo_inc_tail(struct dma_fifo *fifo)\r
-{\r
-       BUG_ON(fifo_empty(fifo));\r
-       fifo->tail = fifo_inc_ct(fifo->tail, fifo->size);\r
-}\r
-\r
-/* internal funcs */\r
-static inline void fifo_dump(struct dma_fifo *fifo)\r
-{\r
-       printk(KERN_INFO "fifo: head %d, tail %d, size %d\n", fifo->head,\r
-                       fifo->tail,\r
-                       fifo->size);\r
-}\r
-\r
-static inline int fifo_inc_ct(int ct, int size)\r
-{\r
-       return (++ct == size) ? 0 : ct;\r
-}\r
-\r
-#endif   /* _ARCVMAC_H */\r
index ab8abc4b54f09afc80cf52caf548744bf7fc38bd..7ec0781ec6a5a6c83841594b4047082f1b792be5 100755 (executable)
@@ -485,8 +485,8 @@ int otg20_hcd_init( struct platform_device *_dev )
 #endif
 #if 0//LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
        /* Do not to do HNP polling if not capable */
-       if (otg_dev->core_if->otg_ver)
-               hcd->self.is_hnp_cap = dwc_otg_get_hnpcapable(otg_dev->core_if);
+       //if (otg_dev->core_if->otg_ver)
+       //      hcd->self.is_hnp_cap = dwc_otg_get_hnpcapable(otg_dev->core_if);
 #endif
        /*
         * Finish generic HCD initialization and start the HCD. This function
@@ -580,8 +580,8 @@ int host20_hcd_init( struct platform_device *_dev )
 #endif
 #if 0//LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
        /* Do not to do HNP polling if not capable */
-       if (otg_dev->core_if->otg_ver)
-               hcd->self.is_hnp_cap = dwc_otg_get_hnpcapable(otg_dev->core_if);
+       //if (otg_dev->core_if->otg_ver)
+       //      hcd->self.is_hnp_cap = dwc_otg_get_hnpcapable(otg_dev->core_if);
 #endif
        /*
         * Finish generic HCD initialization and start the HCD. This function