From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM01-BY2-obe.outbound.protection.outlook.com (mail-by2nam01on0046.outbound.protection.outlook.com [104.47.34.46]) by dpdk.org (Postfix) with ESMTP id 2B1D0728A for ; Fri, 9 Mar 2018 09:43:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=/StdBGRfkjPAvkJCLXsr+2IAwgPNOiSS0hcKxc4F8lw=; b=h+Fpjy98pwE7RUw3Ror+MKfH40KaPYA6COvgS9dRlwjKVJ+HCCa51R+/kmOoVKMmb581XV08Z6eSJQTUwO1jSOjdKRbYHXrw/V/2SJQnv+mLLeEC4+56ZxKbqfxpQ5KTJaXWRN0s/y2npclARBe9HsGAakBgAuAGT78mCkZouek= Received: from wallaby-smavila.amd.com (202.56.249.162) by MWHPR12MB1517.namprd12.prod.outlook.com (2603:10b6:301:b::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.567.12; Fri, 9 Mar 2018 08:43:06 +0000 From: Ravi Kumar To: dev@dpdk.org Cc: ferruh.yigit@intel.com Date: Fri, 9 Mar 2018 03:42:21 -0500 Message-Id: <1520584954-130575-5-git-send-email-Ravi1.kumar@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520584954-130575-1-git-send-email-Ravi1.kumar@amd.com> References: <1515145938-97474-1-git-send-email-Ravi1.kumar@amd.com> <1520584954-130575-1-git-send-email-Ravi1.kumar@amd.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [202.56.249.162] X-ClientProxiedBy: BM1PR0101CA0057.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00:19::19) To MWHPR12MB1517.namprd12.prod.outlook.com (2603:10b6:301:b::21) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 06a035f0-4bbc-44be-244d-08d58599c833 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(48565401081)(5600026)(4604075)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060)(7193020); SRVR:MWHPR12MB1517; X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1517; 3:yfEOnbJKrg59v/vISHGfcFHxUAxvg7bXP0uvr0wwixQWQ10GDpSEHifcfZeSGyCR/afwQp5RvlKYUXY+Iq50/UxbnC+xquzw22zJtYp123twWwJt+nGEgQXNgQ02QSdE9WEsq0kaqn1xZfulfEyyWjBFd2qrANPtLmolblgYfwAssLzXZOxFdjTpZdHBcNnwioVHG2UAYwXlExgd9epquVnZUf6VtVre6BEAwpPdN85N9eexSrknPwoR9nepvjMz; 25:LYls+EcD1yuuiw9/rEBmijgxPqzOhJ+vXmWimc6zbmGSJVCIvbpQ/AncZaHF1TfBjljjU3dd4/ECzJ3/vXt6VYtNu6NPrMbgepINxZlyTnaynINLaM9+ve4//lBBaTg/fkV4lu5q9EYkMXgPNk9dxfZoumxdTOI9fzc+Me6MbpZftGTgnZzXzqyqqGA1qy9e5le7VQ07iMvvTZGeRQGyKtPXwGy7+6V2y/TaJAJoJbM75aomajY286iLNV64vQI8gnIceBg3S7tTfIDAIcYwKx4pE8m6DupWYZi5l7tFow5pv29j2cjA1j6lEd+gu+ii2kdHPDRzoYYTblE+wdg7KA==; 31:FsrJSaWPS0kXVFfjqk83hzJ4dHYKLV1tFhvsd1gLv6R2ES032WjpgpzhJK43t3bjvrhtbRqDg8Ki/mtwY+JIP1y6W3Y0Jw538+B0A8+M2236pECaEtm67lYS9Cxw/qDV4rbnfRTFkVJ2ocK7NFYsxloKuZI1+sw1oowRGuDwbn5aaXkNsMhzUv99tdFKzpiFlFzaNb9ulIRtF1DM9atr1nAu5NehW/m8oN2/GmEcWmc= X-MS-TrafficTypeDiagnostic: MWHPR12MB1517: X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1517; 20:eC/1CtPXacHc+YmhJXtWLAjwALsFL5ArGm1kS9d1SuBieeFBcHCHm9Zs2UjrEOaaJDal7OmM5rScWeFnwV3qd7Tc8Z31KeHwUS3Hs/g5OkkQTeJyZAJ9oNRKrTpdDitz+I9Cxsjrl2QX16rjH6ATH7+P49E6ZpAAj7wNgvgYKGPDFh2D/LfXwgpaiC55n3/dXl4ZRkFf0JPgSF8sdtFTf0qxBe8KE2EbP2eqDkMnxf/kY/rWk1xcOFBNEFb5WC8XIoN+pbnVUJFcycINB0A1apc1B86Dg0ezSzIsc0jhEj2avn+tVZ+BHiTZ7bO+4VgWzPUof5xlr7zE+4WVUZpeOhAcQRN16e99XFdFhL7VQDGuSxhPlnSWrUO63xvWcs4VgwUFSSK71x/KE/qIg/y9HvwB61U9sCwXwfISi55x+52KujYgvbWN9EJ7ttTej/kerw3bgRHhUni+qnErAqshVSB8JE80srk03ROw51LfjQkKqo+uuYFY1UqElckwc26U; 4:BOBI63zbqOubzvL7Ei8W06K9rNHm7I0KNf8B360s19L17aFQyEbX2Ol3Q4GxZRmXUabmRyhnx/Jtast56FyXVgAY4AW/g4hw60fuRvzDW1Nhg7SLj8UgOymMkTO3OmSrScpquQgrHXnPfSrGi5ZzcpH+iNTF8APZtuDWoyrlJ+cRH6mHdBeenctMY8SXC643XVBrcSM56CCzGB6iccd8h7PBIpuz37VXgcMzKCGUYwLZZrPZnObAbkpJaD9v/pAmzG0mr+mwnU/6f1kWznKmSqcS1787Qmyfo+3ivuzDI5QB7Spm2h6VmDjbTt1BnAe9gGH0x7Akgt+SHf9NX+7naVmB+K2KSGSpKnAeFipuVF5Td2f9D5szz0tCd20eKXow X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(22074186197030)(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(10201501046)(93006095)(93001095)(3231220)(944501244)(52105095)(6055026)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123562045)(20161123560045)(20161123564045)(6072148)(201708071742011); SRVR:MWHPR12MB1517; BCL:0; PCL:0; RULEID:; SRVR:MWHPR12MB1517; X-Forefront-PRVS: 0606BBEB39 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(39380400002)(396003)(39860400002)(366004)(376002)(199004)(189003)(305945005)(50226002)(386003)(6346003)(26005)(36756003)(97736004)(25786009)(7736002)(50466002)(8936002)(4326008)(16586007)(86362001)(81156014)(81166006)(6666003)(2950100002)(6916009)(16526019)(186003)(5660300001)(59450400001)(316002)(8676002)(575784001)(76176011)(52116002)(51416003)(7696005)(53416004)(48376002)(6306002)(478600001)(106356001)(6116002)(3846002)(68736007)(2351001)(2906002)(6486002)(66066001)(47776003)(105586002)(53946003)(16200700003)(72206003)(53936002)(2361001)(2004002)(559001)(569006); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR12MB1517; H:wallaby-smavila.amd.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Ravi1.Kumar@amd.com; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; MWHPR12MB1517; 23:/oM2QdbOWla4LHPK48SRO3VgpYVShYExLBYFlPpCk?= =?us-ascii?Q?iEM3NhzzO4PNnLDglnxnj6oH7FleqGtyMwmBb7lProDzDjgHxkV04hVEjVxg?= =?us-ascii?Q?Fu9Npzx5zVHJvefvzBhJGpbA54tIxSoA3IUZhbqR9Jqr/gVxHESZYKG1nuk4?= =?us-ascii?Q?STeCbP32LyCSloYMzmi62RzShb8YwVEg1/3XsK24jMVgfuUE1s1YQ/t9YW6R?= =?us-ascii?Q?umJt/Wl8iXDmaL6aNPORhmNT8NUcbfsc+C1Z8V27NPhQQ61ANML4JeQQDYFK?= =?us-ascii?Q?SVx8C/EYNoP9YnQWHEdn2gr2+Tyd2ZRDeXxge8/ZIfhq5M/Oym3ZaDHYDSVM?= =?us-ascii?Q?w1Q1qTV0N7WVch/xss6FEbWtHAan5YWqLexSy6gK22BkCwuDvwy/r03mEeIk?= =?us-ascii?Q?eHAr2boCFspxkVSLeYbCsNgHaZgvmM08Rz9xy8VffKbRmEzhfGBh9L9c1t1g?= =?us-ascii?Q?3mK7hk4usfL2VCpvlJ2EBQ1GDduSCbhLp3Mkto3Fq4xiuG9FzIXDBACUw4mv?= =?us-ascii?Q?x4lFPucBvx9alzQL4nPM6Ii3SB6pkF7rrGEZN/EGW+D1bwS6X8p3xqJF2O/d?= =?us-ascii?Q?FJnHApjxJQkhHJ34bkXMhCENzv96GtwKnwggYVAEUTpa7oirPlhXjlvDLnB9?= =?us-ascii?Q?pJ7Cv7g/1Zxwu7yTCfBlxo1+FvWqYfmcM7nmt3/3hhcGBXYqB12jzhHu9n1j?= =?us-ascii?Q?7663NBWoF7Y2kJOP3jZmXUob/tRVEdy8QYfalCZxZJuCFpVvFI0YocWm3+Z4?= =?us-ascii?Q?tbHIJoxBgsDzKMicMXop3gN3e2N9p3BsLDwrh9v9mUFwLJfuu9t9CtL4bt+v?= =?us-ascii?Q?Kp+hbFCazgNtgusMdVEgzdwUnUWrCDXpkFgkSUZ/XWGlFGY19V7SXnyJMu2/?= =?us-ascii?Q?u7oAW7jykcUkPDrWj/Q37/5e20+qcv1qlSU8ig8ptmQw+IjnfE9CP16B87Lh?= =?us-ascii?Q?ZE51j/0vlh17DK952rDQhyL7y+vF2NxCvxYRLDqqp3NthTd/BFnn+MIzJn6p?= =?us-ascii?Q?HY8kcN0/yhk7i+Dk/qATv4Hww1lT9ylfX+3SgvE54FAA0/V1m4hWi+ZMSx8G?= =?us-ascii?Q?+OGWbg0rv06hJvhL+CB/pbtK8POabEg6q41lg8cgH3tFFopCOr9/BR6XbgRd?= =?us-ascii?Q?InwKIc+XubHrZpElIknTBI+HtWhGtYTlNlat2pEbPrtnuak8OQvZYZmImlxI?= =?us-ascii?Q?J6yV9AmOxRdrthjMgF2kGzAxXEKHXHSQuxnihRSjLXmAHSSdzoqeI7CoQ5ax?= =?us-ascii?Q?MJD7KLbteABRlsQl8JMpsawaYVprPhV+SWVyYy5TkFaqjzNnvIDQdmEzy6nS?= =?us-ascii?Q?zXZi5lFG2tSFB3JUTsJ+e1lyNOlMWgO/v/epuJJGGP9CvTnaxyR81v4fA5n1?= =?us-ascii?Q?Q7Pyw=3D=3D?= X-Microsoft-Antispam-Message-Info: 2tqPYWUoPbqdmb5WN6Kq7LAmYTktlu+R6vmkw1XUvpnO8+mqQTuW0fsu9DhpnA+FJmsKqBbbQv7nCbLV43a6zm09QsmL7bmfOHYB/2IF12alnO8IEncyxZ03AzAFI/KMuN0RoEEHcZ5WoosDmkOt+lZV3L4i/zT2TRAaXyiD8/FsD+YVJIWyPkcKSIK6zdad X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1517; 6:MhwFKWEVDT+Wz50QaINMLn8MH0YSqEZhGIBeM0T0UqhX16KSH882BGuEScfH9ch8UihlbuPoURUSyxxtn93a6/WRkRn2SOJhjmsYveGIQH/PL9s2R5aNqHNVCijNkT0TcpSPhoCXn96IkpcQvsV71eCLNXFrstDD+BsvtD6w/KZ4Quhw0Cl/ihpndXFXI7AXzAmDxTk2Kh+Xv+fvBlH89YpdDmWMffJGfHPEKNmz+zEXb20SeWTrnGLWyOl32IWCchIbKf8vzJU1wEgYRlFwidhaN+TM82PMt7RNLRzYM3BGv5AXWFJPhpgtCluxLPSTzPPtdnXZ27Wccq35PBE0lWPXldTFLxijtIJykqAnzmk=; 5:c3DuGCWzNU3qBk/BctJaD9GOzucbfi9kwyMr2I9sqow9jdIyPkWPzMt1G4bnQl5M5lAnfxFixVK45I0zFE3K/gGA3Tt7tTh56hgVCDW8OiQuCO5QJoccDuO572eMES9ltzsd7u9V5gEOdb1ludyTqICE9xg2ZEn+ecKlrwbFotc=; 24:BnhEwQVO1VjWwBH64iQlF49OaOhGjYfb09rE8b+l+IOUvjCMURK/pLOKi0wwxFdxftFs+yhSz5ve3VhkDEJkxE1r6LRnM6T6xbxbrNZ2hNE=; 7:Eu6KrEjdPDOqU6qh9Y5nVvLdjt8aVbWIbGG8dTBzChtrma5ZV5SIVD9nKl4Y0umN2kS8O0xS5pKkQwaKlahql6XaT4fGFFlSAW4nF81ZG1W1BhluTZh6cect7ggPzlbv81pWZNOr2GcJN8BGpSd8qxZFDE6tUoyYtDdEL864+E2WeyUm1sx+V/7tEyY4Q87SHlgjEkgwgKEAb8pQ69usa6ilMcjxfijVlgfqUD7gvb9la2NBcuPPkFyJ7pGeVCXF SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1517; 20:rRAgYry/BIhg9IVuFdTlZL6mBXMuDgNAtcgecaveceS4EFQQOG8fKqImNhCWgQTFO62n/9MXvH846wIIkPwGPaVQPGmOyLNHl2ci6YXQdaQUyLaGspWZ5zO2Flvi9R5mqZv8M9tXKEbxHuQnR8oquCDcLt8pmsLs6qjmT4DygFrsvjzxNRxtzzBWMSwdufOxRxuryq5e47NpwaARHXjDvEQrYeBwx6qLiy/iketo5Mp1cSAMxYtqmJTTlAhcyURY X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Mar 2018 08:43:06.8234 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 06a035f0-4bbc-44be-244d-08d58599c833 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR12MB1517 Subject: [dpdk-dev] [PATCH v3 05/18] net/axgbe: add phy initialization and related apis X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Mar 2018 08:43:11 -0000 Signed-off-by: Ravi Kumar --- drivers/net/axgbe/Makefile | 3 + drivers/net/axgbe/axgbe_dev.c | 188 +++++++++ drivers/net/axgbe/axgbe_ethdev.c | 11 + drivers/net/axgbe/axgbe_ethdev.h | 172 ++++++++ drivers/net/axgbe/axgbe_i2c.c | 453 +++++++++++++++++++++ drivers/net/axgbe/axgbe_mdio.c | 203 ++++++++++ drivers/net/axgbe/axgbe_phy_impl.c | 799 +++++++++++++++++++++++++++++++++++++ 7 files changed, 1829 insertions(+) create mode 100644 drivers/net/axgbe/axgbe_i2c.c create mode 100644 drivers/net/axgbe/axgbe_mdio.c create mode 100644 drivers/net/axgbe/axgbe_phy_impl.c diff --git a/drivers/net/axgbe/Makefile b/drivers/net/axgbe/Makefile index ce2485d..a8f3358 100644 --- a/drivers/net/axgbe/Makefile +++ b/drivers/net/axgbe/Makefile @@ -143,5 +143,8 @@ LIBABIVER := 1 # SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_dev.c +SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_mdio.c +SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_phy_impl.c +SRCS-$(CONFIG_RTE_LIBRTE_AXGBE_PMD) += axgbe_i2c.c include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c index 8bf3b82..90a99c4 100644 --- a/drivers/net/axgbe/axgbe_dev.c +++ b/drivers/net/axgbe/axgbe_dev.c @@ -129,6 +129,187 @@ #include "axgbe_common.h" #include "axgbe_phy.h" +/* query busy bit */ +static int mdio_complete(struct axgbe_port *pdata) +{ + if (!AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, BUSY)) + return 1; + + return 0; +} + +static int axgbe_write_ext_mii_regs(struct axgbe_port *pdata, int addr, + int reg, u16 val) +{ + unsigned int mdio_sca, mdio_sccd; + uint64_t timeout; + + mdio_sca = 0; + AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg); + AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr); + AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); + + mdio_sccd = 0; + AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val); + AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1); + AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1); + AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd); + + timeout = rte_get_timer_cycles() + rte_get_timer_hz(); + while (time_before(rte_get_timer_cycles(), timeout)) { + rte_delay_us(100); + if (mdio_complete(pdata)) + return 0; + } + + PMD_DRV_LOG(ERR, "Mdio write operation timed out"); + return -ETIMEDOUT; +} + +static int axgbe_read_ext_mii_regs(struct axgbe_port *pdata, int addr, + int reg) +{ + unsigned int mdio_sca, mdio_sccd; + uint64_t timeout; + + mdio_sca = 0; + AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg); + AXGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr); + AXGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca); + + mdio_sccd = 0; + AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3); + AXGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1); + AXGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd); + + timeout = rte_get_timer_cycles() + rte_get_timer_hz(); + + while (time_before(rte_get_timer_cycles(), timeout)) { + rte_delay_us(100); + if (mdio_complete(pdata)) + goto success; + } + + PMD_DRV_LOG(ERR, "Mdio read operation timed out"); + return -ETIMEDOUT; + +success: + return AXGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA); +} + +static int axgbe_set_ext_mii_mode(struct axgbe_port *pdata, unsigned int port, + enum axgbe_mdio_mode mode) +{ + unsigned int reg_val = 0; + + switch (mode) { + case AXGBE_MDIO_MODE_CL22: + if (port > AXGMAC_MAX_C22_PORT) + return -EINVAL; + reg_val |= (1 << port); + break; + case AXGBE_MDIO_MODE_CL45: + break; + default: + return -EINVAL; + } + AXGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val); + + return 0; +} + +static int axgbe_read_mmd_regs_v2(struct axgbe_port *pdata, + int prtad __rte_unused, int mmd_reg) +{ + unsigned int mmd_address, index, offset; + int mmd_data; + + if (mmd_reg & MII_ADDR_C45) + mmd_address = mmd_reg & ~MII_ADDR_C45; + else + mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); + + /* The PCS registers are accessed using mmio. The underlying + * management interface uses indirect addressing to access the MMD + * register sets. This requires accessing of the PCS register in two + * phases, an address phase and a data phase. + * + * The mmio interface is based on 16-bit offsets and values. All + * register offsets must therefore be adjusted by left shifting the + * offset 1 bit and reading 16 bits of data. + */ + mmd_address <<= 1; + index = mmd_address & ~pdata->xpcs_window_mask; + offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); + + pthread_mutex_lock(&pdata->xpcs_mutex); + + XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index); + mmd_data = XPCS16_IOREAD(pdata, offset); + + pthread_mutex_unlock(&pdata->xpcs_mutex); + + return mmd_data; +} + +static void axgbe_write_mmd_regs_v2(struct axgbe_port *pdata, + int prtad __rte_unused, + int mmd_reg, int mmd_data) +{ + unsigned int mmd_address, index, offset; + + if (mmd_reg & MII_ADDR_C45) + mmd_address = mmd_reg & ~MII_ADDR_C45; + else + mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff); + + /* The PCS registers are accessed using mmio. The underlying + * management interface uses indirect addressing to access the MMD + * register sets. This requires accessing of the PCS register in two + * phases, an address phase and a data phase. + * + * The mmio interface is based on 16-bit offsets and values. All + * register offsets must therefore be adjusted by left shifting the + * offset 1 bit and writing 16 bits of data. + */ + mmd_address <<= 1; + index = mmd_address & ~pdata->xpcs_window_mask; + offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask); + + pthread_mutex_lock(&pdata->xpcs_mutex); + + XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index); + XPCS16_IOWRITE(pdata, offset, mmd_data); + + pthread_mutex_unlock(&pdata->xpcs_mutex); +} + +static int axgbe_read_mmd_regs(struct axgbe_port *pdata, int prtad, + int mmd_reg) +{ + switch (pdata->vdata->xpcs_access) { + case AXGBE_XPCS_ACCESS_V1: + PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported "); + return -1; + case AXGBE_XPCS_ACCESS_V2: + default: + return axgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg); + } +} + +static void axgbe_write_mmd_regs(struct axgbe_port *pdata, int prtad, + int mmd_reg, int mmd_data) +{ + switch (pdata->vdata->xpcs_access) { + case AXGBE_XPCS_ACCESS_V1: + PMD_DRV_LOG(ERR, "PHY_Version 1 is not supported "); + return; + case AXGBE_XPCS_ACCESS_V2: + default: + return axgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data); + } +} + static int __axgbe_exit(struct axgbe_port *pdata) { unsigned int count = 2000; @@ -164,4 +345,11 @@ static int axgbe_exit(struct axgbe_port *pdata) void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if) { hw_if->exit = axgbe_exit; + + hw_if->read_mmd_regs = axgbe_read_mmd_regs; + hw_if->write_mmd_regs = axgbe_write_mmd_regs; + + hw_if->set_ext_mii_mode = axgbe_set_ext_mii_mode; + hw_if->read_ext_mii_regs = axgbe_read_ext_mii_regs; + hw_if->write_ext_mii_regs = axgbe_write_ext_mii_regs; } diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c index 786d929..0dc424d 100644 --- a/drivers/net/axgbe/axgbe_ethdev.c +++ b/drivers/net/axgbe/axgbe_ethdev.c @@ -147,6 +147,7 @@ static const struct rte_pci_id pci_id_axgbe_map[] = { }; static struct axgbe_version_data axgbe_v2a = { + .init_function_ptrs_phy_impl = axgbe_init_function_ptrs_phy_v2, .xpcs_access = AXGBE_XPCS_ACCESS_V2, .mmc_64bit = 1, .tx_max_fifo_size = 229376, @@ -157,6 +158,7 @@ static struct axgbe_version_data axgbe_v2a = { }; static struct axgbe_version_data axgbe_v2b = { + .init_function_ptrs_phy_impl = axgbe_init_function_ptrs_phy_v2, .xpcs_access = AXGBE_XPCS_ACCESS_V2, .mmc_64bit = 1, .tx_max_fifo_size = 65536, @@ -271,6 +273,9 @@ static void axgbe_get_all_hw_features(struct axgbe_port *pdata) static void axgbe_init_all_fptrs(struct axgbe_port *pdata) { axgbe_init_function_ptrs_dev(&pdata->hw_if); + axgbe_init_function_ptrs_phy(&pdata->phy_if); + axgbe_init_function_ptrs_i2c(&pdata->i2c_if); + pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if); } static void axgbe_set_counts(struct axgbe_port *pdata) @@ -458,6 +463,12 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev) pthread_mutex_init(&pdata->an_mutex, NULL); pthread_mutex_init(&pdata->phy_mutex, NULL); + ret = pdata->phy_if.phy_init(pdata); + if (ret) { + rte_free(eth_dev->data->mac_addrs); + return ret; + } + PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x", eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); diff --git a/drivers/net/axgbe/axgbe_ethdev.h b/drivers/net/axgbe/axgbe_ethdev.h index 5d20a1f..6cddb57 100644 --- a/drivers/net/axgbe/axgbe_ethdev.h +++ b/drivers/net/axgbe/axgbe_ethdev.h @@ -311,6 +311,61 @@ enum axgbe_mdio_mode { AXGBE_MDIO_MODE_CL45, }; +struct axgbe_phy { + uint32_t supported; + uint32_t advertising; + uint32_t lp_advertising; + + int address; + + int autoneg; + int speed; + int duplex; + + int link; + + int pause_autoneg; + int tx_pause; + int rx_pause; +}; + +enum axgbe_i2c_cmd { + AXGBE_I2C_CMD_READ = 0, + AXGBE_I2C_CMD_WRITE, +}; + +struct axgbe_i2c_op { + enum axgbe_i2c_cmd cmd; + + unsigned int target; + + uint8_t *buf; + unsigned int len; +}; + +struct axgbe_i2c_op_state { + struct axgbe_i2c_op *op; + + unsigned int tx_len; + unsigned char *tx_buf; + + unsigned int rx_len; + unsigned char *rx_buf; + + unsigned int tx_abort_source; + + int ret; +}; + +struct axgbe_i2c { + unsigned int started; + unsigned int max_speed_mode; + unsigned int rx_fifo_size; + unsigned int tx_fifo_size; + + struct axgbe_i2c_op_state op_state; +}; + struct axgbe_hw_if { void (*config_flow_control)(struct axgbe_port *); int (*config_rx_mode)(struct axgbe_port *); @@ -333,6 +388,89 @@ struct axgbe_hw_if { int (*exit)(struct axgbe_port *); }; +/* This structure represents implementation specific routines for an + * implementation of a PHY. All routines are required unless noted below. + * Optional routines: + * kr_training_pre, kr_training_post + */ +struct axgbe_phy_impl_if { + /* Perform Setup/teardown actions */ + int (*init)(struct axgbe_port *); + void (*exit)(struct axgbe_port *); + + /* Perform start/stop specific actions */ + int (*reset)(struct axgbe_port *); + int (*start)(struct axgbe_port *); + void (*stop)(struct axgbe_port *); + + /* Return the link status */ + int (*link_status)(struct axgbe_port *, int *); + + /* Indicate if a particular speed is valid */ + int (*valid_speed)(struct axgbe_port *, int); + + /* Check if the specified mode can/should be used */ + bool (*use_mode)(struct axgbe_port *, enum axgbe_mode); + /* Switch the PHY into various modes */ + void (*set_mode)(struct axgbe_port *, enum axgbe_mode); + /* Retrieve mode needed for a specific speed */ + enum axgbe_mode (*get_mode)(struct axgbe_port *, int); + /* Retrieve new/next mode when trying to auto-negotiate */ + enum axgbe_mode (*switch_mode)(struct axgbe_port *); + /* Retrieve current mode */ + enum axgbe_mode (*cur_mode)(struct axgbe_port *); + + /* Retrieve current auto-negotiation mode */ + enum axgbe_an_mode (*an_mode)(struct axgbe_port *); + + /* Configure auto-negotiation settings */ + int (*an_config)(struct axgbe_port *); + + /* Set/override auto-negotiation advertisement settings */ + unsigned int (*an_advertising)(struct axgbe_port *port); + + /* Process results of auto-negotiation */ + enum axgbe_mode (*an_outcome)(struct axgbe_port *); + + /* Pre/Post KR training enablement support */ + void (*kr_training_pre)(struct axgbe_port *); + void (*kr_training_post)(struct axgbe_port *); +}; + +struct axgbe_phy_if { + /* For PHY setup/teardown */ + int (*phy_init)(struct axgbe_port *); + void (*phy_exit)(struct axgbe_port *); + + /* For PHY support when setting device up/down */ + int (*phy_reset)(struct axgbe_port *); + int (*phy_start)(struct axgbe_port *); + void (*phy_stop)(struct axgbe_port *); + + /* For PHY support while device is up */ + void (*phy_status)(struct axgbe_port *); + int (*phy_config_aneg)(struct axgbe_port *); + + /* For PHY settings validation */ + int (*phy_valid_speed)(struct axgbe_port *, int); + /* For single interrupt support */ + void (*an_isr)(struct axgbe_port *); + /* PHY implementation specific services */ + struct axgbe_phy_impl_if phy_impl; +}; + +struct axgbe_i2c_if { + /* For initial I2C setup */ + int (*i2c_init)(struct axgbe_port *); + + /* For I2C support when setting device up/down */ + int (*i2c_start)(struct axgbe_port *); + void (*i2c_stop)(struct axgbe_port *); + + /* For performing I2C operations */ + int (*i2c_xfer)(struct axgbe_port *, struct axgbe_i2c_op *); +}; + /* This structure contains flags that indicate what hardware features * or configurations are present in the device. */ @@ -380,6 +518,7 @@ struct axgbe_hw_features { }; struct axgbe_version_data { + void (*init_function_ptrs_phy_impl)(struct axgbe_phy_if *); enum axgbe_xpcs_access xpcs_access; unsigned int mmc_64bit; unsigned int tx_max_fifo_size; @@ -417,6 +556,8 @@ struct axgbe_port { unsigned long dev_state; struct axgbe_hw_if hw_if; + struct axgbe_phy_if phy_if; + struct axgbe_i2c_if i2c_if; /* AXI DMA settings */ unsigned int coherent; @@ -488,7 +629,38 @@ struct axgbe_port { struct axgbe_hw_features hw_feat; struct ether_addr mac_addr; + + /* MDIO/PHY related settings */ + unsigned int phy_started; + void *phy_data; + struct axgbe_phy phy; + int mdio_mmd; + unsigned long link_check; + volatile int mdio_completion; + + unsigned int kr_redrv; + + /* Auto-negotiation atate machine support */ + unsigned int an_int; + unsigned int an_status; + enum axgbe_an an_result; + enum axgbe_an an_state; + enum axgbe_rx kr_state; + enum axgbe_rx kx_state; + unsigned int an_supported; + unsigned int parallel_detect; + unsigned int fec_ability; + unsigned long an_start; + enum axgbe_an_mode an_mode; + + /* I2C support */ + struct axgbe_i2c i2c; + volatile int i2c_complete; }; void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if); +void axgbe_init_function_ptrs_phy(struct axgbe_phy_if *phy_if); +void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if); +void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if); + #endif /* RTE_ETH_AXGBE_H_ */ diff --git a/drivers/net/axgbe/axgbe_i2c.c b/drivers/net/axgbe/axgbe_i2c.c new file mode 100644 index 0000000..468955e --- /dev/null +++ b/drivers/net/axgbe/axgbe_i2c.c @@ -0,0 +1,453 @@ +/*- + * Copyright(c) 2014-2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * AMD 10Gb Ethernet driver + * + * This file is available to you under your choice of the following two + * licenses: + * + * License 1: GPLv2 + * + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * + * This file is free software; you may copy, redistribute and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2013 Synopsys, Inc. + * + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * License 2: Modified BSD + * + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices, Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2013 Synopsys, Inc. + * + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "axgbe_ethdev.h" +#include "axgbe_common.h" + +#define AXGBE_ABORT_COUNT 500 +#define AXGBE_DISABLE_COUNT 1000 + +#define AXGBE_STD_SPEED 1 + +#define AXGBE_INTR_RX_FULL BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX) +#define AXGBE_INTR_TX_EMPTY BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX) +#define AXGBE_INTR_TX_ABRT BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX) +#define AXGBE_INTR_STOP_DET BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX) +#define AXGBE_DEFAULT_INT_MASK (AXGBE_INTR_RX_FULL | \ + AXGBE_INTR_TX_EMPTY | \ + AXGBE_INTR_TX_ABRT | \ + AXGBE_INTR_STOP_DET) + +#define AXGBE_I2C_READ BIT(8) +#define AXGBE_I2C_STOP BIT(9) + +static int axgbe_i2c_abort(struct axgbe_port *pdata) +{ + unsigned int wait = AXGBE_ABORT_COUNT; + + /* Must be enabled to recognize the abort request */ + XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1); + + /* Issue the abort */ + XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1); + + while (wait--) { + if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT)) + return 0; + rte_delay_us(500); + } + + return -EBUSY; +} + +static int axgbe_i2c_set_enable(struct axgbe_port *pdata, bool enable) +{ + unsigned int wait = AXGBE_DISABLE_COUNT; + unsigned int mode = enable ? 1 : 0; + + while (wait--) { + XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode); + if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode) + return 0; + + rte_delay_us(100); + } + + return -EBUSY; +} + +static int axgbe_i2c_disable(struct axgbe_port *pdata) +{ + unsigned int ret; + + ret = axgbe_i2c_set_enable(pdata, false); + if (ret) { + /* Disable failed, try an abort */ + ret = axgbe_i2c_abort(pdata); + if (ret) + return ret; + + /* Abort succeeded, try to disable again */ + ret = axgbe_i2c_set_enable(pdata, false); + } + + return ret; +} + +static int axgbe_i2c_enable(struct axgbe_port *pdata) +{ + return axgbe_i2c_set_enable(pdata, true); +} + +static void axgbe_i2c_clear_all_interrupts(struct axgbe_port *pdata) +{ + XI2C_IOREAD(pdata, IC_CLR_INTR); +} + +static void axgbe_i2c_disable_interrupts(struct axgbe_port *pdata) +{ + XI2C_IOWRITE(pdata, IC_INTR_MASK, 0); +} + +static void axgbe_i2c_enable_interrupts(struct axgbe_port *pdata) +{ + XI2C_IOWRITE(pdata, IC_INTR_MASK, AXGBE_DEFAULT_INT_MASK); +} + +static void axgbe_i2c_write(struct axgbe_port *pdata) +{ + struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; + unsigned int tx_slots; + unsigned int cmd; + + /* Configured to never receive Rx overflows, so fill up Tx fifo */ + tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR); + while (tx_slots && state->tx_len) { + if (state->op->cmd == AXGBE_I2C_CMD_READ) + cmd = AXGBE_I2C_READ; + else + cmd = *state->tx_buf++; + + if (state->tx_len == 1) + XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1); + + XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd); + + tx_slots--; + state->tx_len--; + } + + /* No more Tx operations, so ignore TX_EMPTY and return */ + if (!state->tx_len) + XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0); +} + +static void axgbe_i2c_read(struct axgbe_port *pdata) +{ + struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; + unsigned int rx_slots; + + /* Anything to be read? */ + if (state->op->cmd != AXGBE_I2C_CMD_READ) + return; + + rx_slots = XI2C_IOREAD(pdata, IC_RXFLR); + while (rx_slots && state->rx_len) { + *state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD); + state->rx_len--; + rx_slots--; + } +} + +static void axgbe_i2c_clear_isr_interrupts(struct axgbe_port *pdata, + unsigned int isr) +{ + struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; + + if (isr & AXGBE_INTR_TX_ABRT) { + state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE); + XI2C_IOREAD(pdata, IC_CLR_TX_ABRT); + } + + if (isr & AXGBE_INTR_STOP_DET) + XI2C_IOREAD(pdata, IC_CLR_STOP_DET); +} + +static int axgbe_i2c_isr(struct axgbe_port *pdata) +{ + struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; + unsigned int isr; + + isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT); + + axgbe_i2c_clear_isr_interrupts(pdata, isr); + + if (isr & AXGBE_INTR_TX_ABRT) { + axgbe_i2c_disable_interrupts(pdata); + + state->ret = -EIO; + goto out; + } + + /* Check for data in the Rx fifo */ + axgbe_i2c_read(pdata); + + /* Fill up the Tx fifo next */ + axgbe_i2c_write(pdata); + +out: + /* Complete on an error or STOP condition */ + if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET)) + return 1; + + return 0; +} + +static void axgbe_i2c_set_mode(struct axgbe_port *pdata) +{ + unsigned int reg; + + reg = XI2C_IOREAD(pdata, IC_CON); + XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1); + XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1); + XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1); + XI2C_SET_BITS(reg, IC_CON, SPEED, AXGBE_STD_SPEED); + XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1); + XI2C_IOWRITE(pdata, IC_CON, reg); +} + +static void axgbe_i2c_get_features(struct axgbe_port *pdata) +{ + struct axgbe_i2c *i2c = &pdata->i2c; + unsigned int reg; + + reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1); + i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, + MAX_SPEED_MODE); + i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, + RX_BUFFER_DEPTH); + i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1, + TX_BUFFER_DEPTH); +} + +static void axgbe_i2c_set_target(struct axgbe_port *pdata, unsigned int addr) +{ + XI2C_IOWRITE(pdata, IC_TAR, addr); +} + +static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op) +{ + struct axgbe_i2c_op_state *state = &pdata->i2c.op_state; + int ret; + uint64_t timeout; + + pthread_mutex_lock(&pdata->i2c_mutex); + ret = axgbe_i2c_disable(pdata); + if (ret) { + PMD_DRV_LOG(ERR, "failed to disable i2c master"); + return ret; + } + + axgbe_i2c_set_target(pdata, op->target); + + memset(state, 0, sizeof(*state)); + state->op = op; + state->tx_len = op->len; + state->tx_buf = (unsigned char *)op->buf; + state->rx_len = op->len; + state->rx_buf = (unsigned char *)op->buf; + + axgbe_i2c_clear_all_interrupts(pdata); + ret = axgbe_i2c_enable(pdata); + if (ret) { + PMD_DRV_LOG(ERR, "failed to enable i2c master\n"); + return ret; + } + + /* Enabling the interrupts will cause the TX FIFO empty interrupt to + * fire and begin to process the command via the ISR. + */ + axgbe_i2c_enable_interrupts(pdata); + timeout = rte_get_timer_cycles() + rte_get_timer_hz(); + + while (time_before(rte_get_timer_cycles(), timeout)) { + rte_delay_us(100); + if (XI2C_IOREAD(pdata, IC_RAW_INTR_STAT)) { + if (axgbe_i2c_isr(pdata)) + goto success; + } + } + + PMD_DRV_LOG(ERR, "i2c operation timed out"); + axgbe_i2c_disable_interrupts(pdata); + axgbe_i2c_disable(pdata); + ret = -ETIMEDOUT; + goto unlock; + +success: + ret = state->ret; + if (ret) { + if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK) + ret = -ENOTCONN; + else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST) + ret = -EAGAIN; + } + +unlock: + pthread_mutex_unlock(&pdata->i2c_mutex); + return ret; +} + +static void axgbe_i2c_stop(struct axgbe_port *pdata) +{ + if (!pdata->i2c.started) + return; + + pdata->i2c.started = 0; + axgbe_i2c_disable_interrupts(pdata); + axgbe_i2c_disable(pdata); + axgbe_i2c_clear_all_interrupts(pdata); +} + +static int axgbe_i2c_start(struct axgbe_port *pdata) +{ + if (pdata->i2c.started) + return 0; + + pdata->i2c.started = 1; + + return 0; +} + +static int axgbe_i2c_init(struct axgbe_port *pdata) +{ + int ret; + + axgbe_i2c_disable_interrupts(pdata); + + ret = axgbe_i2c_disable(pdata); + if (ret) { + PMD_DRV_LOG(ERR, "failed to disable i2c master"); + return ret; + } + + axgbe_i2c_get_features(pdata); + + axgbe_i2c_set_mode(pdata); + + axgbe_i2c_clear_all_interrupts(pdata); + + return 0; +} + +void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if) +{ + i2c_if->i2c_init = axgbe_i2c_init; + i2c_if->i2c_start = axgbe_i2c_start; + i2c_if->i2c_stop = axgbe_i2c_stop; + i2c_if->i2c_xfer = axgbe_i2c_xfer; +} diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c new file mode 100644 index 0000000..4fbf5c3 --- /dev/null +++ b/drivers/net/axgbe/axgbe_mdio.c @@ -0,0 +1,203 @@ +/*- + * Copyright(c) 2014-2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * AMD 10Gb Ethernet driver + * + * This file is available to you under your choice of the following two + * licenses: + * + * License 1: GPLv2 + * + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * + * This file is free software; you may copy, redistribute and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2013 Synopsys, Inc. + * + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * License 2: Modified BSD + * + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices, Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2013 Synopsys, Inc. + * + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "axgbe_ethdev.h" +#include "axgbe_common.h" +#include "axgbe_phy.h" + +static int axgbe_phy_best_advertised_speed(struct axgbe_port *pdata) +{ + if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) + return SPEED_10000; + else if (pdata->phy.advertising & ADVERTISED_10000baseT_Full) + return SPEED_10000; + else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full) + return SPEED_2500; + else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full) + return SPEED_1000; + else if (pdata->phy.advertising & ADVERTISED_1000baseT_Full) + return SPEED_1000; + else if (pdata->phy.advertising & ADVERTISED_100baseT_Full) + return SPEED_100; + + return SPEED_UNKNOWN; +} + +static int axgbe_phy_init(struct axgbe_port *pdata) +{ + int ret; + + pdata->mdio_mmd = MDIO_MMD_PCS; + + /* Check for FEC support */ + pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, + MDIO_PMA_10GBR_FECABLE); + pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE | + MDIO_PMA_10GBR_FECABLE_ERRABLE); + + /* Setup the phy (including supported features) */ + ret = pdata->phy_if.phy_impl.init(pdata); + if (ret) + return ret; + pdata->phy.advertising = pdata->phy.supported; + + pdata->phy.address = 0; + + if (pdata->phy.advertising & ADVERTISED_Autoneg) { + pdata->phy.autoneg = AUTONEG_ENABLE; + pdata->phy.speed = SPEED_UNKNOWN; + pdata->phy.duplex = DUPLEX_UNKNOWN; + } else { + pdata->phy.autoneg = AUTONEG_DISABLE; + pdata->phy.speed = axgbe_phy_best_advertised_speed(pdata); + pdata->phy.duplex = DUPLEX_FULL; + } + + pdata->phy.link = 0; + + pdata->phy.pause_autoneg = pdata->pause_autoneg; + pdata->phy.tx_pause = pdata->tx_pause; + pdata->phy.rx_pause = pdata->rx_pause; + + /* Fix up Flow Control advertising */ + pdata->phy.advertising &= ~ADVERTISED_Pause; + pdata->phy.advertising &= ~ADVERTISED_Asym_Pause; + + if (pdata->rx_pause) { + pdata->phy.advertising |= ADVERTISED_Pause; + pdata->phy.advertising |= ADVERTISED_Asym_Pause; + } + + if (pdata->tx_pause) + pdata->phy.advertising ^= ADVERTISED_Asym_Pause; + return 0; +} + +void axgbe_init_function_ptrs_phy(struct axgbe_phy_if *phy_if) +{ + phy_if->phy_init = axgbe_phy_init; +} diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c new file mode 100644 index 0000000..cea4266 --- /dev/null +++ b/drivers/net/axgbe/axgbe_phy_impl.c @@ -0,0 +1,799 @@ +/*- + * Copyright(c) 2014-2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * AMD 10Gb Ethernet driver + * + * This file is available to you under your choice of the following two + * licenses: + * + * License 1: GPLv2 + * + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * + * This file is free software; you may copy, redistribute and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2013 Synopsys, Inc. + * + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * License 2: Modified BSD + * + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Advanced Micro Devices, Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (c) 2013 Synopsys, Inc. + * + * The Synopsys DWC ETHER XGMAC Software Driver and documentation + * (hereinafter "Software") is an unsupported proprietary work of Synopsys, + * Inc. unless otherwise expressly agreed to in writing between Synopsys + * and you. + * + * The Software IS NOT an item of Licensed Software or Licensed Product + * under any End User Software License Agreement or Agreement for Licensed + * Product with Synopsys or any supplement thereto. Permission is hereby + * granted, free of charge, to any person obtaining a copy of this software + * annotated with this license and the Software, to deal in the Software + * without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" + * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "axgbe_ethdev.h" +#include "axgbe_common.h" +#include "axgbe_phy.h" + +#define AXGBE_PHY_PORT_SPEED_100 BIT(0) +#define AXGBE_PHY_PORT_SPEED_1000 BIT(1) +#define AXGBE_PHY_PORT_SPEED_2500 BIT(2) +#define AXGBE_PHY_PORT_SPEED_10000 BIT(3) + +#define AXGBE_MUTEX_RELEASE 0x80000000 + +#define AXGBE_SFP_DIRECT 7 + +/* I2C target addresses */ +#define AXGBE_SFP_SERIAL_ID_ADDRESS 0x50 +#define AXGBE_SFP_DIAG_INFO_ADDRESS 0x51 +#define AXGBE_SFP_PHY_ADDRESS 0x56 +#define AXGBE_GPIO_ADDRESS_PCA9555 0x20 + +/* SFP sideband signal indicators */ +#define AXGBE_GPIO_NO_TX_FAULT BIT(0) +#define AXGBE_GPIO_NO_RATE_SELECT BIT(1) +#define AXGBE_GPIO_NO_MOD_ABSENT BIT(2) +#define AXGBE_GPIO_NO_RX_LOS BIT(3) + +/* Rate-change complete wait/retry count */ +#define AXGBE_RATECHANGE_COUNT 500 + +enum axgbe_port_mode { + AXGBE_PORT_MODE_RSVD = 0, + AXGBE_PORT_MODE_BACKPLANE, + AXGBE_PORT_MODE_BACKPLANE_2500, + AXGBE_PORT_MODE_1000BASE_T, + AXGBE_PORT_MODE_1000BASE_X, + AXGBE_PORT_MODE_NBASE_T, + AXGBE_PORT_MODE_10GBASE_T, + AXGBE_PORT_MODE_10GBASE_R, + AXGBE_PORT_MODE_SFP, + AXGBE_PORT_MODE_MAX, +}; + +enum axgbe_conn_type { + AXGBE_CONN_TYPE_NONE = 0, + AXGBE_CONN_TYPE_SFP, + AXGBE_CONN_TYPE_MDIO, + AXGBE_CONN_TYPE_RSVD1, + AXGBE_CONN_TYPE_BACKPLANE, + AXGBE_CONN_TYPE_MAX, +}; + +/* SFP/SFP+ related definitions */ +enum axgbe_sfp_comm { + AXGBE_SFP_COMM_DIRECT = 0, + AXGBE_SFP_COMM_PCA9545, +}; + +enum axgbe_sfp_cable { + AXGBE_SFP_CABLE_UNKNOWN = 0, + AXGBE_SFP_CABLE_ACTIVE, + AXGBE_SFP_CABLE_PASSIVE, +}; + +enum axgbe_sfp_base { + AXGBE_SFP_BASE_UNKNOWN = 0, + AXGBE_SFP_BASE_1000_T, + AXGBE_SFP_BASE_1000_SX, + AXGBE_SFP_BASE_1000_LX, + AXGBE_SFP_BASE_1000_CX, + AXGBE_SFP_BASE_10000_SR, + AXGBE_SFP_BASE_10000_LR, + AXGBE_SFP_BASE_10000_LRM, + AXGBE_SFP_BASE_10000_ER, + AXGBE_SFP_BASE_10000_CR, +}; + +enum axgbe_sfp_speed { + AXGBE_SFP_SPEED_UNKNOWN = 0, + AXGBE_SFP_SPEED_100_1000, + AXGBE_SFP_SPEED_1000, + AXGBE_SFP_SPEED_10000, +}; + +/* SFP Serial ID Base ID values relative to an offset of 0 */ +#define AXGBE_SFP_BASE_ID 0 +#define AXGBE_SFP_ID_SFP 0x03 + +#define AXGBE_SFP_BASE_EXT_ID 1 +#define AXGBE_SFP_EXT_ID_SFP 0x04 + +#define AXGBE_SFP_BASE_10GBE_CC 3 +#define AXGBE_SFP_BASE_10GBE_CC_SR BIT(4) +#define AXGBE_SFP_BASE_10GBE_CC_LR BIT(5) +#define AXGBE_SFP_BASE_10GBE_CC_LRM BIT(6) +#define AXGBE_SFP_BASE_10GBE_CC_ER BIT(7) + +#define AXGBE_SFP_BASE_1GBE_CC 6 +#define AXGBE_SFP_BASE_1GBE_CC_SX BIT(0) +#define AXGBE_SFP_BASE_1GBE_CC_LX BIT(1) +#define AXGBE_SFP_BASE_1GBE_CC_CX BIT(2) +#define AXGBE_SFP_BASE_1GBE_CC_T BIT(3) + +#define AXGBE_SFP_BASE_CABLE 8 +#define AXGBE_SFP_BASE_CABLE_PASSIVE BIT(2) +#define AXGBE_SFP_BASE_CABLE_ACTIVE BIT(3) + +#define AXGBE_SFP_BASE_BR 12 +#define AXGBE_SFP_BASE_BR_1GBE_MIN 0x0a +#define AXGBE_SFP_BASE_BR_1GBE_MAX 0x0d +#define AXGBE_SFP_BASE_BR_10GBE_MIN 0x64 +#define AXGBE_SFP_BASE_BR_10GBE_MAX 0x68 + +#define AXGBE_SFP_BASE_CU_CABLE_LEN 18 + +#define AXGBE_SFP_BASE_VENDOR_NAME 20 +#define AXGBE_SFP_BASE_VENDOR_NAME_LEN 16 +#define AXGBE_SFP_BASE_VENDOR_PN 40 +#define AXGBE_SFP_BASE_VENDOR_PN_LEN 16 +#define AXGBE_SFP_BASE_VENDOR_REV 56 +#define AXGBE_SFP_BASE_VENDOR_REV_LEN 4 + +#define AXGBE_SFP_BASE_CC 63 + +/* SFP Serial ID Extended ID values relative to an offset of 64 */ +#define AXGBE_SFP_BASE_VENDOR_SN 4 +#define AXGBE_SFP_BASE_VENDOR_SN_LEN 16 + +#define AXGBE_SFP_EXTD_DIAG 28 +#define AXGBE_SFP_EXTD_DIAG_ADDR_CHANGE BIT(2) + +#define AXGBE_SFP_EXTD_SFF_8472 30 + +#define AXGBE_SFP_EXTD_CC 31 + +struct axgbe_sfp_eeprom { + u8 base[64]; + u8 extd[32]; + u8 vendor[32]; +}; + +#define AXGBE_BEL_FUSE_VENDOR "BEL-FUSE" +#define AXGBE_BEL_FUSE_PARTNO "1GBT-SFP06" + +struct axgbe_sfp_ascii { + union { + char vendor[AXGBE_SFP_BASE_VENDOR_NAME_LEN + 1]; + char partno[AXGBE_SFP_BASE_VENDOR_PN_LEN + 1]; + char rev[AXGBE_SFP_BASE_VENDOR_REV_LEN + 1]; + char serno[AXGBE_SFP_BASE_VENDOR_SN_LEN + 1]; + } u; +}; + +/* MDIO PHY reset types */ +enum axgbe_mdio_reset { + AXGBE_MDIO_RESET_NONE = 0, + AXGBE_MDIO_RESET_I2C_GPIO, + AXGBE_MDIO_RESET_INT_GPIO, + AXGBE_MDIO_RESET_MAX, +}; + +/* Re-driver related definitions */ +enum axgbe_phy_redrv_if { + AXGBE_PHY_REDRV_IF_MDIO = 0, + AXGBE_PHY_REDRV_IF_I2C, + AXGBE_PHY_REDRV_IF_MAX, +}; + +enum axgbe_phy_redrv_model { + AXGBE_PHY_REDRV_MODEL_4223 = 0, + AXGBE_PHY_REDRV_MODEL_4227, + AXGBE_PHY_REDRV_MODEL_MAX, +}; + +enum axgbe_phy_redrv_mode { + AXGBE_PHY_REDRV_MODE_CX = 5, + AXGBE_PHY_REDRV_MODE_SR = 9, +}; + +#define AXGBE_PHY_REDRV_MODE_REG 0x12b0 + +/* PHY related configuration information */ +struct axgbe_phy_data { + enum axgbe_port_mode port_mode; + + unsigned int port_id; + + unsigned int port_speeds; + + enum axgbe_conn_type conn_type; + + enum axgbe_mode cur_mode; + enum axgbe_mode start_mode; + + unsigned int rrc_count; + + unsigned int mdio_addr; + + unsigned int comm_owned; + + /* SFP Support */ + enum axgbe_sfp_comm sfp_comm; + unsigned int sfp_mux_address; + unsigned int sfp_mux_channel; + + unsigned int sfp_gpio_address; + unsigned int sfp_gpio_mask; + unsigned int sfp_gpio_rx_los; + unsigned int sfp_gpio_tx_fault; + unsigned int sfp_gpio_mod_absent; + unsigned int sfp_gpio_rate_select; + + unsigned int sfp_rx_los; + unsigned int sfp_tx_fault; + unsigned int sfp_mod_absent; + unsigned int sfp_diags; + unsigned int sfp_changed; + unsigned int sfp_phy_avail; + unsigned int sfp_cable_len; + enum axgbe_sfp_base sfp_base; + enum axgbe_sfp_cable sfp_cable; + enum axgbe_sfp_speed sfp_speed; + struct axgbe_sfp_eeprom sfp_eeprom; + + /* External PHY support */ + enum axgbe_mdio_mode phydev_mode; + enum axgbe_mdio_reset mdio_reset; + unsigned int mdio_reset_addr; + unsigned int mdio_reset_gpio; + + /* Re-driver support */ + unsigned int redrv; + unsigned int redrv_if; + unsigned int redrv_addr; + unsigned int redrv_lane; + unsigned int redrv_model; +}; + +static void axgbe_phy_sfp_gpio_setup(struct axgbe_port *pdata) +{ + struct axgbe_phy_data *phy_data = pdata->phy_data; + unsigned int reg; + + reg = XP_IOREAD(pdata, XP_PROP_3); + + phy_data->sfp_gpio_address = AXGBE_GPIO_ADDRESS_PCA9555 + + XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR); + + phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK); + + phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3, + GPIO_RX_LOS); + phy_data->sfp_gpio_tx_fault = XP_GET_BITS(reg, XP_PROP_3, + GPIO_TX_FAULT); + phy_data->sfp_gpio_mod_absent = XP_GET_BITS(reg, XP_PROP_3, + GPIO_MOD_ABS); + phy_data->sfp_gpio_rate_select = XP_GET_BITS(reg, XP_PROP_3, + GPIO_RATE_SELECT); +} + +static void axgbe_phy_sfp_comm_setup(struct axgbe_port *pdata) +{ + struct axgbe_phy_data *phy_data = pdata->phy_data; + unsigned int reg, mux_addr_hi, mux_addr_lo; + + reg = XP_IOREAD(pdata, XP_PROP_4); + + mux_addr_hi = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_HI); + mux_addr_lo = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_LO); + if (mux_addr_lo == AXGBE_SFP_DIRECT) + return; + + phy_data->sfp_comm = AXGBE_SFP_COMM_PCA9545; + phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo; + phy_data->sfp_mux_channel = XP_GET_BITS(reg, XP_PROP_4, MUX_CHAN); +} + +static void axgbe_phy_sfp_setup(struct axgbe_port *pdata) +{ + axgbe_phy_sfp_comm_setup(pdata); + axgbe_phy_sfp_gpio_setup(pdata); +} + +static bool axgbe_phy_redrv_error(struct axgbe_phy_data *phy_data) +{ + if (!phy_data->redrv) + return false; + + if (phy_data->redrv_if >= AXGBE_PHY_REDRV_IF_MAX) + return true; + + switch (phy_data->redrv_model) { + case AXGBE_PHY_REDRV_MODEL_4223: + if (phy_data->redrv_lane > 3) + return true; + break; + case AXGBE_PHY_REDRV_MODEL_4227: + if (phy_data->redrv_lane > 1) + return true; + break; + default: + return true; + } + + return false; +} + +static int axgbe_phy_mdio_reset_setup(struct axgbe_port *pdata) +{ + struct axgbe_phy_data *phy_data = pdata->phy_data; + unsigned int reg; + + if (phy_data->conn_type != AXGBE_CONN_TYPE_MDIO) + return 0; + reg = XP_IOREAD(pdata, XP_PROP_3); + phy_data->mdio_reset = XP_GET_BITS(reg, XP_PROP_3, MDIO_RESET); + switch (phy_data->mdio_reset) { + case AXGBE_MDIO_RESET_NONE: + case AXGBE_MDIO_RESET_I2C_GPIO: + case AXGBE_MDIO_RESET_INT_GPIO: + break; + default: + PMD_DRV_LOG(ERR, "unsupported MDIO reset (%#x)\n", + phy_data->mdio_reset); + return -EINVAL; + } + if (phy_data->mdio_reset == AXGBE_MDIO_RESET_I2C_GPIO) { + phy_data->mdio_reset_addr = AXGBE_GPIO_ADDRESS_PCA9555 + + XP_GET_BITS(reg, XP_PROP_3, + MDIO_RESET_I2C_ADDR); + phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, + MDIO_RESET_I2C_GPIO); + } else if (phy_data->mdio_reset == AXGBE_MDIO_RESET_INT_GPIO) { + phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3, + MDIO_RESET_INT_GPIO); + } + + return 0; +} + +static bool axgbe_phy_port_mode_mismatch(struct axgbe_port *pdata) +{ + struct axgbe_phy_data *phy_data = pdata->phy_data; + + switch (phy_data->port_mode) { + case AXGBE_PORT_MODE_BACKPLANE: + if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) + return false; + break; + case AXGBE_PORT_MODE_BACKPLANE_2500: + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) + return false; + break; + case AXGBE_PORT_MODE_1000BASE_T: + if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000)) + return false; + break; + case AXGBE_PORT_MODE_1000BASE_X: + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) + return false; + break; + case AXGBE_PORT_MODE_NBASE_T: + if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500)) + return false; + break; + case AXGBE_PORT_MODE_10GBASE_T: + if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) + return false; + break; + case AXGBE_PORT_MODE_10GBASE_R: + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) + return false; + break; + case AXGBE_PORT_MODE_SFP: + if ((phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) || + (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000)) + return false; + break; + default: + break; + } + + return true; +} + +static bool axgbe_phy_conn_type_mismatch(struct axgbe_port *pdata) +{ + struct axgbe_phy_data *phy_data = pdata->phy_data; + + switch (phy_data->port_mode) { + case AXGBE_PORT_MODE_BACKPLANE: + case AXGBE_PORT_MODE_BACKPLANE_2500: + if (phy_data->conn_type == AXGBE_CONN_TYPE_BACKPLANE) + return false; + break; + case AXGBE_PORT_MODE_1000BASE_T: + case AXGBE_PORT_MODE_1000BASE_X: + case AXGBE_PORT_MODE_NBASE_T: + case AXGBE_PORT_MODE_10GBASE_T: + case AXGBE_PORT_MODE_10GBASE_R: + if (phy_data->conn_type == AXGBE_CONN_TYPE_MDIO) + return false; + break; + case AXGBE_PORT_MODE_SFP: + if (phy_data->conn_type == AXGBE_CONN_TYPE_SFP) + return false; + break; + default: + break; + } + + return true; +} + +static bool axgbe_phy_port_enabled(struct axgbe_port *pdata) +{ + unsigned int reg; + + reg = XP_IOREAD(pdata, XP_PROP_0); + if (!XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS)) + return false; + if (!XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE)) + return false; + + return true; +} + +static int axgbe_phy_init(struct axgbe_port *pdata) +{ + struct axgbe_phy_data *phy_data; + unsigned int reg; + int ret; + + /* Check if enabled */ + if (!axgbe_phy_port_enabled(pdata)) { + PMD_DRV_LOG(ERR, "device is not enabled"); + return -ENODEV; + } + + /* Initialize the I2C controller */ + ret = pdata->i2c_if.i2c_init(pdata); + if (ret) + return ret; + + phy_data = rte_zmalloc("phy_data memory", sizeof(*phy_data), 0); + if (!phy_data) { + PMD_DRV_LOG(ERR, "phy_data allocation failed"); + return -ENOMEM; + } + pdata->phy_data = phy_data; + + reg = XP_IOREAD(pdata, XP_PROP_0); + phy_data->port_mode = XP_GET_BITS(reg, XP_PROP_0, PORT_MODE); + phy_data->port_id = XP_GET_BITS(reg, XP_PROP_0, PORT_ID); + phy_data->port_speeds = XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS); + phy_data->conn_type = XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE); + phy_data->mdio_addr = XP_GET_BITS(reg, XP_PROP_0, MDIO_ADDR); + + reg = XP_IOREAD(pdata, XP_PROP_4); + phy_data->redrv = XP_GET_BITS(reg, XP_PROP_4, REDRV_PRESENT); + phy_data->redrv_if = XP_GET_BITS(reg, XP_PROP_4, REDRV_IF); + phy_data->redrv_addr = XP_GET_BITS(reg, XP_PROP_4, REDRV_ADDR); + phy_data->redrv_lane = XP_GET_BITS(reg, XP_PROP_4, REDRV_LANE); + phy_data->redrv_model = XP_GET_BITS(reg, XP_PROP_4, REDRV_MODEL); + + /* Validate the connection requested */ + if (axgbe_phy_conn_type_mismatch(pdata)) { + PMD_DRV_LOG(ERR, "phy mode/connection mismatch (%#x/%#x)", + phy_data->port_mode, phy_data->conn_type); + return -EINVAL; + } + + /* Validate the mode requested */ + if (axgbe_phy_port_mode_mismatch(pdata)) { + PMD_DRV_LOG(ERR, "phy mode/speed mismatch (%#x/%#x)", + phy_data->port_mode, phy_data->port_speeds); + return -EINVAL; + } + + /* Check for and validate MDIO reset support */ + ret = axgbe_phy_mdio_reset_setup(pdata); + if (ret) + return ret; + + /* Validate the re-driver information */ + if (axgbe_phy_redrv_error(phy_data)) { + PMD_DRV_LOG(ERR, "phy re-driver settings error"); + return -EINVAL; + } + pdata->kr_redrv = phy_data->redrv; + + /* Indicate current mode is unknown */ + phy_data->cur_mode = AXGBE_MODE_UNKNOWN; + + /* Initialize supported features */ + pdata->phy.supported = 0; + + switch (phy_data->port_mode) { + /* Backplane support */ + case AXGBE_PORT_MODE_BACKPLANE: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_Backplane; + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { + pdata->phy.supported |= SUPPORTED_1000baseKX_Full; + phy_data->start_mode = AXGBE_MODE_KX_1000; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { + pdata->phy.supported |= SUPPORTED_10000baseKR_Full; + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) + pdata->phy.supported |= + SUPPORTED_10000baseR_FEC; + phy_data->start_mode = AXGBE_MODE_KR; + } + + phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; + break; + case AXGBE_PORT_MODE_BACKPLANE_2500: + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_Backplane; + pdata->phy.supported |= SUPPORTED_2500baseX_Full; + phy_data->start_mode = AXGBE_MODE_KX_2500; + + phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; + break; + + /* MDIO 1GBase-T support */ + case AXGBE_PORT_MODE_1000BASE_T: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_TP; + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { + pdata->phy.supported |= SUPPORTED_100baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { + pdata->phy.supported |= SUPPORTED_1000baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_1000; + } + + phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; + break; + + /* MDIO Base-X support */ + case AXGBE_PORT_MODE_1000BASE_X: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_FIBRE; + pdata->phy.supported |= SUPPORTED_1000baseT_Full; + phy_data->start_mode = AXGBE_MODE_X; + + phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; + break; + + /* MDIO NBase-T support */ + case AXGBE_PORT_MODE_NBASE_T: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_TP; + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { + pdata->phy.supported |= SUPPORTED_100baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { + pdata->phy.supported |= SUPPORTED_1000baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_1000; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_2500) { + pdata->phy.supported |= SUPPORTED_2500baseX_Full; + phy_data->start_mode = AXGBE_MODE_KX_2500; + } + + phy_data->phydev_mode = AXGBE_MDIO_MODE_CL45; + break; + + /* 10GBase-T support */ + case AXGBE_PORT_MODE_10GBASE_T: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_TP; + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { + pdata->phy.supported |= SUPPORTED_100baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { + pdata->phy.supported |= SUPPORTED_1000baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_1000; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { + pdata->phy.supported |= SUPPORTED_10000baseT_Full; + phy_data->start_mode = AXGBE_MODE_KR; + } + + phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; + break; + + /* 10GBase-R support */ + case AXGBE_PORT_MODE_10GBASE_R: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_TP; + pdata->phy.supported |= SUPPORTED_10000baseT_Full; + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) + pdata->phy.supported |= SUPPORTED_10000baseR_FEC; + phy_data->start_mode = AXGBE_MODE_SFI; + + phy_data->phydev_mode = AXGBE_MDIO_MODE_NONE; + break; + + /* SFP support */ + case AXGBE_PORT_MODE_SFP: + pdata->phy.supported |= SUPPORTED_Autoneg; + pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; + pdata->phy.supported |= SUPPORTED_TP; + pdata->phy.supported |= SUPPORTED_FIBRE; + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_100) { + pdata->phy.supported |= SUPPORTED_100baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_100; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_1000) { + pdata->phy.supported |= SUPPORTED_1000baseT_Full; + phy_data->start_mode = AXGBE_MODE_SGMII_1000; + } + if (phy_data->port_speeds & AXGBE_PHY_PORT_SPEED_10000) { + pdata->phy.supported |= SUPPORTED_10000baseT_Full; + phy_data->start_mode = AXGBE_MODE_SFI; + if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) + pdata->phy.supported |= + SUPPORTED_10000baseR_FEC; + } + + phy_data->phydev_mode = AXGBE_MDIO_MODE_CL22; + + axgbe_phy_sfp_setup(pdata); + break; + default: + return -EINVAL; + } + + if ((phy_data->conn_type & AXGBE_CONN_TYPE_MDIO) && + (phy_data->phydev_mode != AXGBE_MDIO_MODE_NONE)) { + ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr, + phy_data->phydev_mode); + if (ret) { + PMD_DRV_LOG(ERR, "mdio port/clause not compatible (%d/%u)", + phy_data->mdio_addr, phy_data->phydev_mode); + return -EINVAL; + } + } + + if (phy_data->redrv && !phy_data->redrv_if) { + ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr, + AXGBE_MDIO_MODE_CL22); + if (ret) { + PMD_DRV_LOG(ERR, "redriver mdio port not compatible (%u)", + phy_data->redrv_addr); + return -EINVAL; + } + } + return 0; +} +void axgbe_init_function_ptrs_phy_v2(struct axgbe_phy_if *phy_if) +{ + struct axgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; + + phy_impl->init = axgbe_phy_init; +} -- 2.7.4