get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/811575/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 811575,
    "url": "http://patchwork.ozlabs.org/api/patches/811575/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/1504875731-3680-3-git-send-email-hayashi.kunihiko@socionext.com/",
    "project": {
        "id": 7,
        "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api",
        "name": "Linux network development",
        "link_name": "netdev",
        "list_id": "netdev.vger.kernel.org",
        "list_email": "netdev@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1504875731-3680-3-git-send-email-hayashi.kunihiko@socionext.com>",
    "list_archive_url": null,
    "date": "2017-09-08T13:02:10",
    "name": "[net-next,2/3] net: ethernet: socionext: add AVE ethernet driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "f13e630086b422802d35057686a6b5fe3cc7b9e1",
    "submitter": {
        "id": 71700,
        "url": "http://patchwork.ozlabs.org/api/people/71700/?format=api",
        "name": "Kunihiko Hayashi",
        "email": "hayashi.kunihiko@socionext.com"
    },
    "delegate": {
        "id": 34,
        "url": "http://patchwork.ozlabs.org/api/users/34/?format=api",
        "username": "davem",
        "first_name": "David",
        "last_name": "Miller",
        "email": "davem@davemloft.net"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/1504875731-3680-3-git-send-email-hayashi.kunihiko@socionext.com/mbox/",
    "series": [
        {
            "id": 2200,
            "url": "http://patchwork.ozlabs.org/api/series/2200/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=2200",
            "date": "2017-09-08T13:02:11",
            "name": "add UniPhier AVE ethernet support",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/2200/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/811575/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/811575/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netdev-owner@vger.kernel.org>",
        "X-Original-To": "patchwork-incoming@ozlabs.org",
        "Delivered-To": "patchwork-incoming@ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xpcvM6X14z9ryk\n\tfor <patchwork-incoming@ozlabs.org>;\n\tFri,  8 Sep 2017 23:03:27 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S932434AbdIHNDL (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tFri, 8 Sep 2017 09:03:11 -0400",
            "from mx.socionext.com ([202.248.49.38]:38772 \"EHLO\n\tmx.socionext.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S932161AbdIHNC3 (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tFri, 8 Sep 2017 09:02:29 -0400",
            "from unknown (HELO iyokan-ex.css.socionext.com) ([172.31.9.54])\n\tby mx.socionext.com with ESMTP; 08 Sep 2017 22:02:28 +0900",
            "from mail.mfilter.local (unknown [10.213.24.61])\n\tby iyokan-ex.css.socionext.com (Postfix) with ESMTP id 1D9A0610C6;\n\tFri,  8 Sep 2017 22:02:28 +0900 (JST)",
            "from 172.31.9.51 (172.31.9.51) by m-FILTER with ESMTP;\n\tFri, 8 Sep 2017 22:02:28 +0900",
            "from plum.e01.socionext.com (unknown [10.213.132.32])\n\tby kinkan.css.socionext.com (Postfix) with ESMTP id 62C551A0E11;\n\tFri,  8 Sep 2017 22:02:27 +0900 (JST)"
        ],
        "From": "Kunihiko Hayashi <hayashi.kunihiko@socionext.com>",
        "To": "netdev@vger.kernel.org, \"David S. Miller\" <davem@davemloft.net>,\n\tAndrew Lunn <andrew@lunn.ch>, Florian Fainelli <f.fainelli@gmail.com>",
        "Cc": "Rob Herring <robh+dt@kernel.org>, Mark Rutland <mark.rutland@arm.com>,\n\tlinux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org,\n\tdevicetree@vger.kernel.org,\n\tMasahiro Yamada <yamada.masahiro@socionext.com>,\n\tMasami Hiramatsu <masami.hiramatsu@linaro.org>,\n\tJassi Brar <jaswinder.singh@linaro.org>,\n\tKunihiko Hayashi <hayashi.kunihiko@socionext.com>",
        "Subject": "[PATCH net-next 2/3] net: ethernet: socionext: add AVE ethernet\n\tdriver",
        "Date": "Fri,  8 Sep 2017 22:02:10 +0900",
        "Message-Id": "<1504875731-3680-3-git-send-email-hayashi.kunihiko@socionext.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1504875731-3680-1-git-send-email-hayashi.kunihiko@socionext.com>",
        "References": "<1504875731-3680-1-git-send-email-hayashi.kunihiko@socionext.com>",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "The UniPhier platform from Socionext provides the AVE ethernet\ncontroller that includes MAC and MDIO bus supporting RGMII/RMII\nmodes. The controller is named AVE.\n\nSigned-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>\nSigned-off-by: Jassi Brar <jaswinder.singh@linaro.org>\n---\n drivers/net/ethernet/Kconfig             |    1 +\n drivers/net/ethernet/Makefile            |    1 +\n drivers/net/ethernet/socionext/Kconfig   |   22 +\n drivers/net/ethernet/socionext/Makefile  |    4 +\n drivers/net/ethernet/socionext/sni_ave.c | 1618 ++++++++++++++++++++++++++++++\n 5 files changed, 1646 insertions(+)\n create mode 100644 drivers/net/ethernet/socionext/Kconfig\n create mode 100644 drivers/net/ethernet/socionext/Makefile\n create mode 100644 drivers/net/ethernet/socionext/sni_ave.c",
    "diff": "diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig\nindex c604213..d50519e 100644\n--- a/drivers/net/ethernet/Kconfig\n+++ b/drivers/net/ethernet/Kconfig\n@@ -170,6 +170,7 @@ source \"drivers/net/ethernet/sis/Kconfig\"\n source \"drivers/net/ethernet/sfc/Kconfig\"\n source \"drivers/net/ethernet/sgi/Kconfig\"\n source \"drivers/net/ethernet/smsc/Kconfig\"\n+source \"drivers/net/ethernet/socionext/Kconfig\"\n source \"drivers/net/ethernet/stmicro/Kconfig\"\n source \"drivers/net/ethernet/sun/Kconfig\"\n source \"drivers/net/ethernet/tehuti/Kconfig\"\ndiff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile\nindex a0a03d4..9f55b36 100644\n--- a/drivers/net/ethernet/Makefile\n+++ b/drivers/net/ethernet/Makefile\n@@ -81,6 +81,7 @@ obj-$(CONFIG_SFC) += sfc/\n obj-$(CONFIG_SFC_FALCON) += sfc/falcon/\n obj-$(CONFIG_NET_VENDOR_SGI) += sgi/\n obj-$(CONFIG_NET_VENDOR_SMSC) += smsc/\n+obj-$(CONFIG_NET_VENDOR_SOCIONEXT) += socionext/\n obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/\n obj-$(CONFIG_NET_VENDOR_SUN) += sun/\n obj-$(CONFIG_NET_VENDOR_TEHUTI) += tehuti/\ndiff --git a/drivers/net/ethernet/socionext/Kconfig b/drivers/net/ethernet/socionext/Kconfig\nnew file mode 100644\nindex 0000000..788f26f\n--- /dev/null\n+++ b/drivers/net/ethernet/socionext/Kconfig\n@@ -0,0 +1,22 @@\n+config NET_VENDOR_SOCIONEXT\n+\tbool \"Socionext ethernet drivers\"\n+\tdefault y\n+\t---help---\n+\t  Option to select ethernet drivers for Socionext platforms.\n+\n+\t  Note that the answer to this question doesn't directly affect the\n+\t  kernel: saying N will just cause the configurator to skip all\n+\t  the questions about Agere devices. If you say Y, you will be asked\n+\t  for your specific card in the following questions.\n+\n+if NET_VENDOR_SOCIONEXT\n+\n+config SNI_AVE\n+\ttristate \"Socionext AVE ethernet support\"\n+\tdepends on (ARCH_UNIPHIER || COMPILE_TEST) && OF\n+\tselect PHYLIB\n+\t---help---\n+\t  Driver for gigabit ethernet MACs, called AVE, in the\n+\t  Socionext UniPhier family.\n+\n+endif #NET_VENDOR_SOCIONEXT\ndiff --git a/drivers/net/ethernet/socionext/Makefile b/drivers/net/ethernet/socionext/Makefile\nnew file mode 100644\nindex 0000000..0356341\n--- /dev/null\n+++ b/drivers/net/ethernet/socionext/Makefile\n@@ -0,0 +1,4 @@\n+#\n+# Makefile for all ethernet ip drivers on Socionext platforms\n+#\n+obj-$(CONFIG_SNI_AVE) += sni_ave.o\ndiff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c\nnew file mode 100644\nindex 0000000..c870777\n--- /dev/null\n+++ b/drivers/net/ethernet/socionext/sni_ave.c\n@@ -0,0 +1,1618 @@\n+/**\n+ * sni_ave.c - Socionext UniPhier AVE ethernet driver\n+ *\n+ * Copyright 2014 Panasonic Corporation\n+ * Copyright 2015-2017 Socionext Inc.\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License version 2  of\n+ * the License as published by the Free Software Foundation.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ */\n+\n+#include <linux/bitops.h>\n+#include <linux/clk.h>\n+#include <linux/etherdevice.h>\n+#include <linux/interrupt.h>\n+#include <linux/io.h>\n+#include <linux/mii.h>\n+#include <linux/module.h>\n+#include <linux/netdevice.h>\n+#include <linux/of_net.h>\n+#include <linux/of_mdio.h>\n+#include <linux/of_platform.h>\n+#include <linux/phy.h>\n+#include <linux/reset.h>\n+#include <linux/types.h>\n+\n+/* General Register Group */\n+#define AVE_IDR\t\t0x0\t/* ID */\n+#define AVE_VR\t\t0x4\t/* Version */\n+#define AVE_GRR\t\t0x8\t/* Global Reset */\n+#define AVE_CFGR\t0xc\t/* Configuration */\n+\n+/* Interrupt Register Group */\n+#define AVE_GIMR\t0x100\t/* Global Interrupt Mask */\n+#define AVE_GISR\t0x104\t/* Global Interrupt Status */\n+\n+/* MAC Register Group */\n+#define AVE_TXCR\t0x200\t/* TX Setup */\n+#define AVE_RXCR\t0x204\t/* RX Setup */\n+#define AVE_RXMAC1R\t0x208\t/* MAC address (lower) */\n+#define AVE_RXMAC2R\t0x20c\t/* MAC address (upper) */\n+#define AVE_MDIOCTR\t0x214\t/* MDIO Control */\n+#define AVE_MDIOAR\t0x218\t/* MDIO Address */\n+#define AVE_MDIOWDR\t0x21c\t/* MDIO Data */\n+#define AVE_MDIOSR\t0x220\t/* MDIO Status */\n+#define AVE_MDIORDR\t0x224\t/* MDIO Rd Data */\n+\n+/* Descriptor Control Register Group */\n+#define AVE_DESCC\t0x300\t/* Descriptor Control */\n+#define AVE_TXDC\t0x304\t/* TX Descriptor Configuration */\n+#define AVE_RXDC0\t0x308\t/* RX Descriptor Ring0 Configuration */\n+#define AVE_IIRQC\t0x34c\t/* Interval IRQ Control */\n+\n+/* Frame Counter Register Group */\n+#define AVE_BFCR\t0x400\t/* Bad Frame Counter */\n+#define AVE_RX0OVFFC\t0x414\t/* OVF Frame Counter (Ring0) */\n+#define AVE_SN5FC\t0x438\t/* Frame Counter No5 */\n+#define AVE_SN6FC\t0x43c\t/* Frame Counter No6 */\n+#define AVE_SN7FC\t0x440\t/* Frame Counter No7 */\n+\n+/* Packet Filter Register Group */\n+#define AVE_PKTF_BASE\t\t0x800\t/* PF Base Address */\n+#define AVE_PFMBYTE_BASE\t0xd00\t/* PF Mask Byte Base Address */\n+#define AVE_PFMBIT_BASE\t\t0xe00\t/* PF Mask Bit Base Address */\n+#define AVE_PFSEL_BASE\t\t0xf00\t/* PF Selector Base Address */\n+#define AVE_PFEN\t\t0xffc\t/* Packet Filter Enable */\n+#define AVE_PKTF(ent)\t\t(AVE_PKTF_BASE + (ent) * 0x40)\n+#define AVE_PFMBYTE(ent)\t(AVE_PFMBYTE_BASE + (ent) * 8)\n+#define AVE_PFMBIT(ent)\t\t(AVE_PFMBIT_BASE + (ent) * 4)\n+#define AVE_PFSEL(ent)\t\t(AVE_PFSEL_BASE + (ent) * 4)\n+\n+/* 64bit descriptor memory */\n+#define AVE_DESC_SIZE_64\t12\t/* Descriptor Size */\n+\n+#define AVE_TXDM_64\t\t0x1000\t/* Tx Descriptor Memory */\n+#define AVE_RXDM_64\t\t0x1c00\t/* Rx Descriptor Memory */\n+\n+#define AVE_TXDM_SIZE_64\t0x0ba0\t/* Tx Descriptor Memory Size 3KB */\n+#define AVE_RXDM_SIZE_64\t0x6000\t/* Rx Descriptor Memory Size 24KB */\n+\n+/* 32bit descriptor memory */\n+#define AVE_DESC_SIZE_32\t8\t/* Descriptor Size */\n+\n+#define AVE_TXDM_32\t\t0x1000\t/* Tx Descriptor Memory */\n+#define AVE_RXDM_32\t\t0x1800\t/* Rx Descriptor Memory */\n+\n+#define AVE_TXDM_SIZE_32\t0x07c0\t/* Tx Descriptor Memory Size 2KB */\n+#define AVE_RXDM_SIZE_32\t0x4000\t/* Rx Descriptor Memory Size 16KB */\n+\n+/* RMII Bridge Register Group */\n+#define AVE_RSTCTRL\t\t0x8028\t/* Reset control */\n+#define AVE_RSTCTRL_RMIIRST\tBIT(16)\n+#define AVE_LINKSEL\t\t0x8034\t/* Link speed setting */\n+#define AVE_LINKSEL_100M\tBIT(0)\n+\n+/* AVE_GRR */\n+#define AVE_GRR_RXFFR\t\tBIT(5)\t/* Reset RxFIFO */\n+#define AVE_GRR_PHYRST\t\tBIT(4)\t/* Reset external PHY */\n+#define AVE_GRR_GRST\t\tBIT(0)\t/* Reset all MAC */\n+\n+/* AVE_GISR (common with GIMR) */\n+#define AVE_GI_PHY\t\tBIT(24)\t/* PHY interrupt */\n+#define AVE_GI_TX\t\tBIT(16)\t/* Tx complete */\n+#define AVE_GI_RXERR\t\tBIT(8)\t/* Receive frame more than max size */\n+#define AVE_GI_RXOVF\t\tBIT(7)\t/* Overflow at the RxFIFO */\n+#define AVE_GI_RXDROP\t\tBIT(6)\t/* Drop packet */\n+#define AVE_GI_RXIINT\t\tBIT(5)\t/* Interval interrupt */\n+\n+/* AVE_TXCR */\n+#define AVE_TXCR_FLOCTR\t\tBIT(18)\t/* Flow control */\n+#define AVE_TXCR_TXSPD_1G\tBIT(17)\n+#define AVE_TXCR_TXSPD_100\tBIT(16)\n+\n+/* AVE_RXCR */\n+#define AVE_RXCR_RXEN\t\tBIT(30)\t/* Rx enable */\n+#define AVE_RXCR_FDUPEN\t\tBIT(22)\t/* Interface mode */\n+#define AVE_RXCR_FLOCTR\t\tBIT(21)\t/* Flow control */\n+#define AVE_RXCR_AFEN\t\tBIT(19)\t/* MAC address filter */\n+#define AVE_RXCR_DRPEN\t\tBIT(18)\t/* Drop pause frame */\n+#define AVE_RXCR_MPSIZ_MASK\tGENMASK(10, 0)\n+\n+/* AVE_MDIOCTR */\n+#define AVE_MDIOCTR_RREQ\tBIT(3)\t/* Read request */\n+#define AVE_MDIOCTR_WREQ\tBIT(2)\t/* Write request */\n+\n+/* AVE_MDIOSR */\n+#define AVE_MDIOSR_STS\t\tBIT(0)\t/* access status */\n+\n+/* AVE_DESCC */\n+#define AVE_DESCC_TD\t\tBIT(0)\t/* Enable Tx descriptor */\n+#define AVE_DESCC_RDSTP\t\tBIT(4)\t/* Pause Rx descriptor */\n+#define AVE_DESCC_RD0\t\tBIT(8)\t/* Enable Rx descriptor Ring0 */\n+\n+#define AVE_DESCC_CTRL_MASK\tGENMASK(15, 0)\n+\n+/* AVE_TXDC */\n+#define AVE_TXDC_SIZE\t\tGENMASK(27, 16)\t/* Size of Tx descriptor */\n+#define AVE_TXDC_ADDR\t\tGENMASK(11, 0)\t/* Start address */\n+#define AVE_TXDC_ADDR_START\t0\n+\n+/* AVE_RXDC0 */\n+#define AVE_RXDC0_SIZE\t\tGENMASK(30, 16)\t/* Size of Rx descriptor */\n+#define AVE_RXDC0_ADDR\t\tGENMASK(14, 0)\t/* Start address */\n+#define AVE_RXDC0_ADDR_START\t0\n+\n+/* AVE_IIRQC */\n+#define AVE_IIRQC_EN0\t\tBIT(27)\t/* Enable interval interrupt Ring0 */\n+#define AVE_IIRQC_BSCK\t\tGENMASK(15, 0)\t/* Interval count unit */\n+\n+/* Command status for Descriptor */\n+#define AVE_STS_OWN\t\tBIT(31)\t/* Descriptor ownership */\n+#define AVE_STS_INTR\t\tBIT(29)\t/* Request for interrupt */\n+#define AVE_STS_OK\t\tBIT(27)\t/* Normal transmit */\n+/* TX */\n+#define AVE_STS_NOCSUM\t\tBIT(28)\t/* No use HW checksum */\n+#define AVE_STS_1ST\t\tBIT(26)\t/* Head of buffer chain */\n+#define AVE_STS_LAST\t\tBIT(25)\t/* Tail of buffer chain */\n+#define AVE_STS_OWC\t\tBIT(21)\t/* Out of window,Late Collision */\n+#define AVE_STS_EC\t\tBIT(20)\t/* Excess collision occurred */\n+#define AVE_STS_PKTLEN_TX\tGENMASK(15, 0)\n+/* RX */\n+#define AVE_STS_CSSV\t\tBIT(21)\t/* Checksum check performed */\n+#define AVE_STS_CSER\t\tBIT(20)\t/* Checksum error detected */\n+#define AVE_STS_PKTLEN_RX\tGENMASK(10, 0)\n+\n+/* AVE_CFGR */\n+#define AVE_CFGR_FLE\t\tBIT(31)\t/* Filter Function */\n+#define AVE_CFGR_CHE\t\tBIT(30)\t/* Checksum Function */\n+#define AVE_CFGR_MII\t\tBIT(27)\t/* Func mode (1:MII/RMII, 0:RGMII) */\n+#define AVE_CFGR_IPFCEN\t\tBIT(24)\t/* IP fragment sum Enable */\n+\n+#define AVE_MAX_ETHFRAME\t1518\n+\n+/* Packet filter size */\n+#define AVE_PF_SIZE\t\t17\t/* Number of all packet filter */\n+#define AVE_PF_MULTICAST_SIZE\t7\t/* Number of multicast filter */\n+\n+/* Packet filter definition */\n+#define AVE_PFNUM_FILTER\t0\t/* No.0 */\n+#define AVE_PFNUM_UNICAST\t1\t/* No.1 */\n+#define AVE_PFNUM_BROADCAST\t2\t/* No.2 */\n+#define AVE_PFNUM_MULTICAST\t11\t/* No.11-17 */\n+\n+/* NETIF Message control */\n+#define AVE_DEFAULT_MSG_ENABLE\t(NETIF_MSG_DRV    |\t\\\n+\t\t\t\t NETIF_MSG_PROBE  |\t\\\n+\t\t\t\t NETIF_MSG_LINK   |\t\\\n+\t\t\t\t NETIF_MSG_TIMER  |\t\\\n+\t\t\t\t NETIF_MSG_IFDOWN |\t\\\n+\t\t\t\t NETIF_MSG_IFUP   |\t\\\n+\t\t\t\t NETIF_MSG_RX_ERR |\t\\\n+\t\t\t\t NETIF_MSG_TX_ERR)\n+\n+/* Parameter for descriptor */\n+#define AVE_NR_TXDESC\t\t32\t/* Tx descriptor */\n+#define AVE_NR_RXDESC\t\t64\t/* Rx descriptor */\n+\n+/* Parameter for interrupt */\n+#define AVE_INTM_COUNT\t\t20\n+#define AVE_FORCE_TXINTCNT\t1\n+\n+#define IS_DESC_64BIT(p)\t((p)->desc_size == AVE_DESC_SIZE_64)\n+\n+enum desc_id {\n+\tAVE_DESCID_TX = 0,\n+\tAVE_DESCID_RX,\n+};\n+\n+enum desc_state {\n+\tAVE_DESC_STOP = 0,\n+\tAVE_DESC_START,\n+\tAVE_DESC_RX_SUSPEND,\n+\tAVE_DESC_RX_PERMIT,\n+};\n+\n+struct ave_desc {\n+\tstruct sk_buff\t*skbs;\n+\tdma_addr_t\tskbs_dma;\n+\tsize_t\t\tskbs_dmalen;\n+};\n+\n+struct ave_desc_info {\n+\tu32\tndesc;\t\t/* number of descriptor */\n+\tu32\tdaddr;\t\t/* start address of descriptor */\n+\tu32\tproc_idx;\t/* index of processing packet */\n+\tu32\tdone_idx;\t/* index of processed packet */\n+\tstruct ave_desc *desc;\t/* skb info related descriptor */\n+};\n+\n+struct ave_private {\n+\tint\t\t\tphy_id;\n+\tunsigned int\t\tdesc_size;\n+\tu32\t\t\tmsg_enable;\n+\tstruct clk\t\t*clk;\n+\tphy_interface_t\t\tphy_mode;\n+\tstruct phy_device\t*phydev;\n+\tstruct mii_bus\t\t*mdio;\n+\tstruct net_device_stats\tstats;\n+\tbool\t\t\tinternal_phy_interrupt;\n+\n+\t/* NAPI support */\n+\tstruct net_device\t*ndev;\n+\tstruct napi_struct\tnapi_rx;\n+\tstruct napi_struct\tnapi_tx;\n+\n+\t/* descriptor */\n+\tstruct ave_desc_info\trx;\n+\tstruct ave_desc_info\ttx;\n+};\n+\n+static inline u32 ave_r32(struct net_device *ndev, u32 offset)\n+{\n+\tvoid __iomem *addr = (void __iomem *)ndev->base_addr;\n+\n+\treturn readl_relaxed(addr + offset);\n+}\n+\n+static inline void ave_w32(struct net_device *ndev, u32 offset, u32 value)\n+{\n+\tvoid __iomem *addr = (void __iomem *)ndev->base_addr;\n+\n+\twritel_relaxed(value, addr + offset);\n+}\n+\n+static inline u32 ave_rdesc(struct net_device *ndev, enum desc_id id,\n+\t\t\t    int entry, int offset)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 addr = (id == AVE_DESCID_TX) ? priv->tx.daddr : priv->rx.daddr;\n+\n+\taddr += entry * priv->desc_size + offset;\n+\n+\treturn ave_r32(ndev, addr);\n+}\n+\n+static inline void ave_wdesc(struct net_device *ndev, enum desc_id id,\n+\t\t\t     int entry, int offset, u32 val)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 addr = (id == AVE_DESCID_TX) ? priv->tx.daddr : priv->rx.daddr;\n+\n+\taddr += entry * priv->desc_size + offset;\n+\n+\tave_w32(ndev, addr, val);\n+}\n+\n+static void ave_wdesc_addr(struct net_device *ndev, enum desc_id id,\n+\t\t\t   int entry, int offset, dma_addr_t paddr)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\n+\tave_wdesc(ndev, id, entry, offset, (u32)((u64)paddr & 0xFFFFFFFFULL));\n+\tif (IS_DESC_64BIT(priv))\n+\t\tave_wdesc(ndev, id,\n+\t\t\t  entry, offset + 4, (u32)((u64)paddr >> 32));\n+\telse if ((u64)paddr > (u64)U32_MAX)\n+\t\tnetdev_warn(ndev, \"DMA address exceeds the address space\\n\");\n+}\n+\n+static void ave_get_fwversion(struct net_device *ndev, char *buf, int len)\n+{\n+\tu32 major, minor;\n+\n+\tmajor = (ave_r32(ndev, AVE_VR) & GENMASK(15, 8)) >> 8;\n+\tminor = (ave_r32(ndev, AVE_VR) & GENMASK(7, 0));\n+\tsnprintf(buf, len, \"v%u.%u\", major, minor);\n+}\n+\n+static void ave_get_drvinfo(struct net_device *ndev,\n+\t\t\t    struct ethtool_drvinfo *info)\n+{\n+\tstruct device *dev = ndev->dev.parent;\n+\n+\tstrlcpy(info->driver, dev->driver->name, sizeof(info->driver));\n+\tstrlcpy(info->bus_info, dev_name(dev), sizeof(info->bus_info));\n+\tave_get_fwversion(ndev, info->fw_version, sizeof(info->fw_version));\n+}\n+\n+static int ave_nway_reset(struct net_device *ndev)\n+{\n+\treturn genphy_restart_aneg(ndev->phydev);\n+}\n+\n+static u32 ave_get_link(struct net_device *ndev)\n+{\n+\tint err;\n+\n+\terr = genphy_update_link(ndev->phydev);\n+\tif (err)\n+\t\treturn ethtool_op_get_link(ndev);\n+\n+\treturn ndev->phydev->link;\n+}\n+\n+static u32 ave_get_msglevel(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\n+\treturn priv->msg_enable;\n+}\n+\n+static void ave_set_msglevel(struct net_device *ndev, u32 val)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\n+\tpriv->msg_enable = val;\n+}\n+\n+static void ave_get_wol(struct net_device *ndev,\n+\t\t\tstruct ethtool_wolinfo *wol)\n+{\n+\twol->supported = 0;\n+\twol->wolopts   = 0;\n+\tphy_ethtool_get_wol(ndev->phydev, wol);\n+}\n+\n+static int ave_set_wol(struct net_device *ndev,\n+\t\t       struct ethtool_wolinfo *wol)\n+{\n+\tif (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))\n+\t\treturn -EOPNOTSUPP;\n+\n+\treturn phy_ethtool_set_wol(ndev->phydev, wol);\n+}\n+\n+static const struct ethtool_ops ave_ethtool_ops = {\n+\t.get_link_ksettings\t= phy_ethtool_get_link_ksettings,\n+\t.set_link_ksettings\t= phy_ethtool_set_link_ksettings,\n+\t.get_drvinfo\t\t= ave_get_drvinfo,\n+\t.nway_reset\t\t= ave_nway_reset,\n+\t.get_link\t\t= ave_get_link,\n+\t.get_msglevel\t\t= ave_get_msglevel,\n+\t.set_msglevel\t\t= ave_set_msglevel,\n+\t.get_wol\t\t= ave_get_wol,\n+\t.set_wol\t\t= ave_set_wol,\n+};\n+\n+static int ave_pfsel_start(struct net_device *ndev, unsigned int entry)\n+{\n+\tu32 val;\n+\n+\tif (WARN_ON(entry > AVE_PF_SIZE))\n+\t\treturn -EINVAL;\n+\n+\tval = ave_r32(ndev, AVE_PFEN);\n+\tave_w32(ndev, AVE_PFEN, val | BIT(entry));\n+\n+\treturn 0;\n+}\n+\n+static int ave_pfsel_stop(struct net_device *ndev, unsigned int entry)\n+{\n+\tu32 val;\n+\n+\tif (WARN_ON(entry > AVE_PF_SIZE))\n+\t\treturn -EINVAL;\n+\n+\tval = ave_r32(ndev, AVE_PFEN);\n+\tave_w32(ndev, AVE_PFEN, val & ~BIT(entry));\n+\n+\treturn 0;\n+}\n+\n+static int ave_pfsel_macaddr_set(struct net_device *ndev,\n+\t\t\t\t unsigned int entry, unsigned char *mac_addr,\n+\t\t\t\t unsigned int set_size)\n+{\n+\tu32 val;\n+\n+\tif (WARN_ON(entry > AVE_PF_SIZE))\n+\t\treturn -EINVAL;\n+\tif (WARN_ON(set_size > 6))\n+\t\treturn -EINVAL;\n+\n+\tave_pfsel_stop(ndev, entry);\n+\n+\t/* set MAC address for the filter */\n+\tval = le32_to_cpu(((u32 *)mac_addr)[0]);\n+\tave_w32(ndev, AVE_PKTF(entry), val);\n+\tval = (u32)le16_to_cpu(((u16 *)mac_addr)[2]);\n+\tave_w32(ndev, AVE_PKTF(entry) + 4, val);\n+\n+\t/* set byte mask */\n+\tave_w32(ndev, AVE_PFMBYTE(entry), GENMASK(31, set_size) & ~0xc0);\n+\tave_w32(ndev, AVE_PFMBYTE(entry) + 4, 0xFFFFFFFF);\n+\n+\t/* set bit mask filter */\n+\tave_w32(ndev, AVE_PFMBIT(entry), 0x0000FFFF);\n+\n+\t/* set selector to ring 0 */\n+\tave_w32(ndev, AVE_PFSEL(entry), 0);\n+\n+\t/* restart filter */\n+\tave_pfsel_start(ndev, entry);\n+\n+\treturn 0;\n+}\n+\n+static int ave_mdio_busywait(struct net_device *ndev)\n+{\n+\tint ret = 1, loop = 100;\n+\tu32 mdiosr;\n+\n+\t/* wait until completion */\n+\twhile (1) {\n+\t\tmdiosr = ave_r32(ndev, AVE_MDIOSR);\n+\t\tif (!(mdiosr & AVE_MDIOSR_STS))\n+\t\t\tbreak;\n+\n+\t\tusleep_range(10, 20);\n+\t\tif (!loop--) {\n+\t\t\tnetdev_err(ndev,\n+\t\t\t\t   \"failed to read from MDIO (status:0x%08x)\\n\",\n+\t\t\t\t   mdiosr);\n+\t\t\tret = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int ave_mdiobus_read(struct mii_bus *bus, int phyid, int regnum)\n+{\n+\tstruct net_device *ndev = bus->priv;\n+\tu32 mdioctl;\n+\n+\t/* write address */\n+\tave_w32(ndev, AVE_MDIOAR, (phyid << 8) | regnum);\n+\n+\t/* read request */\n+\tmdioctl = ave_r32(ndev, AVE_MDIOCTR);\n+\tave_w32(ndev, AVE_MDIOCTR, mdioctl | AVE_MDIOCTR_RREQ);\n+\n+\tif (!ave_mdio_busywait(ndev)) {\n+\t\tnetdev_err(ndev, \"phy-%d reg-%x read failed\\n\",\n+\t\t\t   phyid, regnum);\n+\t\treturn 0xffff;\n+\t}\n+\n+\treturn ave_r32(ndev, AVE_MDIORDR) & GENMASK(15, 0);\n+}\n+\n+static int ave_mdiobus_write(struct mii_bus *bus,\n+\t\t\t     int phyid, int regnum, u16 val)\n+{\n+\tstruct net_device *ndev = bus->priv;\n+\tu32 mdioctl;\n+\n+\t/* write address */\n+\tave_w32(ndev, AVE_MDIOAR, (phyid << 8) | regnum);\n+\n+\t/* write data */\n+\tave_w32(ndev, AVE_MDIOWDR, val);\n+\n+\t/* write request */\n+\tmdioctl = ave_r32(ndev, AVE_MDIOCTR);\n+\tave_w32(ndev, AVE_MDIOCTR, mdioctl | AVE_MDIOCTR_WREQ);\n+\n+\tif (!ave_mdio_busywait(ndev)) {\n+\t\tnetdev_err(ndev, \"phy-%d reg-%x write failed\\n\",\n+\t\t\t   phyid, regnum);\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static dma_addr_t ave_dma_map(struct net_device *ndev, struct ave_desc *desc,\n+\t\t\t      void *ptr, size_t len,\n+\t\t\t      enum dma_data_direction dir)\n+{\n+\tdma_addr_t paddr;\n+\n+\tpaddr = dma_map_single(ndev->dev.parent, ptr, len, dir);\n+\tif (dma_mapping_error(ndev->dev.parent, paddr)) {\n+\t\tdesc->skbs_dma = 0;\n+\t\tpaddr = (dma_addr_t)virt_to_phys(ptr);\n+\t} else {\n+\t\tdesc->skbs_dma = paddr;\n+\t\tdesc->skbs_dmalen = len;\n+\t}\n+\n+\treturn paddr;\n+}\n+\n+static void ave_dma_unmap(struct net_device *ndev, struct ave_desc *desc,\n+\t\t\t  enum dma_data_direction dir)\n+{\n+\tif (!desc->skbs_dma)\n+\t\treturn;\n+\n+\tdma_unmap_single(ndev->dev.parent,\n+\t\t\t desc->skbs_dma, desc->skbs_dmalen, dir);\n+\tdesc->skbs_dma = 0;\n+}\n+\n+/* Set Rx descriptor and memory */\n+static int ave_set_rxdesc(struct net_device *ndev, int entry)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tstruct sk_buff *skb;\n+\tunsigned long align;\n+\tdma_addr_t paddr;\n+\tvoid *buffptr;\n+\tint ret = 0;\n+\n+\tskb = priv->rx.desc[entry].skbs;\n+\tif (!skb) {\n+\t\tskb = netdev_alloc_skb_ip_align(ndev,\n+\t\t\t\t\t\tAVE_MAX_ETHFRAME + NET_SKB_PAD);\n+\t\tif (!skb) {\n+\t\t\tnetdev_err(ndev, \"can't allocate skb for Rx\\n\");\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t}\n+\n+\t/* set disable to cmdsts */\n+\tave_wdesc(ndev, AVE_DESCID_RX, entry, 0, AVE_STS_INTR | AVE_STS_OWN);\n+\n+\t/* align skb data for cache size */\n+\talign = (unsigned long)skb_tail_pointer(skb) & (NET_SKB_PAD - 1);\n+\talign = NET_SKB_PAD - align;\n+\tskb_reserve(skb, align);\n+\tbuffptr = (void *)skb_tail_pointer(skb);\n+\n+\tpaddr = ave_dma_map(ndev, &priv->rx.desc[entry], buffptr,\n+\t\t\t    AVE_MAX_ETHFRAME + NET_IP_ALIGN, DMA_FROM_DEVICE);\n+\tpriv->rx.desc[entry].skbs = skb;\n+\n+\t/* set buffer pointer */\n+\tave_wdesc_addr(ndev, AVE_DESCID_RX, entry, 4, paddr);\n+\n+\t/* set enable to cmdsts */\n+\tave_wdesc(ndev, AVE_DESCID_RX,\n+\t\t  entry, 0, AVE_STS_INTR | AVE_MAX_ETHFRAME);\n+\n+\treturn ret;\n+}\n+\n+/* Switch state of descriptor */\n+static int ave_desc_switch(struct net_device *ndev, enum desc_state state)\n+{\n+\tint counter;\n+\tu32 val;\n+\n+\tswitch (state) {\n+\tcase AVE_DESC_START:\n+\t\tave_w32(ndev, AVE_DESCC, AVE_DESCC_TD | AVE_DESCC_RD0);\n+\t\tbreak;\n+\n+\tcase AVE_DESC_STOP:\n+\t\tave_w32(ndev, AVE_DESCC, 0);\n+\t\tcounter = 0;\n+\t\twhile (1) {\n+\t\t\tusleep_range(100, 150);\n+\t\t\tif (!ave_r32(ndev, AVE_DESCC))\n+\t\t\t\tbreak;\n+\n+\t\t\tcounter++;\n+\t\t\tif (counter > 100) {\n+\t\t\t\tnetdev_err(ndev, \"can't stop descriptor\\n\");\n+\t\t\t\treturn -EBUSY;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\n+\tcase AVE_DESC_RX_SUSPEND:\n+\t\tval = ave_r32(ndev, AVE_DESCC);\n+\t\tval |= AVE_DESCC_RDSTP;\n+\t\tval &= AVE_DESCC_CTRL_MASK;\n+\t\tave_w32(ndev, AVE_DESCC, val);\n+\n+\t\tcounter = 0;\n+\t\twhile (1) {\n+\t\t\tusleep_range(100, 150);\n+\t\t\tval = ave_r32(ndev, AVE_DESCC);\n+\t\t\tif (val & (AVE_DESCC_RDSTP << 16))\n+\t\t\t\tbreak;\n+\n+\t\t\tcounter++;\n+\t\t\tif (counter > 1000) {\n+\t\t\t\tnetdev_err(ndev, \"can't suspend descriptor\\n\");\n+\t\t\t\treturn -EBUSY;\n+\t\t\t}\n+\t\t}\n+\t\tbreak;\n+\n+\tcase AVE_DESC_RX_PERMIT:\n+\t\tval = ave_r32(ndev, AVE_DESCC);\n+\t\tval &= ~AVE_DESCC_RDSTP;\n+\t\tval &= AVE_DESCC_CTRL_MASK;\n+\t\tave_w32(ndev, AVE_DESCC, val);\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int ave_tx_completion(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 proc_idx, done_idx, ndesc, val;\n+\tint freebuf_flag = 0;\n+\n+\tproc_idx = priv->tx.proc_idx;\n+\tdone_idx = priv->tx.done_idx;\n+\tndesc    = priv->tx.ndesc;\n+\n+\t/* free pre stored skb from done to proc */\n+\twhile (proc_idx != done_idx) {\n+\t\t/* get cmdsts */\n+\t\tval = ave_rdesc(ndev, AVE_DESCID_TX, done_idx, 0);\n+\n+\t\t/* do nothing if owner is HW */\n+\t\tif (val & AVE_STS_OWN)\n+\t\t\tbreak;\n+\n+\t\t/* check Tx status and updates statistics */\n+\t\tif (val & AVE_STS_OK) {\n+\t\t\tpriv->stats.tx_bytes += val & AVE_STS_PKTLEN_TX;\n+\n+\t\t\t/* success */\n+\t\t\tif (val & AVE_STS_LAST)\n+\t\t\t\tpriv->stats.tx_packets++;\n+\t\t} else {\n+\t\t\t/* error */\n+\t\t\tif (val & AVE_STS_LAST) {\n+\t\t\t\tpriv->stats.tx_errors++;\n+\t\t\t\tif (val & (AVE_STS_OWC | AVE_STS_EC))\n+\t\t\t\t\tpriv->stats.collisions++;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* release skb */\n+\t\tif (priv->tx.desc[done_idx].skbs) {\n+\t\t\tave_dma_unmap(ndev, &priv->tx.desc[done_idx],\n+\t\t\t\t      DMA_TO_DEVICE);\n+\t\t\tdev_consume_skb_any(priv->tx.desc[done_idx].skbs);\n+\t\t\tpriv->tx.desc[done_idx].skbs = NULL;\n+\t\t\tfreebuf_flag++;\n+\t\t}\n+\t\tdone_idx = (done_idx + 1) % ndesc;\n+\t}\n+\n+\tpriv->tx.done_idx = done_idx;\n+\n+\t/* wake queue for freeing buffer */\n+\tif (netif_queue_stopped(ndev))\n+\t\tif (netif_running(ndev))\n+\t\t\tif (freebuf_flag)\n+\t\t\t\tnetif_wake_queue(ndev);\n+\n+\treturn freebuf_flag;\n+}\n+\n+static int ave_rx(struct net_device *ndev, int num)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tstruct sk_buff *skb;\n+\tu32 proc_idx, done_idx, ndesc, cmdsts;\n+\tint restpkt, npkts;\n+\tunsigned int pktlen;\n+\n+\tproc_idx = priv->rx.proc_idx;\n+\tdone_idx = priv->rx.done_idx;\n+\tndesc    = priv->rx.ndesc;\n+\trestpkt  = ((proc_idx + ndesc - 1) - done_idx) % ndesc;\n+\n+\tfor (npkts = 0; npkts < num; npkts++) {\n+\t\t/* we can't receive more packet, so fill desc quickly */\n+\t\tif (--restpkt < 0)\n+\t\t\tbreak;\n+\n+\t\tcmdsts = ave_rdesc(ndev, AVE_DESCID_RX, proc_idx, 0);\n+\n+\t\t/* owner is hardware */\n+\t\tif ((cmdsts & AVE_STS_OWN) != AVE_STS_OWN)\n+\t\t\tbreak;\n+\n+\t\tif ((cmdsts & AVE_STS_OK) != AVE_STS_OK) {\n+\t\t\tpriv->stats.rx_errors++;\n+\t\t\tproc_idx = (proc_idx + 1) % ndesc;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tpktlen = cmdsts & AVE_STS_PKTLEN_RX;\n+\n+\t\t/* get skbuff for rx */\n+\t\tskb = priv->rx.desc[proc_idx].skbs;\n+\t\tpriv->rx.desc[proc_idx].skbs = NULL;\n+\n+\t\tave_dma_unmap(ndev, &priv->rx.desc[proc_idx], DMA_FROM_DEVICE);\n+\n+\t\tskb->dev = ndev;\n+\t\tskb_reserve(skb, NET_IP_ALIGN);\n+\t\tskb_put(skb, pktlen);\n+\n+\t\tskb->protocol = eth_type_trans(skb, ndev);\n+\n+\t\tif ((cmdsts & AVE_STS_CSSV) && (!(cmdsts & AVE_STS_CSER)))\n+\t\t\tskb->ip_summed = CHECKSUM_UNNECESSARY;\n+\n+\t\t/* update stats */\n+\t\tpriv->stats.rx_packets++;\n+\t\tpriv->stats.rx_bytes += pktlen;\n+\n+\t\tnetif_receive_skb(skb);\n+\n+\t\tproc_idx = (proc_idx + 1) % ndesc;\n+\t}\n+\n+\tpriv->rx.proc_idx = proc_idx;\n+\n+\t/* refill the Rx buffers */\n+\twhile (proc_idx != done_idx) {\n+\t\tif (ave_set_rxdesc(ndev, done_idx))\n+\t\t\tbreak;\n+\t\tdone_idx = (done_idx + 1) % ndesc;\n+\t}\n+\n+\tpriv->rx.done_idx = done_idx;\n+\n+\treturn npkts;\n+}\n+\n+static inline u32 ave_irq_disable_all(struct net_device *ndev)\n+{\n+\tu32 ret;\n+\n+\tret = ave_r32(ndev, AVE_GIMR);\n+\tave_w32(ndev, AVE_GIMR, 0);\n+\n+\treturn ret;\n+}\n+\n+static inline void ave_irq_restore(struct net_device *ndev, u32 val)\n+{\n+\tave_w32(ndev, AVE_GIMR, val);\n+}\n+\n+static inline void ave_irq_enable(struct net_device *ndev, u32 bitflag)\n+{\n+\tave_w32(ndev, AVE_GIMR, ave_r32(ndev, AVE_GIMR) | bitflag);\n+\tave_w32(ndev, AVE_GISR, bitflag);\n+}\n+\n+static inline void ave_irq_disable(struct net_device *ndev, u32 bitflag)\n+{\n+\tave_w32(ndev, AVE_GIMR, ave_r32(ndev, AVE_GIMR) & ~bitflag);\n+}\n+\n+static void ave_global_reset(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 grr, descc;\n+\tu32 val;\n+\n+\tgrr = ave_r32(ndev, AVE_GRR);\n+\tif ((grr & AVE_GRR_GRST) != AVE_GRR_GRST) {\n+\t\tdescc = ave_r32(ndev, AVE_DESCC);\n+\t\tif ((descc & AVE_DESCC_RD0) == AVE_DESCC_RD0)\n+\t\t\t/* suspend Rx descriptor */\n+\t\t\tave_desc_switch(ndev, AVE_DESC_RX_SUSPEND);\n+\t}\n+\n+\t/* set config register */\n+\tval = AVE_CFGR_FLE | AVE_CFGR_IPFCEN | AVE_CFGR_CHE;\n+\tif (priv->phy_mode != PHY_INTERFACE_MODE_RGMII)\n+\t\tval |= AVE_CFGR_MII;\n+\tave_w32(ndev, AVE_CFGR, val);\n+\n+\t/* reset RMII register */\n+\tval = ave_r32(ndev, AVE_RSTCTRL);\n+\tval &= ~AVE_RSTCTRL_RMIIRST;\n+\tave_w32(ndev, AVE_RSTCTRL, val);\n+\n+\t/* assert reset */\n+\tave_w32(ndev, AVE_GRR, AVE_GRR_GRST | AVE_GRR_PHYRST);\n+\tmsleep(20);\n+\n+\t/* 1st, negate PHY reset only */\n+\tave_w32(ndev, AVE_GRR, AVE_GRR_GRST);\n+\tmsleep(40);\n+\n+\t/* negate reset */\n+\tave_w32(ndev, AVE_GRR, 0);\n+\tmsleep(40);\n+\n+\t/* negate RMII register */\n+\tval = ave_r32(ndev, AVE_RSTCTRL);\n+\tval |= AVE_RSTCTRL_RMIIRST;\n+\tave_w32(ndev, AVE_RSTCTRL, val);\n+\n+\t/* disable all interrupt */\n+\tave_irq_disable_all(ndev);\n+}\n+\n+static void ave_rxf_reset(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 rxcr_org;\n+\n+\t/* save and disable MAC receive op */\n+\trxcr_org = ave_r32(ndev, AVE_RXCR);\n+\tave_w32(ndev, AVE_RXCR, rxcr_org & (~AVE_RXCR_RXEN));\n+\n+\t/* suspend Rx descriptor */\n+\tave_desc_switch(ndev, AVE_DESC_RX_SUSPEND);\n+\n+\t/* receive all packets before descriptor starts */\n+\tave_rx(ndev, priv->rx.ndesc);\n+\n+\t/* assert reset */\n+\tave_w32(ndev, AVE_GRR, AVE_GRR_RXFFR);\n+\tusleep_range(40, 50);\n+\n+\t/* negate reset */\n+\tave_w32(ndev, AVE_GRR, 0);\n+\tusleep_range(10, 20);\n+\n+\t/* negate interrupt status */\n+\tave_w32(ndev, AVE_GISR, AVE_GI_RXOVF);\n+\n+\t/* permit descriptor */\n+\tave_desc_switch(ndev, AVE_DESC_RX_PERMIT);\n+\n+\t/* restore MAC reccieve op */\n+\tave_w32(ndev, AVE_RXCR, rxcr_org);\n+}\n+\n+static irqreturn_t ave_interrupt(int irq, void *netdev)\n+{\n+\tstruct net_device *ndev = (struct net_device *)netdev;\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 gimr_val, gisr_val;\n+\n+\tgimr_val = ave_irq_disable_all(ndev);\n+\n+\t/* get interrupt status */\n+\tgisr_val = ave_r32(ndev, AVE_GISR);\n+\n+\t/* PHY */\n+\tif (gisr_val & AVE_GI_PHY) {\n+\t\tave_w32(ndev, AVE_GISR, AVE_GI_PHY);\n+\t\tif (priv->internal_phy_interrupt)\n+\t\t\tphy_mac_interrupt(ndev->phydev, ndev->phydev->link);\n+\t}\n+\n+\t/* check exceeding packet */\n+\tif (gisr_val & AVE_GI_RXERR) {\n+\t\tave_w32(ndev, AVE_GISR, AVE_GI_RXERR);\n+\t\tnetdev_err(ndev, \"receive a packet exceeding frame buffer\\n\");\n+\t}\n+\n+\tgisr_val &= gimr_val;\n+\tif (!gisr_val)\n+\t\tgoto exit_isr;\n+\n+\t/* RxFIFO overflow */\n+\tif (gisr_val & AVE_GI_RXOVF) {\n+\t\tpriv->stats.rx_fifo_errors++;\n+\t\tave_rxf_reset(ndev);\n+\t\tgoto exit_isr;\n+\t}\n+\n+\t/* Rx drop */\n+\tif (gisr_val & AVE_GI_RXDROP) {\n+\t\tpriv->stats.rx_dropped++;\n+\t\tave_w32(ndev, AVE_GISR, AVE_GI_RXDROP);\n+\t}\n+\n+\t/* Rx interval */\n+\tif (gisr_val & AVE_GI_RXIINT) {\n+\t\tnapi_schedule(&priv->napi_rx);\n+\t\t/* still force to disable Rx interrupt until NAPI finishes */\n+\t\tgimr_val &= ~AVE_GI_RXIINT;\n+\t}\n+\n+\t/* Tx completed */\n+\tif (gisr_val & AVE_GI_TX) {\n+\t\tnapi_schedule(&priv->napi_tx);\n+\t\t/* still force to disable Tx interrupt until NAPI finishes */\n+\t\tgimr_val &= ~AVE_GI_TX;\n+\t}\n+\n+exit_isr:\n+\tave_irq_restore(ndev, gimr_val);\n+\n+\treturn IRQ_HANDLED;\n+}\n+\n+static int ave_poll_rx(struct napi_struct *napi, int budget)\n+{\n+\tstruct ave_private *priv;\n+\tstruct net_device *ndev;\n+\tint num;\n+\n+\tpriv = container_of(napi, struct ave_private, napi_rx);\n+\tndev = priv->ndev;\n+\n+\tnum = ave_rx(ndev, budget);\n+\tif (num < budget) {\n+\t\tnapi_complete_done(napi, num);\n+\n+\t\t/* enable Rx interrupt when NAPI finishes */\n+\t\tave_irq_enable(ndev, AVE_GI_RXIINT);\n+\t}\n+\n+\treturn num;\n+}\n+\n+static int ave_poll_tx(struct napi_struct *napi, int budget)\n+{\n+\tstruct ave_private *priv;\n+\tstruct net_device *ndev;\n+\tint num;\n+\n+\tpriv = container_of(napi, struct ave_private, napi_tx);\n+\tndev = priv->ndev;\n+\n+\tnum = ave_tx_completion(ndev);\n+\tif (num < budget) {\n+\t\tnapi_complete(napi);\n+\n+\t\t/* enable Tx interrupt when NAPI finishes */\n+\t\tave_irq_enable(ndev, AVE_GI_TX);\n+\t}\n+\n+\treturn num;\n+}\n+\n+static void ave_pfsel_promisc_set(struct net_device *ndev,\n+\t\t\t\t  unsigned int entry, u32 rxring)\n+{\n+\tif (WARN_ON(entry > AVE_PF_SIZE))\n+\t\treturn;\n+\n+\tave_pfsel_stop(ndev, entry);\n+\n+\t/* set byte mask */\n+\tave_w32(ndev, AVE_PFMBYTE(entry),     0xFFFFFFFF);\n+\tave_w32(ndev, AVE_PFMBYTE(entry) + 4, 0xFFFFFFFF);\n+\n+\t/* set bit mask filter */\n+\tave_w32(ndev, AVE_PFMBIT(entry), 0x0000FFFF);\n+\n+\t/* set selector to rxring */\n+\tave_w32(ndev, AVE_PFSEL(entry), rxring);\n+\n+\tave_pfsel_start(ndev, entry);\n+}\n+\n+static void ave_pfsel_init(struct net_device *ndev)\n+{\n+\tint i;\n+\tunsigned char bcast_mac[ETH_ALEN];\n+\n+\teth_broadcast_addr(bcast_mac);\n+\n+\t/* Stop all filter */\n+\tfor (i = 0; i < AVE_PF_SIZE; i++)\n+\t\tave_pfsel_stop(ndev, i);\n+\n+\t/* promiscious entry, select ring 0 */\n+\tave_pfsel_promisc_set(ndev, AVE_PFNUM_FILTER, 0);\n+\n+\t/* unicast entry */\n+\tave_pfsel_macaddr_set(ndev, AVE_PFNUM_UNICAST, ndev->dev_addr, 6);\n+\n+\t/* broadcast entry */\n+\tave_pfsel_macaddr_set(ndev, AVE_PFNUM_BROADCAST, bcast_mac, 6);\n+}\n+\n+static void ave_adjust_link(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tstruct phy_device *phydev = ndev->phydev;\n+\tu32 val, txcr, rxcr, rxcr_org;\n+\n+\t/* set RGMII speed */\n+\tval = ave_r32(ndev, AVE_TXCR);\n+\tval &= ~(AVE_TXCR_TXSPD_100 | AVE_TXCR_TXSPD_1G);\n+\n+\tif (priv->phy_mode == PHY_INTERFACE_MODE_RGMII &&\n+\t    phydev->speed == SPEED_1000)\n+\t\tval |= AVE_TXCR_TXSPD_1G;\n+\telse if (phydev->speed == SPEED_100)\n+\t\tval |= AVE_TXCR_TXSPD_100;\n+\n+\tave_w32(ndev, AVE_TXCR, val);\n+\n+\t/* set RMII speed (100M/10M only) */\n+\tif (priv->phy_mode != PHY_INTERFACE_MODE_RGMII) {\n+\t\tval = ave_r32(ndev, AVE_LINKSEL);\n+\t\tif (phydev->speed == SPEED_10)\n+\t\t\tval &= ~AVE_LINKSEL_100M;\n+\t\telse\n+\t\t\tval |= AVE_LINKSEL_100M;\n+\t\tave_w32(ndev, AVE_LINKSEL, val);\n+\t}\n+\n+\t/* check current RXCR/TXCR */\n+\trxcr = ave_r32(ndev, AVE_RXCR);\n+\ttxcr = ave_r32(ndev, AVE_TXCR);\n+\trxcr_org = rxcr;\n+\n+\tif (phydev->duplex)\n+\t\trxcr |= AVE_RXCR_FDUPEN;\n+\telse\n+\t\trxcr &= ~AVE_RXCR_FDUPEN;\n+\n+\tif (phydev->pause) {\n+\t\trxcr |= AVE_RXCR_FLOCTR;\n+\t\ttxcr |= AVE_TXCR_FLOCTR;\n+\t} else {\n+\t\trxcr &= ~AVE_RXCR_FLOCTR;\n+\t\ttxcr &= ~AVE_TXCR_FLOCTR;\n+\t}\n+\n+\tif (rxcr_org != rxcr) {\n+\t\t/* disable Rx mac */\n+\t\tave_w32(ndev, AVE_RXCR, rxcr & ~AVE_RXCR_RXEN);\n+\t\t/* change and enable TX/Rx mac */\n+\t\tave_w32(ndev, AVE_TXCR, txcr);\n+\t\tave_w32(ndev, AVE_RXCR, rxcr);\n+\t}\n+\n+\tif (phydev->link)\n+\t\tnetif_carrier_on(ndev);\n+\telse\n+\t\tnetif_carrier_off(ndev);\n+\n+\tphy_print_status(phydev);\n+}\n+\n+static int ave_init(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tstruct device *dev = ndev->dev.parent;\n+\tstruct device_node *phy_node, *np = dev->of_node;\n+\tstruct phy_device *phydev;\n+\tconst void *mac_addr;\n+\tu32 supported;\n+\n+\t/* get mac address */\n+\tmac_addr = of_get_mac_address(np);\n+\tif (mac_addr)\n+\t\tether_addr_copy(ndev->dev_addr, mac_addr);\n+\n+\t/* if the mac address is invalid, use random mac address */\n+\tif (!is_valid_ether_addr(ndev->dev_addr)) {\n+\t\teth_hw_addr_random(ndev);\n+\t\tdev_warn(dev, \"Using random MAC address: %pM\\n\",\n+\t\t\t ndev->dev_addr);\n+\t}\n+\n+\t/* attach PHY with MAC */\n+\tphy_node =  of_get_next_available_child(np, NULL);\n+\tphydev = of_phy_connect(ndev, phy_node,\n+\t\t\t\tave_adjust_link, 0, priv->phy_mode);\n+\tif (!phydev) {\n+\t\tdev_err(dev, \"could not attach to PHY\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\tof_node_put(phy_node);\n+\n+\tpriv->phydev = phydev;\n+\tphydev->autoneg = AUTONEG_ENABLE;\n+\tphydev->speed = 0;\n+\tphydev->duplex = 0;\n+\n+\tdev_info(dev, \"connected to %s phy with id 0x%x\\n\",\n+\t\t phydev->drv->name, phydev->phy_id);\n+\n+\tif (priv->phy_mode != PHY_INTERFACE_MODE_RGMII) {\n+\t\tsupported = phydev->supported;\n+\t\tphydev->supported &= ~PHY_GBIT_FEATURES;\n+\t\tphydev->supported |= supported & PHY_BASIC_FEATURES;\n+\t}\n+\n+\t/* PHY interrupt stop instruction is needed because the interrupt\n+\t * continues to assert.\n+\t */\n+\tphy_stop_interrupts(phydev);\n+\n+\t/* When PHY driver can't handle its interrupt directly,\n+\t * interrupt request always fails and polling method is used\n+\t * alternatively. In this case, the libphy says\n+\t * \"libphy: uniphier-mdio: Can't get IRQ -1 (PHY)\".\n+\t */\n+\tphy_start_interrupts(phydev);\n+\n+\tphy_start_aneg(phydev);\n+\n+\treturn 0;\n+}\n+\n+static void ave_uninit(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\n+\tphy_stop_interrupts(priv->phydev);\n+\tphy_disconnect(priv->phydev);\n+}\n+\n+static int ave_open(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tint entry;\n+\tu32 val;\n+\n+\t/* initialize Tx work */\n+\tpriv->tx.proc_idx = 0;\n+\tpriv->tx.done_idx = 0;\n+\tmemset(priv->tx.desc, 0, sizeof(struct ave_desc) * priv->tx.ndesc);\n+\n+\t/* initialize Tx descriptor */\n+\tfor (entry = 0; entry < priv->tx.ndesc; entry++) {\n+\t\tave_wdesc(ndev, AVE_DESCID_TX, entry, 0, 0);\n+\t\tave_wdesc_addr(ndev, AVE_DESCID_TX, entry, 4, 0);\n+\t}\n+\tave_w32(ndev, AVE_TXDC, AVE_TXDC_ADDR_START\n+\t\t| (((priv->tx.ndesc * priv->desc_size) << 16) & AVE_TXDC_SIZE));\n+\n+\t/* initialize Rx work */\n+\tpriv->rx.proc_idx = 0;\n+\tpriv->rx.done_idx = 0;\n+\tmemset(priv->rx.desc, 0, sizeof(struct ave_desc) * priv->rx.ndesc);\n+\n+\t/* initialize Rx descriptor and buffer */\n+\tfor (entry = 0; entry < priv->rx.ndesc; entry++) {\n+\t\tif (ave_set_rxdesc(ndev, entry))\n+\t\t\tbreak;\n+\t}\n+\tave_w32(ndev, AVE_RXDC0, AVE_RXDC0_ADDR_START\n+\t    | (((priv->rx.ndesc * priv->desc_size) << 16) & AVE_RXDC0_SIZE));\n+\n+\t/* enable descriptor */\n+\tave_desc_switch(ndev, AVE_DESC_START);\n+\n+\t/* initialize filter */\n+\tave_pfsel_init(ndev);\n+\n+\t/* set macaddr */\n+\tval = le32_to_cpu(((u32 *)ndev->dev_addr)[0]);\n+\tave_w32(ndev, AVE_RXMAC1R, val);\n+\tval = (u32)le16_to_cpu(((u16 *)ndev->dev_addr)[2]);\n+\tave_w32(ndev, AVE_RXMAC2R, val);\n+\n+\t/* set Rx configuration */\n+\t/* full duplex, enable pause drop, enalbe flow control */\n+\tval = AVE_RXCR_RXEN | AVE_RXCR_FDUPEN | AVE_RXCR_DRPEN |\n+\t\tAVE_RXCR_FLOCTR | (AVE_MAX_ETHFRAME & AVE_RXCR_MPSIZ_MASK);\n+\tave_w32(ndev, AVE_RXCR, val);\n+\n+\t/* set Tx configuration */\n+\t/* enable flow control, disable loopback */\n+\tave_w32(ndev, AVE_TXCR, AVE_TXCR_FLOCTR);\n+\n+\t/* enable timer, clear EN,INTM, and mask interval unit(BSCK) */\n+\tval = ave_r32(ndev, AVE_IIRQC) & AVE_IIRQC_BSCK;\n+\tval |= AVE_IIRQC_EN0 | (AVE_INTM_COUNT << 16);\n+\tave_w32(ndev, AVE_IIRQC, val);\n+\n+\t/* set interrupt mask */\n+\tval = AVE_GI_RXIINT | AVE_GI_RXOVF | AVE_GI_TX;\n+\tval |= (priv->internal_phy_interrupt) ? AVE_GI_PHY : 0;\n+\tave_irq_restore(ndev, val);\n+\n+\tnapi_enable(&priv->napi_rx);\n+\tnapi_enable(&priv->napi_tx);\n+\n+\tphy_start(ndev->phydev);\n+\tnetif_start_queue(ndev);\n+\n+\treturn 0;\n+}\n+\n+static int ave_stop(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tint entry;\n+\n+\t/* disable all interrupt */\n+\tave_irq_disable_all(ndev);\n+\tdisable_irq(ndev->irq);\n+\n+\tnetif_tx_disable(ndev);\n+\tphy_stop(ndev->phydev);\n+\tnapi_disable(&priv->napi_tx);\n+\tnapi_disable(&priv->napi_rx);\n+\n+\t/* free Tx buffer */\n+\tfor (entry = 0; entry < priv->tx.ndesc; entry++) {\n+\t\tif (!priv->tx.desc[entry].skbs)\n+\t\t\tcontinue;\n+\n+\t\tave_dma_unmap(ndev, &priv->tx.desc[entry], DMA_TO_DEVICE);\n+\t\tdev_kfree_skb_any(priv->tx.desc[entry].skbs);\n+\t\tpriv->tx.desc[entry].skbs = NULL;\n+\t}\n+\tpriv->tx.proc_idx = 0;\n+\tpriv->tx.done_idx = 0;\n+\n+\t/* free Rx buffer */\n+\tfor (entry = 0; entry < priv->rx.ndesc; entry++) {\n+\t\tif (!priv->rx.desc[entry].skbs)\n+\t\t\tcontinue;\n+\n+\t\tave_dma_unmap(ndev, &priv->rx.desc[entry], DMA_FROM_DEVICE);\n+\t\tdev_kfree_skb_any(priv->rx.desc[entry].skbs);\n+\t\tpriv->rx.desc[entry].skbs = NULL;\n+\t}\n+\tpriv->rx.proc_idx = 0;\n+\tpriv->rx.done_idx = 0;\n+\n+\treturn 0;\n+}\n+\n+static int ave_start_xmit(struct sk_buff *skb, struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 proc_idx, done_idx, ndesc, cmdsts;\n+\tint freepkt;\n+\tunsigned char *buffptr = NULL; /* buffptr for descriptor */\n+\tunsigned int len;\n+\tdma_addr_t paddr;\n+\n+\tproc_idx = priv->tx.proc_idx;\n+\tdone_idx = priv->tx.done_idx;\n+\tndesc = priv->tx.ndesc;\n+\tfreepkt = ((done_idx + ndesc - 1) - proc_idx) % ndesc;\n+\n+\t/* not enough entry, then we stop queue */\n+\tif (unlikely(freepkt < 2)) {\n+\t\tnetif_stop_queue(ndev);\n+\t\tif (unlikely(freepkt < 1))\n+\t\t\treturn NETDEV_TX_BUSY;\n+\t}\n+\n+\tpriv->tx.desc[proc_idx].skbs = skb;\n+\n+\t/* add padding for short packet */\n+\tif (skb_padto(skb, ETH_ZLEN)) {\n+\t\tdev_kfree_skb_any(skb);\n+\t\treturn NETDEV_TX_OK;\n+\t}\n+\n+\tbuffptr = skb->data - NET_IP_ALIGN;\n+\tlen = max_t(unsigned int, ETH_ZLEN, skb->len);\n+\n+\tpaddr = ave_dma_map(ndev, &priv->tx.desc[proc_idx], buffptr,\n+\t\t\t    len + NET_IP_ALIGN, DMA_TO_DEVICE);\n+\tpaddr += NET_IP_ALIGN;\n+\n+\t/* set buffer address to descriptor */\n+\tave_wdesc_addr(ndev, AVE_DESCID_TX, proc_idx, 4, paddr);\n+\n+\t/* set flag and length to send */\n+\tcmdsts = AVE_STS_OWN | AVE_STS_1ST | AVE_STS_LAST\n+\t\t| (len & AVE_STS_PKTLEN_TX);\n+\n+\t/* set interrupt per AVE_FORCE_TXINTCNT or when queue is stopped */\n+\tif (!(proc_idx % AVE_FORCE_TXINTCNT) || netif_queue_stopped(ndev))\n+\t\tcmdsts |= AVE_STS_INTR;\n+\n+\t/* disable checksum calculation when skb doesn't calurate checksum */\n+\tif (skb->ip_summed == CHECKSUM_NONE ||\n+\t    skb->ip_summed == CHECKSUM_UNNECESSARY)\n+\t\tcmdsts |= AVE_STS_NOCSUM;\n+\n+\t/* set cmdsts */\n+\tave_wdesc(ndev, AVE_DESCID_TX, proc_idx, 0, cmdsts);\n+\n+\tpriv->tx.proc_idx = (proc_idx + 1) % ndesc;\n+\n+\treturn NETDEV_TX_OK;\n+}\n+\n+static int ave_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)\n+{\n+\treturn phy_mii_ioctl(ndev->phydev, ifr, cmd);\n+}\n+\n+static void ave_set_rx_mode(struct net_device *ndev)\n+{\n+\tint count, mc_cnt = netdev_mc_count(ndev);\n+\tstruct netdev_hw_addr *hw_adr;\n+\tu32 val;\n+\tu8 v4multi_macadr[6] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };\n+\tu8 v6multi_macadr[6] = { 0x33, 0x00, 0x00, 0x00, 0x00, 0x00 };\n+\n+\t/* MAC addr filter enable for promiscious mode */\n+\tval = ave_r32(ndev, AVE_RXCR);\n+\tif (ndev->flags & IFF_PROMISC || !mc_cnt)\n+\t\tval &= ~AVE_RXCR_AFEN;\n+\telse\n+\t\tval |= AVE_RXCR_AFEN;\n+\tave_w32(ndev, AVE_RXCR, val);\n+\n+\t/* set all multicast address */\n+\tif ((ndev->flags & IFF_ALLMULTI) || (mc_cnt > AVE_PF_MULTICAST_SIZE)) {\n+\t\tave_pfsel_macaddr_set(ndev, AVE_PFNUM_MULTICAST,\n+\t\t\t\t      v4multi_macadr, 1);\n+\t\tave_pfsel_macaddr_set(ndev, AVE_PFNUM_MULTICAST + 1,\n+\t\t\t\t      v6multi_macadr, 1);\n+\t} else {\n+\t\t/* stop all multicast filter */\n+\t\tfor (count = 0; count < AVE_PF_MULTICAST_SIZE; count++)\n+\t\t\tave_pfsel_stop(ndev, AVE_PFNUM_MULTICAST + count);\n+\n+\t\t/* set multicast addresses */\n+\t\tcount = 0;\n+\t\tnetdev_for_each_mc_addr(hw_adr, ndev) {\n+\t\t\tif (count == mc_cnt)\n+\t\t\t\tbreak;\n+\t\t\tave_pfsel_macaddr_set(ndev, AVE_PFNUM_MULTICAST + count,\n+\t\t\t\t\t      hw_adr->addr, 6);\n+\t\t\tcount++;\n+\t\t}\n+\t}\n+}\n+\n+static struct net_device_stats *ave_stats(struct net_device *ndev)\n+{\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\tu32 drop_num = 0;\n+\n+\tpriv->stats.rx_errors = ave_r32(ndev, AVE_BFCR);\n+\n+\tdrop_num += ave_r32(ndev, AVE_RX0OVFFC);\n+\tdrop_num += ave_r32(ndev, AVE_SN5FC);\n+\tdrop_num += ave_r32(ndev, AVE_SN6FC);\n+\tdrop_num += ave_r32(ndev, AVE_SN7FC);\n+\tpriv->stats.rx_dropped = drop_num;\n+\n+\treturn &priv->stats;\n+}\n+\n+static int ave_set_mac_address(struct net_device *ndev, void *p)\n+{\n+\tint ret = eth_mac_addr(ndev, p);\n+\tu32 val;\n+\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* set macaddr */\n+\tval = le32_to_cpu(((u32 *)ndev->dev_addr)[0]);\n+\tave_w32(ndev, AVE_RXMAC1R, val);\n+\tval = (u32)le16_to_cpu(((u16 *)ndev->dev_addr)[2]);\n+\tave_w32(ndev, AVE_RXMAC2R, val);\n+\n+\t/* pfsel unicast entry */\n+\tave_pfsel_macaddr_set(ndev, AVE_PFNUM_UNICAST, ndev->dev_addr, 6);\n+\n+\treturn 0;\n+}\n+\n+static const struct net_device_ops ave_netdev_ops = {\n+\t.ndo_init\t\t= ave_init,\n+\t.ndo_uninit\t\t= ave_uninit,\n+\t.ndo_open\t\t= ave_open,\n+\t.ndo_stop\t\t= ave_stop,\n+\t.ndo_start_xmit\t\t= ave_start_xmit,\n+\t.ndo_do_ioctl\t\t= ave_ioctl,\n+\t.ndo_set_rx_mode\t= ave_set_rx_mode,\n+\t.ndo_get_stats\t\t= ave_stats,\n+\t.ndo_set_mac_address\t= ave_set_mac_address,\n+};\n+\n+static int ave_probe(struct platform_device *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct device_node *np = dev->of_node;\n+\tu32 desc_bits, ave_id;\n+\tstruct reset_control *rst;\n+\tstruct ave_private *priv;\n+\tphy_interface_t phy_mode;\n+\tstruct net_device *ndev;\n+\tstruct resource\t*res;\n+\tvoid __iomem *base;\n+\tint irq, ret = 0;\n+\tchar buf[ETHTOOL_FWVERS_LEN];\n+\n+\t/* get phy mode */\n+\tphy_mode = of_get_phy_mode(np);\n+\tif (phy_mode < 0) {\n+\t\tdev_err(dev, \"phy-mode not found\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tirq = platform_get_irq(pdev, 0);\n+\tif (irq < 0) {\n+\t\tdev_err(dev, \"IRQ not found\\n\");\n+\t\treturn irq;\n+\t}\n+\n+\tres = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n+\tbase = devm_ioremap_resource(dev, res);\n+\tif (IS_ERR(base))\n+\t\treturn PTR_ERR(base);\n+\n+\t/* alloc netdevice */\n+\tndev = alloc_etherdev(sizeof(struct ave_private));\n+\tif (!ndev) {\n+\t\tdev_err(dev, \"can't allocate ethernet device\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tndev->base_addr = (unsigned long)base;\n+\tndev->irq = irq;\n+\tndev->netdev_ops = &ave_netdev_ops;\n+\tndev->ethtool_ops = &ave_ethtool_ops;\n+\tSET_NETDEV_DEV(ndev, dev);\n+\n+\t/* support hardware checksum */\n+\tndev->features    |= (NETIF_F_IP_CSUM | NETIF_F_RXCSUM);\n+\tndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_RXCSUM);\n+\n+\tndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN);\n+\n+\tpriv = netdev_priv(ndev);\n+\tpriv->ndev = ndev;\n+\tpriv->msg_enable = netif_msg_init(-1, AVE_DEFAULT_MSG_ENABLE);\n+\tpriv->phy_mode = phy_mode;\n+\n+\t/* get bits of descriptor from devicetree */\n+\tof_property_read_u32(np, \"socionext,desc-bits\", &desc_bits);\n+\tpriv->desc_size = AVE_DESC_SIZE_32;\n+\tif (desc_bits == 64)\n+\t\tpriv->desc_size = AVE_DESC_SIZE_64;\n+\telse if (desc_bits != 32)\n+\t\tdev_warn(dev, \"Defaulting to 32bit descriptor\\n\");\n+\n+\t/* use internal phy interrupt */\n+\tpriv->internal_phy_interrupt =\n+\t\tof_property_read_bool(np, \"socionext,internal-phy-interrupt\");\n+\n+\t/* setting private data for descriptor */\n+\tpriv->tx.daddr = IS_DESC_64BIT(priv) ? AVE_TXDM_64 : AVE_TXDM_32;\n+\tpriv->tx.ndesc = AVE_NR_TXDESC;\n+\tpriv->tx.desc = devm_kzalloc(dev,\n+\t\t\t\t     sizeof(struct ave_desc) * priv->tx.ndesc,\n+\t\t\t\t     GFP_KERNEL);\n+\tif (!priv->tx.desc)\n+\t\treturn -ENOMEM;\n+\n+\tpriv->rx.daddr = IS_DESC_64BIT(priv) ? AVE_RXDM_64 : AVE_RXDM_32;\n+\tpriv->rx.ndesc = AVE_NR_RXDESC;\n+\tpriv->rx.desc = devm_kzalloc(dev,\n+\t\t\t\t     sizeof(struct ave_desc) * priv->rx.ndesc,\n+\t\t\t\t     GFP_KERNEL);\n+\tif (!priv->rx.desc)\n+\t\treturn -ENOMEM;\n+\n+\t/* enable clock */\n+\tpriv->clk = devm_clk_get(dev, NULL);\n+\tif (IS_ERR(priv->clk))\n+\t\tpriv->clk = NULL;\n+\tclk_prepare_enable(priv->clk);\n+\n+\t/* reset block */\n+\trst = devm_reset_control_get(dev, NULL);\n+\tif (!IS_ERR_OR_NULL(rst)) {\n+\t\treset_control_deassert(rst);\n+\t\treset_control_put(rst);\n+\t}\n+\n+\t/* reset mac and phy */\n+\tave_global_reset(ndev);\n+\n+\t/* request interrupt */\n+\tret = devm_request_irq(dev, irq, ave_interrupt,\n+\t\t\t       IRQF_SHARED, ndev->name, ndev);\n+\tif (ret)\n+\t\tgoto err_req_irq;\n+\n+\t/* create MDIO bus */\n+\tpriv->mdio = devm_mdiobus_alloc(dev);\n+\tif (!priv->mdio) {\n+\t\tret = -ENOMEM;\n+\t\tgoto err_mdiobus_alloc;\n+\t}\n+\n+\tpriv->mdio->priv = ndev;\n+\tpriv->mdio->parent = dev;\n+\tpriv->mdio->read = ave_mdiobus_read;\n+\tpriv->mdio->write = ave_mdiobus_write;\n+\tpriv->mdio->name = \"uniphier-mdio\";\n+\tsnprintf(priv->mdio->id, MII_BUS_ID_SIZE, \"%s-%x\",\n+\t\t pdev->name, pdev->id);\n+\n+\tret = of_mdiobus_register(priv->mdio, np);\n+\tif (ret) {\n+\t\tdev_err(dev, \"of_mdiobus_register(%s) failed\\n\", np->full_name);\n+\t\tret = -ENOMEM;\n+\t\tgoto err_mdiobus_register;\n+\t}\n+\n+\t/* Register as a NAPI supported driver */\n+\tnetif_napi_add(ndev, &priv->napi_rx, ave_poll_rx, priv->rx.ndesc);\n+\tnetif_tx_napi_add(ndev, &priv->napi_tx, ave_poll_tx, priv->tx.ndesc);\n+\n+\tret = register_netdev(ndev);\n+\tif (ret) {\n+\t\tdev_err(dev, \"failed to register netdevice\\n\");\n+\t\tgoto err_netdev_register;\n+\t}\n+\n+\tplatform_set_drvdata(pdev, ndev);\n+\n+\t/* get ID and version */\n+\tave_id = ave_r32(ndev, AVE_IDR);\n+\tave_get_fwversion(ndev, buf, sizeof(buf));\n+\n+\tdev_info(dev, \"Socionext %c%c%c%c Ethernet IP %s (irq=%d, phy=%s)\\n\",\n+\t\t (ave_id >> 24) & 0xff, (ave_id >> 16) & 0xff,\n+\t\t (ave_id >> 8) & 0xff, (ave_id >> 0) & 0xff,\n+\t\t buf, ndev->irq, phy_modes(phy_mode));\n+\n+\treturn 0;\n+\n+err_netdev_register:\n+\tnetif_napi_del(&priv->napi_rx);\n+\tnetif_napi_del(&priv->napi_tx);\n+\tmdiobus_unregister(priv->mdio);\n+err_mdiobus_register:\n+err_mdiobus_alloc:\n+err_req_irq:\n+\tfree_netdev(ndev);\n+\tclk_disable_unprepare(priv->clk);\n+\n+\treturn ret;\n+}\n+\n+static int ave_remove(struct platform_device *pdev)\n+{\n+\tstruct net_device *ndev = platform_get_drvdata(pdev);\n+\tstruct ave_private *priv = netdev_priv(ndev);\n+\n+\tunregister_netdev(ndev);\n+\tnetif_napi_del(&priv->napi_rx);\n+\tnetif_napi_del(&priv->napi_tx);\n+\tmdiobus_unregister(priv->mdio);\n+\tfree_netdev(ndev);\n+\tclk_disable_unprepare(priv->clk);\n+\n+\treturn 0;\n+}\n+\n+static const struct of_device_id of_ave_match[] = {\n+\t{ .compatible = \"socionext,uniphier-ave4\" },\n+\t{ /* Sentinel */ }\n+};\n+MODULE_DEVICE_TABLE(of, of_ave_match);\n+\n+static struct platform_driver ave_driver = {\n+\t.probe  = ave_probe,\n+\t.remove = ave_remove,\n+\t.driver\t= {\n+\t\t.name = \"ave\",\n+\t\t.of_match_table\t= of_ave_match,\n+\t},\n+};\n+module_platform_driver(ave_driver);\n+\n+MODULE_DESCRIPTION(\"Socionext UniPhier AVE ethernet driver\");\n+MODULE_LICENSE(\"GPL v2\");\n",
    "prefixes": [
        "net-next",
        "2/3"
    ]
}