Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933735AbbFJP0J (ORCPT ); Wed, 10 Jun 2015 11:26:09 -0400 Received: from mail-by2on0144.outbound.protection.outlook.com ([207.46.100.144]:48288 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933247AbbFJPXc (ORCPT ); Wed, 10 Jun 2015 11:23:32 -0400 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; From: Madalin Bucur To: , , CC: , Igal Liberman Subject: [PATCH 06/12] fsl/fman: Add the FMan MAC FLIB Date: Wed, 10 Jun 2015 18:21:52 +0300 Message-ID: <1433949712-5648-13-git-send-email-madalin.bucur@freescale.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1433949712-5648-12-git-send-email-madalin.bucur@freescale.com> References: <1433949712-5648-1-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-2-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-3-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-4-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-5-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-6-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-7-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-8-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-9-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-10-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-11-git-send-email-madalin.bucur@freescale.com> <1433949712-5648-12-git-send-email-madalin.bucur@freescale.com> Reply-To: X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11FD022;1:xxRre8pA1xRUqyr+hMUAbMgChRD1tB50BBzT8LePFfk+4CbNWooARN8yd91nFMpGNFfag1t5+N0nDL5SV5Bt952jp/F5elw2CR32m5OjTBsTcVlU8+2OqsuuWQxyGmcRzs2YcUvvB+GWzx/z28zS6yHM8dwHCEkPklkI52jjeDHUE4/k/6PXTiDHkbqCp9mm1KoKEXaR+2H4MBwugkoL5MhMLf1HTDIvEIKgmq3wQaxi2MwYuV9yhMwbsb75gBh1Ad211mzfxfmukYutxX/7CSOwM866bbWCgS45H7e5fPJVnMftuMNMWmMJQ/909QAx9pUUgNp+uM4MceILknePng== X-Forefront-Antispam-Report: CIP:192.88.168.50;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(339900001)(189002)(199003)(47776003)(19580405001)(189998001)(104016003)(77096005)(50226001)(575784001)(77156002)(19580395003)(36756003)(86362001)(49486002)(87936001)(5001960100002)(5001920100001)(53806999)(5001770100001)(6806004)(105606002)(551934003)(2201001)(76176999)(43066003)(2950100001)(50986999)(229853001)(46102003)(48376002)(85426001)(33646002)(62966003)(107886002)(2004002)(2101003)(4001430100001)(559001)(579004);DIR:OUT;SFP:1102;SCL:1;SRVR:BN3PR03MB1478;H:tx30smr01.am.freescale.net;FPR:;SPF:Fail;MLV:sfv;MX:1;A:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB1478;2:75Locaj+0A+ksq6dmZR8SFbyHc1UI/4BfuzYuyKIr5nUUmZCTg/jcbfMvpTGbKEC;2:Jnyj7U33l5oYC17AGuRUmw8KOsXM/D5p6oAFs6+UO/rOwa+IuaOQ0rdmDPXnuMh1HA0JyoRzLnOvZLhMieM8+2ASMd6LdB0BXob8bCVIAryh04FZ/QSQoQx/o15zwZQr1tiIrHCgliJ+Sp8CCvPn95LfOhSrMxHIoeIdP6zjzA9YditFRv0wYtKd7pSG/Rg8U1UnWrodtm0+pQEYJXE8nZn7ipZavfdrE+xAsrCVXcg=;6:+UdwP0YCWCgQ20BcL14HZ90aVBU22P3MoIfvfE+ROGxQZYk3eVJ/1uwnGL54hD5FmTxGuPt8geFdiaweYYNezh8cVHVvurLLmz09t1UGDXwcszS3mcupAKMWEgfH64GC9M+xp8kM9B7fIMExnFES6p5O3ZBAGpHIPpJlmHLR5q89ASoeiTmBhv19JIyv6tyaq73cJv2qQIRwIub25lGHHoq57pNA0Hnm6fL2VNetRjCLkXqD0M8TA9ub0GYRQWF/5YCYj8vUfP5HQA8EAm+cKAUIts+MvT3woIutsUa6NytQSVVacc5K3Cz+wAEFp+gnmC+qt+WSGPcwLy0kMQRFpw==;3:/p/IAAOhphnBL41qujIzbu+4zJQbMjMjPWXFLjXsIHhSy55MxFLACwopWnVscEdOfc3RMhY5bkTMl1JpkeZiD6PRLjSNDUDqp+fjCnIVR7V9HtMge8ZofUMDUi3Mq0xQbFQy/mU6HrcwF58o8R7Upjkb9l1x7D4oDrqI6U+jD4MvSEp1+pMR3hXYA7K5LXW2VPzywrlyJEC7nroEw4+MJ4NKLPk1MojZc95TueKoAAAIEjPW9+lPliRM9gtFoRPtDfjycJVn16C1+gIOBe4G0V/3ZiX0eYJDKvHjAH5SVb3jigWcqArpCZ7AgwOcILHv X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1478; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(520003)(3002001);SRVR:BN3PR03MB1478;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1478; X-Forefront-PRVS: 06036BD506 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN3PR03MB1478;9:ZpF6rhNAdcUGZK/EqxJ++ft6Z8W/PH9SE3JL5oU8P4?= =?us-ascii?Q?m4k7FaCcz6oY700/y1RL11kiY9QXnIcCValfbZyNGd42T74PnmnF0QONqOpS?= =?us-ascii?Q?tsA0hkCBFa9hZo1sMZY4F3cbe4sUU/P2m2BowU37vly6zcPdzaWaLzal5DrF?= =?us-ascii?Q?YUYyXq6cISVYTZ91UWFFBbrvCdBRf/h9uIn9hhmhlVEqHU1Rl+kAXaAeMJMR?= =?us-ascii?Q?52edg0Z0e5cn2IhVNVoL3DVpEtPtFOmsnW1JdAqvzgJN1sj71CagKMSRqhQ9?= =?us-ascii?Q?qfhkbwbQzuSmJZu57/ltj1KYwp0QQIjShf+9+Ybmk5goxJzCJ2znz7ZDRNHj?= =?us-ascii?Q?nocfR648vFNpQsRFdvb/bQXIDWFXqUBEvY+72Lhh0sqtUhMdFHFY3JLaS1+D?= =?us-ascii?Q?DzljCGt8fO8SPvJgZpM9RXwygQxEM720UC8+P4201Ec3ibk5CASa3chRZTHv?= =?us-ascii?Q?zcOYWvRvYqsK7KOcC5ForMn7pqyinDIWzcrWCygrQAvlllITNbVSXCZdFQuM?= =?us-ascii?Q?XWouI3tztJ2bCiyLXq3PRJlVDQcrBiK9sB46ucMkD4K5TP361fBCEb1oLKtN?= =?us-ascii?Q?k4fev2iO5sg/o242Mn4mCslS1cRb4yj+orNlP4ASzk4fSzQmrUwoBJtsQKGo?= =?us-ascii?Q?mZRFj2eQMrFOHLViSYiE6173d5ur7SCWB9ABQjQMY9dYGRCtXXX95eMxd6lh?= =?us-ascii?Q?FQwLOAbnax+S/wZizUKjCHiQnELLuEfKDnDpu3OLOW1lxMTFFehRUmAwyw2l?= =?us-ascii?Q?wVydhejnQaIok722RfQs/JZjJFtWuzVGALB/ta+Hq6b89zSZrN4ymIn0PgTk?= =?us-ascii?Q?82132lbfRvL9hf+i07QmTKenJ31ilUArjeCaPFSjgoWRPOpspvvRQwjqnkKe?= =?us-ascii?Q?Wf6z3gf0X0pklRuvbdCcKWC3lkmA1+kH8V3+QtAaAcOyWNy/8o/QwhlF9dUi?= =?us-ascii?Q?AET3nGfBs3V0zIMBKEo4ign9+jF+KNWX1jnzUPbK2ettyVim5SHhkljnom0F?= =?us-ascii?Q?K/0mwDxN3OTm7fXLv51HywkPDJFrPWPbctOcj3O0mo8phl5H3K7kMnOXXaLp?= =?us-ascii?Q?e5dTrvzFf/TTutrF2cP1710Osj?= X-Microsoft-Exchange-Diagnostics: 1;BN3PR03MB1478;3:XhboTx9rSjXR2yb5B5y+Ng9P9mvhezMZ4cggQDmc29xyBtpggfYyib1IwME7LgxxoRFCyHGlaLuzeNewtfWqNBiq+TtxaYkyIPpJoWRgebTRaJR5eTcEgessMe3XN9gDTAeXDCqmV3YJxvHf0PmaiA==;10:oOAGAFD84hr75i1zp8Ine1nHrkA+De8j3eMkiFcdj1qCEr1jFEn6viqGe/zt/6ebrFb16iCQaZ7+Ccj/5IL8HGSKxj6zSe/Z7YKnzONx68g=;6:C/QWMzVYYRTujlZ+Mx0M50xsS6u+RPz5W3gqjLIvzhvh90sv1Rj5Za/FTlccyYiL X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Jun 2015 15:23:26.6078 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB1478 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 49271 Lines: 1618 From: Igal Liberman The FMan MAC FLib provides basic API used by the drivers to configure and control the FMan MAC hardware. Signed-off-by: Igal Liberman --- drivers/net/ethernet/freescale/fman/Makefile | 1 + drivers/net/ethernet/freescale/fman/mac/Makefile | 5 + .../net/ethernet/freescale/fman/mac/fman_dtsec.c | 571 +++++++++++++++++++++ .../freescale/fman/mac/fman_dtsec_mii_acc.c | 168 ++++++ .../net/ethernet/freescale/fman/mac/fman_memac.c | 365 +++++++++++++ .../freescale/fman/mac/fman_memac_mii_acc.c | 217 ++++++++ .../net/ethernet/freescale/fman/mac/fman_tgec.c | 217 ++++++++ 7 files changed, 1544 insertions(+) create mode 100644 drivers/net/ethernet/freescale/fman/mac/Makefile create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_memac.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_tgec.c diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile index 50a4de2..1841b03 100644 --- a/drivers/net/ethernet/freescale/fman/Makefile +++ b/drivers/net/ethernet/freescale/fman/Makefile @@ -5,3 +5,4 @@ obj-y += fsl_fman.o fsl_fman-objs := fman.o obj-y += port/ +obj-y += mac/ diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile new file mode 100644 index 0000000..ce03e25 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/mac/Makefile @@ -0,0 +1,5 @@ +obj-y += fsl_fman_mac.o + +fsl_fman_mac-objs := fman_dtsec.o fman_dtsec_mii_acc.o \ + fman_memac.o fman_memac_mii_acc.o \ + fman_tgec.o diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c new file mode 100644 index 0000000..290a037 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c @@ -0,0 +1,571 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_dtsec.h" + +void fman_dtsec_stop_rx(struct dtsec_regs __iomem *regs) +{ + /* Assert the graceful stop bit */ + iowrite32be(ioread32be(®s->rctrl) | RCTRL_GRS, ®s->rctrl); +} + +void fman_dtsec_stop_tx(struct dtsec_regs __iomem *regs) +{ + /* Assert the graceful stop bit */ + iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_GTS, ®s->tctrl); +} + +void fman_dtsec_start_tx(struct dtsec_regs __iomem *regs) +{ + /* clear the graceful stop bit */ + iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS, ®s->tctrl); +} + +void fman_dtsec_start_rx(struct dtsec_regs __iomem *regs) +{ + /* clear the graceful stop bit */ + iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS, ®s->rctrl); +} + +void fman_dtsec_defconfig(struct dtsec_cfg *cfg) +{ + cfg->halfdup_on = DEFAULT_HALFDUP_ON; + cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT; + cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW; + cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER; + cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF; + cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF; + cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL; + cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN; + cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST; + cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM; + cfg->rx_len_check = DEFAULT_RX_LEN_CHECK; + cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC; + cfg->tx_crc = DEFAULT_TX_CRC; + cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC; + cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME; + /* PHY address 0 is reserved (DPAA RM) */ + cfg->tbipa = DEFAULT_TBIPA; + cfg->rx_prepend = DEFAULT_RX_PREPEND; + cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN; + cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN; + cfg->preamble_len = DEFAULT_PREAMBLE_LEN; + cfg->rx_preamble = DEFAULT_RX_PREAMBLE; + cfg->tx_preamble = DEFAULT_TX_PREAMBLE; + cfg->loopback = DEFAULT_LOOPBACK; + cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN; + cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN; + cfg->rx_flow = DEFAULT_RX_FLOW; + cfg->tx_flow = DEFAULT_TX_FLOW; + cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD; + cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD; + cfg->rx_promisc = DEFAULT_RX_PROMISC; + cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1; + cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2; + cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT; + cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG; + cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME; + cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR; + cfg->wake_on_lan = DEFAULT_WAKE_ON_LAN; +} + +int fman_dtsec_init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg, + enum enet_interface iface_mode, + enum enet_speed iface_speed, + uint8_t *macaddr, + uint8_t __maybe_unused fm_rev_maj, + uint8_t __maybe_unused fm_rev_min, uint32_t exception_mask) +{ + bool is_rgmii, is_sgmii, is_qsgmii; + int i; + uint32_t tmp; + + /* let's start with a soft reset */ + iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); + iowrite32be(0, ®s->maccfg1); + + /*dtsec_id2*/ + tmp = ioread32be(®s->tsec_id2); + + /* check RGMII support */ + if (iface_mode == E_ENET_IF_RGMII || iface_mode == E_ENET_IF_RMII) + if (tmp & DTSEC_ID2_INT_REDUCED_OFF) + return -EINVAL; + + if (iface_mode == E_ENET_IF_SGMII || iface_mode == E_ENET_IF_MII) + if (tmp & DTSEC_ID2_INT_REDUCED_OFF) + return -EINVAL; + + /*ECNTRL*/ + + is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? true : false); + is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? true : false); + is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? true : false); + + tmp = 0; + if (is_rgmii || iface_mode == E_ENET_IF_GMII) + tmp |= DTSEC_ECNTRL_GMIIM; + if (is_sgmii) + tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); + if (is_qsgmii) + tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | + DTSEC_ECNTRL_QSGMIIM); + if (is_rgmii) + tmp |= DTSEC_ECNTRL_RPM; + if (iface_speed == E_ENET_SPEED_100) + tmp |= DTSEC_ECNTRL_R100M; + + iowrite32be(tmp, ®s->ecntrl); + /*ECNTRL*/ + + /*TCTRL*/ + tmp = 0; + if (cfg->halfdup_on) + tmp |= DTSEC_TCTRL_THDF; + if (cfg->tx_time_stamp_en) + tmp |= DTSEC_TCTRL_TTSE; + + iowrite32be(tmp, ®s->tctrl); + + /*TCTRL*/ + + /*PTV*/ + tmp = 0; + +#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 + if ((fm_rev_maj == 1) && (fm_rev_min == 0)) + cfg->tx_pause_time += 2; +#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */ + + if (cfg->tx_pause_time) + tmp |= cfg->tx_pause_time; + if (cfg->tx_pause_time_extd) + tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST; + iowrite32be(tmp, ®s->ptv); + + /*RCTRL*/ + tmp = 0; + tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16; + if (cfg->rx_ctrl_acc) + tmp |= RCTRL_CFA; + if (cfg->rx_group_hash_exd) + tmp |= RCTRL_GHTX; + if (cfg->rx_time_stamp_en) + tmp |= RCTRL_RTSE; + if (cfg->rx_drop_bcast) + tmp |= RCTRL_BC_REJ; + if (cfg->rx_short_frm) + tmp |= RCTRL_RSF; + if (cfg->rx_promisc) + tmp |= RCTRL_PROM; + + iowrite32be(tmp, ®s->rctrl); + /*RCTRL*/ + + /*Assign a Phy Address to the TBI (TBIPA). + *Done also in cases where TBI is not selected to avoid conflict with + *the external PHY's Physical address + */ + iowrite32be(cfg->tbipa, ®s->tbipa); + + /*TMR_CTL*/ + iowrite32be(0, ®s->tmr_ctrl); + + if (cfg->ptp_tsu_en) { + tmp = 0; + tmp |= TMR_PEVENT_TSRE; + iowrite32be(tmp, ®s->tmr_pevent); + + if (cfg->ptp_exception_en) { + tmp = 0; + tmp |= TMR_PEMASK_TSREEN; + iowrite32be(tmp, ®s->tmr_pemask); + } + } + + /*MACCFG1*/ + tmp = 0; + if (cfg->loopback) + tmp |= MACCFG1_LOOPBACK; + if (cfg->rx_flow) + tmp |= MACCFG1_RX_FLOW; + if (cfg->tx_flow) + tmp |= MACCFG1_TX_FLOW; + iowrite32be(tmp, ®s->maccfg1); + + /*MACCFG1*/ + + /*MACCFG2*/ + tmp = 0; + + if (iface_speed < E_ENET_SPEED_1000) + tmp |= MACCFG2_NIBBLE_MODE; + else if (iface_speed == E_ENET_SPEED_1000) + tmp |= MACCFG2_BYTE_MODE; + + tmp |= ((uint32_t)cfg->preamble_len & 0x0000000f) + << PREAMBLE_LENGTH_SHIFT; + + if (cfg->rx_preamble) + tmp |= MACCFG2_PRE_AM_RX_EN; + if (cfg->tx_preamble) + tmp |= MACCFG2_PRE_AM_TX_EN; + if (cfg->rx_len_check) + tmp |= MACCFG2_LENGTH_CHECK; + if (cfg->tx_pad_crc) + tmp |= MACCFG2_PAD_CRC_EN; + if (cfg->tx_crc) + tmp |= MACCFG2_CRC_EN; + if (!cfg->halfdup_on) + tmp |= MACCFG2_FULL_DUPLEX; + iowrite32be(tmp, ®s->maccfg2); + + /*MACCFG2*/ + + /*IPGIFG*/ + tmp = (((cfg->non_back_to_back_ipg1 << + IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT) + & IPGIFG_NON_BACK_TO_BACK_IPG_1) + | ((cfg->non_back_to_back_ipg2 << + IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT) + & IPGIFG_NON_BACK_TO_BACK_IPG_2) + | ((cfg->min_ifg_enforcement << IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT) + & IPGIFG_MIN_IFG_ENFORCEMENT) + | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG)); + iowrite32be(tmp, ®s->ipgifg); + + /*IPGIFG*/ + + /*HAFDUP*/ + tmp = 0; + + if (cfg->halfdup_alt_backoff_en) + tmp = (uint32_t)(HAFDUP_ALT_BEB | + ((cfg->halfdup_alt_backoff_val & 0x0000000f) + << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT)); + if (cfg->halfdup_bp_no_backoff) + tmp |= HAFDUP_BP_NO_BACKOFF; + if (cfg->halfdup_no_backoff) + tmp |= HAFDUP_NO_BACKOFF; + if (cfg->halfdup_excess_defer) + tmp |= HAFDUP_EXCESS_DEFER; + tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT) + & HAFDUP_RETRANSMISSION_MAX); + tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW); + + iowrite32be(tmp, ®s->hafdup); + /*HAFDUP*/ + + /*MAXFRM*/ + /* Initialize MAXFRM */ + iowrite32be(cfg->maximum_frame, ®s->maxfrm); + + /*MAXFRM*/ + + /*CAM1*/ + iowrite32be(0xffffffff, ®s->cam1); + iowrite32be(0xffffffff, ®s->cam2); + + /*IMASK*/ + iowrite32be(exception_mask, ®s->imask); + /*IMASK*/ + + /*IEVENT*/ + iowrite32be(0xffffffff, ®s->ievent); + + /*MACSTNADDR1/2*/ + + tmp = (uint32_t)((macaddr[5] << 24) | + (macaddr[4] << 16) | (macaddr[3] << 8) | macaddr[2]); + iowrite32be(tmp, ®s->macstnaddr1); + + tmp = (uint32_t)((macaddr[1] << 24) | (macaddr[0] << 16)); + iowrite32be(tmp, ®s->macstnaddr2); + + /*MACSTNADDR1/2*/ + + /*HASH*/ + for (i = 0; i < NUM_OF_HASH_REGS; i++) { + /* Initialize IADDRx */ + iowrite32be(0, ®s->igaddr[i]); + /* Initialize GADDRx */ + iowrite32be(0, ®s->gaddr[i]); + } + + return 0; +} + +uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs __iomem *regs) +{ + return (uint16_t)ioread32be(®s->maxfrm); +} + +void fman_dtsec_set_max_frame_len(struct dtsec_regs __iomem *regs, + uint16_t length) +{ + iowrite32be(length, ®s->maxfrm); +} + +void fman_dtsec_set_mac_address(struct dtsec_regs __iomem *regs, uint8_t *adr) +{ + uint32_t tmp; + + tmp = (uint32_t)((adr[5] << 24) | + (adr[4] << 16) | (adr[3] << 8) | adr[2]); + iowrite32be(tmp, ®s->macstnaddr1); + + tmp = (uint32_t)((adr[1] << 24) | (adr[0] << 16)); + iowrite32be(tmp, ®s->macstnaddr2); +} + +void fman_dtsec_get_mac_address(struct dtsec_regs __iomem *regs, + uint8_t *macaddr) +{ + uint32_t tmp1, tmp2; + + tmp1 = ioread32be(®s->macstnaddr1); + tmp2 = ioread32be(®s->macstnaddr2); + + macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16); + macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24); + macaddr[2] = (uint8_t)(tmp1 & 0x000000ff); + macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8); + macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16); + macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24); +} + +void fman_dtsec_set_bucket(struct dtsec_regs __iomem *regs, int bucket, + bool enable) +{ + int reg_idx = (bucket >> 5) & 0xf; + int bit_idx = bucket & 0x1f; + uint32_t bit_mask = 0x80000000 >> bit_idx; + uint32_t __iomem *reg; + + if (reg_idx > 7) + reg = ®s->gaddr[reg_idx - 8]; + else + reg = ®s->igaddr[reg_idx]; + + if (enable) + iowrite32be(ioread32be(reg) | bit_mask, reg); + else + iowrite32be(ioread32be(reg) & (~bit_mask), reg); +} + +int fman_dtsec_adjust_link(struct dtsec_regs __iomem *regs, + enum enet_interface __maybe_unused iface_mode, + enum enet_speed speed, bool full_dx) +{ + uint32_t tmp; + + if ((speed == E_ENET_SPEED_1000) && !full_dx) + return -EINVAL; + + tmp = ioread32be(®s->maccfg2); + if (!full_dx) + tmp &= ~MACCFG2_FULL_DUPLEX; + else + tmp |= MACCFG2_FULL_DUPLEX; + + tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); + if (speed < E_ENET_SPEED_1000) + tmp |= MACCFG2_NIBBLE_MODE; + else if (speed == E_ENET_SPEED_1000) + tmp |= MACCFG2_BYTE_MODE; + iowrite32be(tmp, ®s->maccfg2); + + tmp = ioread32be(®s->ecntrl); + if (speed == E_ENET_SPEED_100) + tmp |= DTSEC_ECNTRL_R100M; + else + tmp &= ~DTSEC_ECNTRL_R100M; + iowrite32be(tmp, ®s->ecntrl); + + return 0; +} + +void fman_dtsec_set_uc_promisc(struct dtsec_regs __iomem *regs, bool enable) +{ + uint32_t tmp; + + tmp = ioread32be(®s->rctrl); + + if (enable) + tmp |= RCTRL_UPROM; + else + tmp &= ~RCTRL_UPROM; + + iowrite32be(tmp, ®s->rctrl); +} + +void fman_dtsec_set_mc_promisc(struct dtsec_regs __iomem *regs, bool enable) +{ + uint32_t tmp; + + tmp = ioread32be(®s->rctrl); + + if (enable) + tmp |= RCTRL_MPROM; + else + tmp &= ~RCTRL_MPROM; + + iowrite32be(tmp, ®s->rctrl); +} + +void fman_dtsec_enable(struct dtsec_regs __iomem *regs, bool apply_rx, + bool apply_tx) +{ + uint32_t tmp; + + tmp = ioread32be(®s->maccfg1); + + if (apply_rx) + tmp |= MACCFG1_RX_EN; + + if (apply_tx) + tmp |= MACCFG1_TX_EN; + + iowrite32be(tmp, ®s->maccfg1); +} + +void fman_dtsec_disable(struct dtsec_regs __iomem *regs, bool apply_rx, + bool apply_tx) +{ + uint32_t tmp; + + tmp = ioread32be(®s->maccfg1); + + if (apply_rx) + tmp &= ~MACCFG1_RX_EN; + + if (apply_tx) + tmp &= ~MACCFG1_TX_EN; + + iowrite32be(tmp, ®s->maccfg1); +} + +void fman_dtsec_set_tx_pause_frames(struct dtsec_regs __iomem *regs, + uint16_t time) +{ + uint32_t ptv = 0; + + /* fixme: don't enable tx pause for half-duplex */ + + if (time) { + ptv = ioread32be(®s->ptv); + ptv &= 0xffff0000; + ptv |= time & 0x0000ffff; + iowrite32be(ptv, ®s->ptv); + + /* trigger the transmission of a flow-control pause frame */ + iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW, + ®s->maccfg1); + } else + iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, + ®s->maccfg1); +} + +void fman_dtsec_handle_rx_pause(struct dtsec_regs __iomem *regs, bool en) +{ + uint32_t tmp; + + /* todo: check if mac is set to full-duplex */ + + tmp = ioread32be(®s->maccfg1); + if (en) + tmp |= MACCFG1_RX_FLOW; + else + tmp &= ~MACCFG1_RX_FLOW; + iowrite32be(tmp, ®s->maccfg1); +} + +uint32_t fman_dtsec_get_rctrl(struct dtsec_regs __iomem *regs) +{ + return ioread32be(®s->rctrl); +} + +uint32_t fman_dtsec_get_revision(struct dtsec_regs __iomem *regs) +{ + return ioread32be(®s->tsec_id); +} + +uint32_t fman_dtsec_get_event(struct dtsec_regs __iomem *regs, + uint32_t ev_mask) +{ + return ioread32be(®s->ievent) & ev_mask; +} + +void fman_dtsec_ack_event(struct dtsec_regs __iomem *regs, uint32_t ev_mask) +{ + iowrite32be(ev_mask, ®s->ievent); +} + +uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs __iomem *regs) +{ + return ioread32be(®s->imask); +} + +uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs __iomem *regs) +{ + uint32_t event; + + event = ioread32be(®s->tmr_pevent); + event &= ioread32be(®s->tmr_pemask); + + if (event) + iowrite32be(event, ®s->tmr_pevent); + return event; +} + +void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs __iomem *regs) +{ + iowrite32be(ioread32be(®s->tmr_pemask) | TMR_PEMASK_TSREEN, + ®s->tmr_pemask); +} + +void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs __iomem *regs) +{ + iowrite32be(ioread32be(®s->tmr_pemask) & ~TMR_PEMASK_TSREEN, + ®s->tmr_pemask); +} + +void fman_dtsec_enable_interrupt(struct dtsec_regs __iomem *regs, + uint32_t ev_mask) +{ + iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); +} + +void fman_dtsec_disable_interrupt(struct dtsec_regs __iomem *regs, + uint32_t ev_mask) +{ + iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); +} diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c new file mode 100644 index 0000000..c393938 --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c @@ -0,0 +1,168 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "common/general.h" +#include "fsl_fman_dtsec_mii_acc.h" + +/*dtsec_mii_get_div() - calculates the value of the dtsec mii divider + *@dtsec_freq: dtsec clock frequency (in Mhz) + *This function calculates the dtsec mii clock divider that determines + *the MII MDC clock. MII MDC clock will be set to work in the range + *of 1.5 to 2.5Mhz + *The output of this function is the value of MIIMCFG[MgmtClk] which + *implicitly determines the divider value. + *Note: the dTSEC system clock is equal to 1/2 of the FMan clock. + *The table below which reflects dtsec_mii_get_div() functionality + *shows the relations among dtsec_freq, MgmtClk, actual divider + *and the MII frequency: + *dtsec freq MgmtClk div MII freq Mhz + *[0.....80] 1 (1/4)(1/8) [0 to 2.5] + *[81...120] 2 (1/6)(1/8) [1.6 to 2.5] + *[121..160] 3 (1/8)(1/8) [1.8 to 2.5] + *[161..200] 4 (1/10)(1/8) [2.0 to 2.5] + *[201..280] 5 (1/14)(1/8) [1.8 to 2.5] + *[281..400] 6 (1/20)(1/8) [1.1 to 2.5] + *[401..560] 7 (1/28)(1/8) [1.8 to 2.5] + *[560..frq] 7 (1/28)(1/8) [frq/224] + *Returns: the MIIMCFG[MgmtClk] appropriate value + */ + +static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq) +{ + uint16_t mgmt_clk; + + if (dtsec_freq < 80) + mgmt_clk = 1; + else if (dtsec_freq < 120) + mgmt_clk = 2; + else if (dtsec_freq < 160) + mgmt_clk = 3; + else if (dtsec_freq < 200) + mgmt_clk = 4; + else if (dtsec_freq < 280) + mgmt_clk = 5; + else if (dtsec_freq < 400) + mgmt_clk = 6; + else + mgmt_clk = 7; + + return (uint8_t)mgmt_clk; +} + +void fman_dtsec_mii_reset(struct dtsec_mii_reg __iomem *regs) +{ + /* Reset the management interface */ + iowrite32be(ioread32be(®s->miimcfg) | MIIMCFG_RESET_MGMT, + ®s->miimcfg); + iowrite32be(ioread32be(®s->miimcfg) & ~MIIMCFG_RESET_MGMT, + ®s->miimcfg); +} + +int fman_dtsec_mii_write_reg(struct dtsec_mii_reg __iomem *regs, uint8_t addr, + uint8_t reg, uint16_t data, uint16_t dtsec_freq) +{ + uint32_t tmp; + + /* Setup the MII Mgmt clock speed */ + iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg); + /* Memory barrier */ + wmb(); + + /* Stop the MII management read cycle */ + iowrite32be(0, ®s->miimcom); + /* Dummy read to make sure MIIMCOM is written */ + tmp = ioread32be(®s->miimcom); + /* Memory barrier */ + wmb(); + + /* Setting up MII Management Address Register */ + tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg); + iowrite32be(tmp, ®s->miimadd); + /* Memory barrier */ + wmb(); + + /* Setting up MII Management Control Register with data */ + iowrite32be((uint32_t)data, ®s->miimcon); + /* Dummy read to make sure MIIMCON is written */ + tmp = ioread32be(®s->miimcon); + /* Memory barrier */ + wmb(); + + /* Wait until MII management write is complete */ + /* todo: a timeout could be useful here */ + while ((ioread32be(®s->miimind)) & MIIMIND_BUSY) + ; /* busy wait */ + + return 0; +} + +int fman_dtsec_mii_read_reg(struct dtsec_mii_reg __iomem *regs, uint8_t addr, + uint8_t reg, uint16_t *data, uint16_t dtsec_freq) +{ + uint32_t tmp; + + /* Setup the MII Mgmt clock speed */ + iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg); + /* Memory barrier */ + wmb(); + + /* Setting up the MII Management Address Register */ + tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg); + iowrite32be(tmp, ®s->miimadd); + /* Memory barrier */ + wmb(); + + /* Perform an MII management read cycle */ + iowrite32be(MIIMCOM_READ_CYCLE, ®s->miimcom); + /* Dummy read to make sure MIIMCOM is written */ + tmp = ioread32be(®s->miimcom); + /* Memory barrier */ + wmb(); + + /* Wait until MII management read is complete */ + /* todo: a timeout could be useful here */ + while ((ioread32be(®s->miimind)) & MIIMIND_BUSY) + ; /* busy wait */ + + /* Read MII management status */ + *data = (uint16_t)ioread32be(®s->miimstat); + /* Memory barrier */ + wmb(); + + iowrite32be(0, ®s->miimcom); + /* Dummy read to make sure MIIMCOM is written */ + tmp = ioread32be(®s->miimcom); + + if (*data == 0xffff) + return -ENXIO; + + return 0; +} diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_memac.c b/drivers/net/ethernet/freescale/fman/mac/fman_memac.c new file mode 100644 index 0000000..e0bac5a --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/mac/fman_memac.c @@ -0,0 +1,365 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_memac.h" + +uint32_t fman_memac_get_event(struct memac_regs __iomem *regs, uint32_t ev_mask) +{ + return ioread32be(®s->ievent) & ev_mask; +} + +uint32_t fman_memac_get_interrupt_mask(struct memac_regs __iomem *regs) +{ + return ioread32be(®s->imask); +} + +void fman_memac_ack_event(struct memac_regs __iomem *regs, uint32_t ev_mask) +{ + iowrite32be(ev_mask, ®s->ievent); +} + +void fman_memac_set_promiscuous(struct memac_regs __iomem *regs, bool val) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + + if (val) + tmp |= CMD_CFG_PROMIS_EN; + else + tmp &= ~CMD_CFG_PROMIS_EN; + + iowrite32be(tmp, ®s->command_config); +} + +void fman_memac_clear_addr_in_paddr(struct memac_regs __iomem *regs, + uint8_t paddr_num) +{ + if (paddr_num == 0) { + iowrite32be(0, ®s->mac_addr0.mac_addr_l); + iowrite32be(0, ®s->mac_addr0.mac_addr_u); + } else { + iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_l); + iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_u); + } +} + +void fman_memac_add_addr_in_paddr(struct memac_regs __iomem *regs, + uint8_t *adr, uint8_t paddr_num) +{ + uint32_t tmp0, tmp1; + + tmp0 = (uint32_t)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24); + tmp1 = (uint32_t)(adr[4] | adr[5] << 8); + + if (paddr_num == 0) { + iowrite32be(tmp0, ®s->mac_addr0.mac_addr_l); + iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u); + } else { + iowrite32be(tmp0, ®s->mac_addr[paddr_num - 1].mac_addr_l); + iowrite32be(tmp1, ®s->mac_addr[paddr_num - 1].mac_addr_u); + } +} + +void fman_memac_enable(struct memac_regs __iomem *regs, bool apply_rx, + bool apply_tx) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + + if (apply_rx) + tmp |= CMD_CFG_RX_EN; + + if (apply_tx) + tmp |= CMD_CFG_TX_EN; + + iowrite32be(tmp, ®s->command_config); +} + +void fman_memac_disable(struct memac_regs __iomem *regs, bool apply_rx, + bool apply_tx) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + + if (apply_rx) + tmp &= ~CMD_CFG_RX_EN; + + if (apply_tx) + tmp &= ~CMD_CFG_TX_EN; + + iowrite32be(tmp, ®s->command_config); +} + +void fman_memac_reset(struct memac_regs __iomem *regs) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + + tmp |= CMD_CFG_SW_RESET; + + iowrite32be(tmp, ®s->command_config); + + while (ioread32be(®s->command_config) & CMD_CFG_SW_RESET) + ; +} + +int fman_memac_init(struct memac_regs __iomem *regs, + struct memac_cfg *cfg, + enum enet_interface enet_interface, + enum enet_speed enet_speed, + bool slow_10g_if, + uint32_t exceptions) +{ + uint32_t tmp; + + /* Config */ + tmp = 0; + if (cfg->wan_mode_enable) + tmp |= CMD_CFG_WAN_MODE; + if (cfg->promiscuous_mode_enable) + tmp |= CMD_CFG_PROMIS_EN; + if (cfg->pause_forward_enable) + tmp |= CMD_CFG_PAUSE_FWD; + if (cfg->pause_ignore) + tmp |= CMD_CFG_PAUSE_IGNORE; + if (cfg->tx_addr_ins_enable) + tmp |= CMD_CFG_TX_ADDR_INS; + if (cfg->loopback_enable) + tmp |= CMD_CFG_LOOPBACK_EN; + if (cfg->cmd_frame_enable) + tmp |= CMD_CFG_CNT_FRM_EN; + if (cfg->send_idle_enable) + tmp |= CMD_CFG_SEND_IDLE; + if (cfg->no_length_check_enable) + tmp |= CMD_CFG_NO_LEN_CHK; + if (cfg->rx_sfd_any) + tmp |= CMD_CFG_SFD_ANY; + if (cfg->pad_enable) + tmp |= CMD_CFG_TX_PAD_EN; + if (cfg->wake_on_lan) + tmp |= CMD_CFG_MG; + + tmp |= CMD_CFG_CRC_FWD; + + iowrite32be(tmp, ®s->command_config); + + /* Max Frame Length */ + iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); + + /* Pause Time */ + iowrite32be((uint32_t)cfg->pause_quanta, ®s->pause_quanta[0]); + iowrite32be((uint32_t)0, ®s->pause_thresh[0]); + + /* IF_MODE */ + tmp = 0; + switch (enet_interface) { + case E_ENET_IF_XGMII: + case E_ENET_IF_XFI: + tmp |= IF_MODE_XGMII; + break; + default: + tmp |= IF_MODE_GMII; + if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable) + tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; + } + iowrite32be(tmp, ®s->if_mode); + + /* TX_FIFO_SECTIONS */ + tmp = 0; + if (enet_interface == E_ENET_IF_XGMII || + enet_interface == E_ENET_IF_XFI) { + if (slow_10g_if) { + tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | + TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); + } else { + tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | + TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); + } + } else { + tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | + TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); + } + iowrite32be(tmp, ®s->tx_fifo_sections); + + /* clear all pending events and set-up interrupts */ + fman_memac_ack_event(regs, 0xffffffff); + fman_memac_set_exception(regs, exceptions, true); + + return 0; +} + +void fman_memac_set_exception(struct memac_regs __iomem *regs, uint32_t val, + bool enable) +{ + uint32_t tmp; + + tmp = ioread32be(®s->imask); + if (enable) + tmp |= val; + else + tmp &= ~val; + + iowrite32be(tmp, ®s->imask); +} + +void fman_memac_set_hash_table(struct memac_regs __iomem *regs, uint32_t val) +{ + iowrite32be(val, ®s->hashtable_ctrl); +} + +uint16_t fman_memac_get_max_frame_len(struct memac_regs __iomem *regs) +{ + uint32_t tmp; + + tmp = ioread32be(®s->maxfrm); + + return (uint16_t)tmp; +} + +void fman_memac_set_tx_pause_frames(struct memac_regs __iomem *regs, + uint8_t priority, + uint16_t pause_time, uint16_t thresh_time) +{ + uint32_t tmp; + + tmp = ioread32be(®s->tx_fifo_sections); + + GET_TX_EMPTY_DEFAULT_VALUE(tmp); + iowrite32be(tmp, ®s->tx_fifo_sections); + + tmp = ioread32be(®s->command_config); + tmp &= ~CMD_CFG_PFC_MODE; + priority = 0; + + iowrite32be(tmp, ®s->command_config); + + tmp = ioread32be(®s->pause_quanta[priority / 2]); + if (priority % 2) + tmp &= 0x0000FFFF; + else + tmp &= 0xFFFF0000; + tmp |= ((uint32_t)pause_time << (16 * (priority % 2))); + iowrite32be(tmp, ®s->pause_quanta[priority / 2]); + + tmp = ioread32be(®s->pause_thresh[priority / 2]); + if (priority % 2) + tmp &= 0x0000FFFF; + else + tmp &= 0xFFFF0000; + tmp |= ((uint32_t)thresh_time << (16 * (priority % 2))); + iowrite32be(tmp, ®s->pause_thresh[priority / 2]); +} + +void fman_memac_set_rx_ignore_pause_frames(struct memac_regs __iomem *regs, + bool enable) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + if (enable) + tmp |= CMD_CFG_PAUSE_IGNORE; + else + tmp &= ~CMD_CFG_PAUSE_IGNORE; + + iowrite32be(tmp, ®s->command_config); +} + +void fman_memac_adjust_link(struct memac_regs __iomem *regs, + enum enet_interface iface_mode, + enum enet_speed speed, bool full_dx) +{ + uint32_t tmp; + + tmp = ioread32be(®s->if_mode); + + if (full_dx) + tmp &= ~IF_MODE_HD; + else + tmp |= IF_MODE_HD; + + if (iface_mode == E_ENET_IF_RGMII) { + /* Configure RGMII in manual mode */ + tmp &= ~IF_MODE_RGMII_AUTO; + tmp &= ~IF_MODE_RGMII_SP_MASK; + + if (full_dx) + tmp |= IF_MODE_RGMII_FD; + else + tmp &= ~IF_MODE_RGMII_FD; + + switch (speed) { + case E_ENET_SPEED_1000: + tmp |= IF_MODE_RGMII_1000; + break; + case E_ENET_SPEED_100: + tmp |= IF_MODE_RGMII_100; + break; + case E_ENET_SPEED_10: + tmp |= IF_MODE_RGMII_10; + break; + default: + break; + } + } + + iowrite32be(tmp, ®s->if_mode); +} + +void fman_memac_defconfig(struct memac_cfg *cfg) +{ + cfg->reset_on_init = false; + cfg->wan_mode_enable = false; + cfg->promiscuous_mode_enable = false; + cfg->pause_forward_enable = false; + cfg->pause_ignore = false; + cfg->tx_addr_ins_enable = false; + cfg->loopback_enable = false; + cfg->cmd_frame_enable = false; + cfg->rx_error_discard = false; + cfg->send_idle_enable = false; + cfg->no_length_check_enable = true; + cfg->lgth_check_nostdr = false; + cfg->time_stamp_enable = false; + cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; + cfg->max_frame_length = DEFAULT_FRAME_LENGTH; + cfg->pause_quanta = DEFAULT_PAUSE_QUANTA; + cfg->pad_enable = true; + cfg->phy_tx_ena_on = false; + cfg->rx_sfd_any = false; + cfg->rx_pbl_fwd = false; + cfg->tx_pbl_fwd = false; + cfg->debug_mode = false; + cfg->wake_on_lan = false; +} diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c new file mode 100644 index 0000000..7addd6d --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c @@ -0,0 +1,217 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_memac_mii_acc.h" + +static void write_phy_reg_10g(struct memac_mii_access_mem_map __iomem *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t data) +{ + uint32_t tmp_reg; + + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + /* Leave only MDIO_CLK_DIV bits set on */ + tmp_reg &= MDIO_CFG_CLK_DIV_MASK; + /* Set maximum MDIO_HOLD value to allow phy to see + * change of data signal + **/ + tmp_reg |= MDIO_CFG_HOLD_MASK; + /* Add 10G interface mode */ + tmp_reg |= MDIO_CFG_ENC45; + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Specify phy and register to be accessed */ + iowrite32be(phy_addr, &mii_regs->mdio_ctrl); + iowrite32be(reg, &mii_regs->mdio_addr); + /* memory barrier */ + wmb(); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Write data */ + iowrite32be(data, &mii_regs->mdio_data); + /* memory barrier */ + wmb(); + + /* Wait for write transaction end */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); +} + +static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map __iomem + *mii_regs, uint8_t phy_addr, uint8_t reg, + uint16_t *data) +{ + uint32_t tmp_reg; + + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + /* Leave only MDIO_CLK_DIV bits set on */ + tmp_reg &= MDIO_CFG_CLK_DIV_MASK; + /* Set maximum MDIO_HOLD value to allow phy to see + * change of data signal + **/ + tmp_reg |= MDIO_CFG_HOLD_MASK; + /* Add 10G interface mode */ + tmp_reg |= MDIO_CFG_ENC45; + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Specify phy and register to be accessed */ + iowrite32be(phy_addr, &mii_regs->mdio_ctrl); + iowrite32be(reg, &mii_regs->mdio_addr); + /* memory barrier */ + wmb(); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Read cycle */ + tmp_reg = phy_addr; + tmp_reg |= MDIO_CTL_READ; + iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); + /* memory barrier */ + wmb(); + + /* Wait for data to be available */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); + + *data = (uint16_t)ioread32be(&mii_regs->mdio_data); + + /* Check if there was an error */ + return ioread32be(&mii_regs->mdio_cfg); +} + +static void write_phy_reg_1g(struct memac_mii_access_mem_map __iomem *mii_regs, + uint8_t phy_addr, uint8_t reg, uint16_t data) +{ + uint32_t tmp_reg; + + /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Write transaction */ + tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); + tmp_reg |= reg; + iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + iowrite32be(data, &mii_regs->mdio_data); + + /* memory barrier */ + wmb(); + + /* Wait for write transaction to end */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); +} + +static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map __iomem + *mii_regs, uint8_t phy_addr, uint8_t reg, + uint16_t *data) +{ + uint32_t tmp_reg; + + /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ + tmp_reg = ioread32be(&mii_regs->mdio_cfg); + tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); + iowrite32be(tmp_reg, &mii_regs->mdio_cfg); + + /* Wait for command completion */ + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Read transaction */ + tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); + tmp_reg |= reg; + tmp_reg |= MDIO_CTL_READ; + iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); + + while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) + udelay(1); + + /* Wait for data to be available */ + while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) + udelay(1); + + *data = (uint16_t)ioread32be(&mii_regs->mdio_data); + + /* Check error */ + return ioread32be(&mii_regs->mdio_cfg); +} + +int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map __iomem + *mii_regs, uint8_t phy_addr, uint8_t reg, + uint16_t data, enum enet_speed enet_speed) +{ + /* Figure out interface type - 10G vs 1G. + * In 10G interface both phy_addr and devAddr present. + **/ + if (enet_speed == E_ENET_SPEED_10000) + write_phy_reg_10g(mii_regs, phy_addr, reg, data); + else + write_phy_reg_1g(mii_regs, phy_addr, reg, data); + + return 0; +} + +int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map __iomem + *mii_regs, uint8_t phy_addr, uint8_t reg, + uint16_t *data, enum enet_speed enet_speed) +{ + uint32_t ans; + /* Figure out interface type - 10G vs 1G. + * In 10G interface both phy_addr and devAddr present. + **/ + if (enet_speed == E_ENET_SPEED_10000) + ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data); + else + ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data); + + if (ans & MDIO_CFG_READ_ERR) + return -EINVAL; + return 0; +} diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c b/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c new file mode 100644 index 0000000..11bcc1a --- /dev/null +++ b/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c @@ -0,0 +1,217 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 "fsl_fman_tgec.h" + +void fman_tgec_set_mac_address(struct tgec_regs __iomem *regs, uint8_t *adr) +{ + uint32_t tmp0, tmp1; + + tmp0 = (uint32_t)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24); + tmp1 = (uint32_t)(adr[4] | adr[5] << 8); + iowrite32be(tmp0, ®s->mac_addr_0); + iowrite32be(tmp1, ®s->mac_addr_1); +} + +void fman_tgec_enable(struct tgec_regs __iomem *regs, bool apply_rx, + bool apply_tx) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + if (apply_rx) + tmp |= CMD_CFG_RX_EN; + if (apply_tx) + tmp |= CMD_CFG_TX_EN; + iowrite32be(tmp, ®s->command_config); +} + +void fman_tgec_disable(struct tgec_regs __iomem *regs, bool apply_rx, + bool apply_tx) +{ + uint32_t tmp_reg_32; + + tmp_reg_32 = ioread32be(®s->command_config); + if (apply_rx) + tmp_reg_32 &= ~CMD_CFG_RX_EN; + if (apply_tx) + tmp_reg_32 &= ~CMD_CFG_TX_EN; + iowrite32be(tmp_reg_32, ®s->command_config); +} + +void fman_tgec_set_promiscuous(struct tgec_regs __iomem *regs, bool val) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + if (val) + tmp |= CMD_CFG_PROMIS_EN; + else + tmp &= ~CMD_CFG_PROMIS_EN; + iowrite32be(tmp, ®s->command_config); +} + +void fman_tgec_set_hash_table(struct tgec_regs __iomem *regs, uint32_t value) +{ + iowrite32be(value, ®s->hashtable_ctrl); +} + +void fman_tgec_set_tx_pause_frames(struct tgec_regs __iomem *regs, + uint16_t pause_time) +{ + iowrite32be((uint32_t)pause_time, ®s->pause_quant); +} + +void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs __iomem *regs, + bool en) +{ + uint32_t tmp; + + tmp = ioread32be(®s->command_config); + if (en) + tmp |= CMD_CFG_PAUSE_IGNORE; + else + tmp &= ~CMD_CFG_PAUSE_IGNORE; + iowrite32be(tmp, ®s->command_config); +} + +uint32_t fman_tgec_get_event(struct tgec_regs __iomem *regs, uint32_t ev_mask) +{ + return ioread32be(®s->ievent) & ev_mask; +} + +void fman_tgec_ack_event(struct tgec_regs __iomem *regs, uint32_t ev_mask) +{ + iowrite32be(ev_mask, ®s->ievent); +} + +uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs __iomem *regs) +{ + return ioread32be(®s->imask); +} + +uint32_t fman_tgec_get_revision(struct tgec_regs __iomem *regs) +{ + return ioread32be(®s->tgec_id); +} + +void fman_tgec_enable_interrupt(struct tgec_regs __iomem *regs, + uint32_t ev_mask) +{ + iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); +} + +void fman_tgec_disable_interrupt(struct tgec_regs __iomem *regs, + uint32_t ev_mask) +{ + iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); +} + +uint16_t fman_tgec_get_max_frame_len(struct tgec_regs __iomem *regs) +{ + return (uint16_t)ioread32be(®s->maxfrm); +} + +void fman_tgec_defconfig(struct tgec_cfg *cfg) +{ + cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE; + cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE; + cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE; + cfg->pause_ignore = DEFAULT_PAUSE_IGNORE; + cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE; + cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE; + cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE; + cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD; + cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE; + cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE; + cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR; + cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE; + cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; + cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH; + cfg->pause_quant = DEFAULT_PAUSE_QUANT; +#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 + cfg->skip_fman11_workaround = false; +#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ +} + +int fman_tgec_init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg, + uint32_t exception_mask) +{ + uint32_t tmp; + + /* Config */ + tmp = 0x40; /* CRC forward */ + if (cfg->wan_mode_enable) + tmp |= CMD_CFG_WAN_MODE; + if (cfg->promiscuous_mode_enable) + tmp |= CMD_CFG_PROMIS_EN; + if (cfg->pause_forward_enable) + tmp |= CMD_CFG_PAUSE_FWD; + if (cfg->pause_ignore) + tmp |= CMD_CFG_PAUSE_IGNORE; + if (cfg->tx_addr_ins_enable) + tmp |= CMD_CFG_TX_ADDR_INS; + if (cfg->loopback_enable) + tmp |= CMD_CFG_LOOPBACK_EN; + if (cfg->cmd_frame_enable) + tmp |= CMD_CFG_CMD_FRM_EN; + if (cfg->rx_error_discard) + tmp |= CMD_CFG_RX_ER_DISC; + if (cfg->send_idle_enable) + tmp |= CMD_CFG_SEND_IDLE; + if (cfg->no_length_check_enable) + tmp |= CMD_CFG_NO_LEN_CHK; + if (cfg->time_stamp_enable) + tmp |= CMD_CFG_EN_TIMESTAMP; + iowrite32be(tmp, ®s->command_config); + + /* Max Frame Length */ + iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); + /* Pause Time */ + iowrite32be(cfg->pause_quant, ®s->pause_quant); + + /* clear all pending events and set-up interrupts */ + fman_tgec_ack_event(regs, 0xffffffff); + fman_tgec_enable_interrupt(regs, exception_mask); + + return 0; +} + +void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs + __iomem *regs) +{ + uint32_t tmp; + + /* restore the default tx ipg Length */ + tmp = (ioread32be(®s->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12; + + iowrite32be(tmp, ®s->tx_ipg_len); +} -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/