From patchwork Fri Aug 2 03:18:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jitendra Vegiraju X-Patchwork-Id: 13751055 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1C14FC3DA64 for ; Fri, 2 Aug 2024 03:20:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=m+cvFAnzA/KfeQnxr7Zc1hChqdcfrDywPl6KTQXOFCI=; b=UDSCHTE9r10z3k1wHZ+c1cpunj MjlvYHaXAbGlRT6veWPrqG7tvbAHa2fNy9lrv9gduX/ie4cTl+qxXFfPonkIandcOJg3YwHXf6A3U 9njA72OFNwbcGVGIETk31+chxNhqGVCe0sbxwskbXooWSkYhi+/hsHGUJ1YzrnztSa3JSq+mKgxm+ B7dpZuZw7mqwK52+2IznpgfLX86kXBtO1ha6EOdZ6yfzVCa2RLnM478T+WfgLTF64Ry15dakPf+52 XDRfxn4vf0LmJoZyNPHWyH1P71qw+FNjDm/p2L71WmRG1tOQh2WVZVoOp1RcjijnlT/2+L0OLBrF5 YEOXtZOQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZipf-00000007T3B-3XCf; Fri, 02 Aug 2024 03:19:55 +0000 Received: from relay.smtp-ext.broadcom.com ([192.19.144.208]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZioH-00000007Sot-1kVP for linux-arm-kernel@lists.infradead.org; Fri, 02 Aug 2024 03:18:32 +0000 Received: from mail-lvn-it-01.lvn.broadcom.net (mail-lvn-it-01.lvn.broadcom.net [10.36.132.253]) by relay.smtp-ext.broadcom.com (Postfix) with ESMTP id E1BCBC0000F3; Thu, 1 Aug 2024 20:18:26 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 relay.smtp-ext.broadcom.com E1BCBC0000F3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com; s=dkimrelay; t=1722568707; bh=Z2OAuZ9IFuxjnq8oX7tr8assXRon6c+l328aPvNO0xg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MjHM+aMtflzmne2cZnu4D2vprFgpYs5d3ET1LpKSNhgjvqeY8f+j8NnADIjwXV/UV XjRmk63SQ+VAxyIPZbugA6vEUvEJ8Qj44B0eRUU8Zy+ffAfwVPpaEsbJMdxdGND5iI VUcv85PWfJkmaETdhXh6T50SezicFxHK9jWot0/o= Received: from pcie-dev03.dhcp.broadcom.net (pcie-dev03.dhcp.broadcom.net [10.59.171.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail-lvn-it-01.lvn.broadcom.net (Postfix) with ESMTPSA id 1997918041CAC6; Thu, 1 Aug 2024 20:18:24 -0700 (PDT) From: jitendra.vegiraju@broadcom.com To: netdev@vger.kernel.org Cc: alexandre.torgue@foss.st.com, joabreu@synopsys.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, jitendra.vegiraju@broadcom.com, bcm-kernel-feedback-list@broadcom.com, richardcochran@gmail.com, ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org, john.fastabend@gmail.com, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, horms@kernel.org, florian.fainelli@broadcom.com Subject: [PATCH net-next v3 1/3] net: stmmac: Add basic dwxgmac4 support to stmmac core Date: Thu, 1 Aug 2024 20:18:20 -0700 Message-Id: <20240802031822.1862030-2-jitendra.vegiraju@broadcom.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240802031822.1862030-1-jitendra.vegiraju@broadcom.com> References: <20240802031822.1862030-1-jitendra.vegiraju@broadcom.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240801_201829_652993_2C6B5D2F X-CRM114-Status: GOOD ( 22.49 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Jitendra Vegiraju Adds support for DWC_xgmac version 4.00a in stmmac core module. This version adds enhancements to DMA architecture for virtualization scalability. This is realized by decoupling physical DMA channels (PDMA) from Virtual DMA channels (VDMA). The VDMAs are software abastractions that map to PDMAs for frame transmission and reception. The virtualization enhancements are currently not being used and hence a fixed mapping of VDMA to PDMA is configured in the init functions. Because of the new init functions, a new instance of struct stmmac_dma_ops dwxgmac400_dma_ops is added. Most of the other dma operation functions in existing dwxgamc2_dma.c file can be reused. Signed-off-by: Jitendra Vegiraju --- drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 31 ++++ .../net/ethernet/stmicro/stmmac/dwxgmac4.c | 142 ++++++++++++++++++ .../net/ethernet/stmicro/stmmac/dwxgmac4.h | 84 +++++++++++ 4 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index c2f0e91f6bf8..2f637612513d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \ mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \ dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \ - stmmac_xdp.o stmmac_est.o \ + stmmac_xdp.o stmmac_est.o dwxgmac4.o \ $(stmmac-y) stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index dd2ab6185c40..c15f5247aaa8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -7,6 +7,7 @@ #include #include "stmmac.h" #include "dwxgmac2.h" +#include "dwxgmac4.h" static int dwxgmac2_dma_reset(void __iomem *ioaddr) { @@ -641,3 +642,33 @@ const struct stmmac_dma_ops dwxgmac210_dma_ops = { .enable_sph = dwxgmac2_enable_sph, .enable_tbs = dwxgmac2_enable_tbs, }; + +const struct stmmac_dma_ops dwxgmac400_dma_ops = { + .reset = dwxgmac2_dma_reset, + .init = dwxgmac4_dma_init, + .init_chan = dwxgmac2_dma_init_chan, + .init_rx_chan = dwxgmac4_dma_init_rx_chan, + .init_tx_chan = dwxgmac4_dma_init_tx_chan, + .axi = dwxgmac2_dma_axi, + .dump_regs = dwxgmac2_dma_dump_regs, + .dma_rx_mode = dwxgmac2_dma_rx_mode, + .dma_tx_mode = dwxgmac2_dma_tx_mode, + .enable_dma_irq = dwxgmac2_enable_dma_irq, + .disable_dma_irq = dwxgmac2_disable_dma_irq, + .start_tx = dwxgmac2_dma_start_tx, + .stop_tx = dwxgmac2_dma_stop_tx, + .start_rx = dwxgmac2_dma_start_rx, + .stop_rx = dwxgmac2_dma_stop_rx, + .dma_interrupt = dwxgmac2_dma_interrupt, + .get_hw_feature = dwxgmac2_get_hw_feature, + .rx_watchdog = dwxgmac2_rx_watchdog, + .set_rx_ring_len = dwxgmac2_set_rx_ring_len, + .set_tx_ring_len = dwxgmac2_set_tx_ring_len, + .set_rx_tail_ptr = dwxgmac2_set_rx_tail_ptr, + .set_tx_tail_ptr = dwxgmac2_set_tx_tail_ptr, + .enable_tso = dwxgmac2_enable_tso, + .qmode = dwxgmac2_qmode, + .set_bfsize = dwxgmac2_set_bfsize, + .enable_sph = dwxgmac2_enable_sph, + .enable_tbs = dwxgmac2_enable_tbs, +}; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c new file mode 100644 index 000000000000..9c8748122dc6 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2024 Broadcom Corporation + */ +#include "dwxgmac2.h" +#include "dwxgmac4.h" + +static int rd_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel) +{ + u32 reg_val = 0; + u32 val = 0; + + reg_val |= mode << XGMAC4_MSEL_SHIFT & XGMAC4_MODE_SELECT; + reg_val |= channel << XGMAC4_AOFF_SHIFT & XGMAC4_ADDR_OFFSET; + reg_val |= XGMAC4_CMD_TYPE | XGMAC4_OB; + writel(reg_val, ioaddr + XGMAC4_DMA_CH_IND_CONTROL); + val = readl(ioaddr + XGMAC4_DMA_CH_IND_DATA); + return val; +} + +static void wr_dma_ch_ind(void __iomem *ioaddr, u8 mode, u32 channel, u32 val) +{ + u32 reg_val = 0; + + writel(val, ioaddr + XGMAC4_DMA_CH_IND_DATA); + reg_val |= mode << XGMAC4_MSEL_SHIFT & XGMAC4_MODE_SELECT; + reg_val |= channel << XGMAC4_AOFF_SHIFT & XGMAC4_ADDR_OFFSET; + reg_val |= XGMAC_OB; + writel(reg_val, ioaddr + XGMAC4_DMA_CH_IND_CONTROL); +} + +static void xgmac4_tp2tc_map(void __iomem *ioaddr, u8 pdma_ch, u32 tc_num) +{ + u32 val = 0; + + val = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, pdma_ch); + val &= ~XGMAC4_TP2TCMP; + val |= tc_num << XGMAC4_TP2TCMP_SHIFT & XGMAC4_TP2TCMP; + wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, pdma_ch, val); +} + +static void xgmac4_rp2tc_map(void __iomem *ioaddr, u8 pdma_ch, u32 tc_num) +{ + u32 val = 0; + + val = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, pdma_ch); + val &= ~XGMAC4_RP2TCMP; + val |= tc_num << XGMAC4_RP2TCMP_SHIFT & XGMAC4_RP2TCMP; + wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, pdma_ch, val); +} + +void dwxgmac4_dma_init(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, int atds) +{ + u32 value; + u32 i; + + value = readl(ioaddr + XGMAC_DMA_SYSBUS_MODE); + + if (dma_cfg->aal) + value |= XGMAC_AAL; + + if (dma_cfg->eame) + value |= XGMAC_EAME; + + writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE); + + for (i = 0; i < VDMA_TOTAL_CH_COUNT; i++) { + value = rd_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, i); + value &= ~XGMAC4_TXDCSZ; + value |= 0x3; + value &= ~XGMAC4_TDPS; + value |= (3 << XGMAC4_TDPS_SHIFT) & XGMAC4_TDPS; + wr_dma_ch_ind(ioaddr, MODE_TXDESCCTRL, i, value); + + value = rd_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, i); + value &= ~XGMAC4_RXDCSZ; + value |= 0x3; + value &= ~XGMAC4_RDPS; + value |= (3 << XGMAC4_RDPS_SHIFT) & XGMAC4_RDPS; + wr_dma_ch_ind(ioaddr, MODE_RXDESCCTRL, i, value); + } + + for (i = 0; i < PDMA_TX_CH_COUNT; i++) { + value = rd_dma_ch_ind(ioaddr, MODE_TXEXTCFG, i); + value &= ~(XGMAC4_TXPBL | XGMAC4_TPBLX8_MODE); + if (dma_cfg->pblx8) + value |= XGMAC4_TPBLX8_MODE; + value |= (dma_cfg->pbl << XGMAC4_TXPBL_SHIFT) & XGMAC4_TXPBL; + wr_dma_ch_ind(ioaddr, MODE_TXEXTCFG, i, value); + xgmac4_tp2tc_map(ioaddr, i, i); + } + + for (i = 0; i < PDMA_RX_CH_COUNT; i++) { + value = rd_dma_ch_ind(ioaddr, MODE_RXEXTCFG, i); + value &= ~(XGMAC4_RXPBL | XGMAC4_RPBLX8_MODE); + if (dma_cfg->pblx8) + value |= XGMAC4_RPBLX8_MODE; + value |= (dma_cfg->pbl << XGMAC4_RXPBL_SHIFT) & XGMAC4_RXPBL; + wr_dma_ch_ind(ioaddr, MODE_RXEXTCFG, i, value); + if (i < PDMA_MAX_TC_COUNT) + xgmac4_rp2tc_map(ioaddr, i, i); + else + xgmac4_rp2tc_map(ioaddr, i, PDMA_MAX_TC_COUNT - 1); + } +} + +void dwxgmac4_dma_init_tx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan) +{ + u32 value; + + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + value &= ~XGMAC4_TVDMA2TCMP; + value |= (chan << XGMAC4_TVDMA2TCMP_SHIFT) & XGMAC4_TVDMA2TCMP; + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + + writel(upper_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan)); + writel(lower_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chan)); +} + +void dwxgmac4_dma_init_rx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan) +{ + u32 value; + + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + value &= ~XGMAC4_RVDMA2TCMP; + value |= (chan << XGMAC4_RVDMA2TCMP_SHIFT) & XGMAC4_RVDMA2TCMP; + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + + writel(upper_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan)); + writel(lower_32_bits(dma_addr), + ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chan)); +} diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h new file mode 100644 index 000000000000..0ce1856b0b34 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac4.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2024 Broadcom Corporation + * XGMAC4 definitions. + */ +#ifndef __STMMAC_DWXGMAC4_H__ +#define __STMMAC_DWXGMAC4_H__ + +/* DMA Indirect Registers*/ +#define XGMAC4_DMA_CH_IND_CONTROL 0X00003080 +#define XGMAC4_MODE_SELECT GENMASK(27, 24) +#define XGMAC4_MSEL_SHIFT 24 +enum dma_ch_ind_modes { + MODE_TXEXTCFG = 0x0, /* Tx Extended Config */ + MODE_RXEXTCFG = 0x1, /* Rx Extended Config */ + MODE_TXDBGSTS = 0x2, /* Tx Debug Status */ + MODE_RXDBGSTS = 0x3, /* Rx Debug Status */ + MODE_TXDESCCTRL = 0x4, /* Tx Descriptor control */ + MODE_RXDESCCTRL = 0x5, /* Rx Descriptor control */ +}; + +#define XGMAC4_ADDR_OFFSET GENMASK(14, 8) +#define XGMAC4_AOFF_SHIFT 8 +#define XGMAC4_AUTO_INCR GENMASK(5, 4) +#define XGMAC4_AUTO_SHIFT 4 +#define XGMAC4_CMD_TYPE BIT(1) +#define XGMAC4_OB BIT(0) +#define XGMAC4_DMA_CH_IND_DATA 0X00003084 + +/* TX Config definitions */ +#define XGMAC4_TXPBL GENMASK(29, 24) +#define XGMAC4_TXPBL_SHIFT 24 +#define XGMAC4_TPBLX8_MODE BIT(19) +#define XGMAC4_TP2TCMP GENMASK(18, 16) +#define XGMAC4_TP2TCMP_SHIFT 16 +#define XGMAC4_ORRQ GENMASK(13, 8) +/* RX Config definitions */ +#define XGMAC4_RXPBL GENMASK(29, 24) +#define XGMAC4_RXPBL_SHIFT 24 +#define XGMAC4_RPBLX8_MODE BIT(19) +#define XGMAC4_RP2TCMP GENMASK(18, 16) +#define XGMAC4_RP2TCMP_SHIFT 16 +#define XGMAC4_OWRQ GENMASK(13, 8) +/* Tx Descriptor control */ +#define XGMAC4_TXDCSZ GENMASK(2, 0) +#define XGMAC4_TDPS GENMASK(5, 3) +#define XGMAC4_TDPS_SHIFT 3 +/* Rx Descriptor control */ +#define XGMAC4_RXDCSZ GENMASK(2, 0) +#define XGMAC4_RDPS GENMASK(5, 3) +#define XGMAC4_RDPS_SHIFT 3 + +/* DWCXG_DMA_CH(#i) Registers*/ +#define XGMAC4_DSL GENMASK(20, 18) +#define XGMAC4_MSS GENMASK(13, 0) +#define XGMAC4_TFSEL GENMASK(30, 29) +#define XGMAC4_TQOS GENMASK(27, 24) +#define XGMAC4_IPBL BIT(15) +#define XGMAC4_TVDMA2TCMP GENMASK(6, 4) +#define XGMAC4_TVDMA2TCMP_SHIFT 4 +#define XGMAC4_RPF BIT(31) +#define XGMAC4_RVDMA2TCMP GENMASK(30, 28) +#define XGMAC4_RVDMA2TCMP_SHIFT 28 +#define XGMAC4_RQOS GENMASK(27, 24) + +/* PDMA Channel count */ +#define PDMA_TX_CH_COUNT 8 +#define PDMA_RX_CH_COUNT 10 +#define PDMA_MAX_TC_COUNT 8 + +/* VDMA channel count */ +#define VDMA_TOTAL_CH_COUNT 32 + +void dwxgmac4_dma_init(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, int atds); + +void dwxgmac4_dma_init_tx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan); +void dwxgmac4_dma_init_rx_chan(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t dma_addr, u32 chan); +#endif /* __STMMAC_DWXGMAC4_H__ */ From patchwork Fri Aug 2 03:18:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jitendra Vegiraju X-Patchwork-Id: 13751053 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BCB56C3DA4A for ; Fri, 2 Aug 2024 03:19:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=9xN4LdzQxHStk6z9WrVd70zj+/XzKPuClzjPhaN5vrM=; b=PHS6GCRYOlnaypMNgDeESbAu1E 5d5LS30N9wgupVkSxOjfmWSgqrvV/OgfqMyXKsGhAPfu3vrygI6llhDxYPpGz5TBM7HGHgBILzNwr s+08dTxKGmS0Cm6cIyIRZFTR4ggzjtJcRM58zLQNmd2saBdfDs/gwbNO7vIq2WJ3H9grClQYfpSRD JBGdlCObndWDBAN59VO0BgvuG1AIFY3BKoDZkvLQ8MsPcNZxVPv/uPyA62yQS2VCBByRPcc4ehtr6 TtjoVqTovx5N5h3pWkZWLd04Yjz1OCQ9iSyegXrTn4ArSF8J/zhz7ED/l3JbyenMeIdTnjhv7/Hi1 26xwhtnA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZiol-00000007SvA-2iQj; Fri, 02 Aug 2024 03:18:59 +0000 Received: from relay.smtp-ext.broadcom.com ([192.19.144.209]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZioH-00000007Sow-1UWZ for linux-arm-kernel@lists.infradead.org; Fri, 02 Aug 2024 03:18:30 +0000 Received: from mail-lvn-it-01.lvn.broadcom.net (mail-lvn-it-01.lvn.broadcom.net [10.36.132.253]) by relay.smtp-ext.broadcom.com (Postfix) with ESMTP id 50B9FC0000FB; Thu, 1 Aug 2024 20:18:27 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 relay.smtp-ext.broadcom.com 50B9FC0000FB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com; s=dkimrelay; t=1722568707; bh=krI7U8sRBmiw28CnfnkGSQgKpZPhoxDuv6WMnKEa0LE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FCC1inpqffmiJmEp+NcaB3ipvjKhCVumgwgPJvq/vrZtn81BYmSsmNdVL7E7sFesA /p6knY5qmUKRJx+mtz36ElVDV7YGRYS4N57Eg38Fa2TeyRt9idXAvjifCX23o8DGuk d4sKRRcISZU89ZJOQTxGXrgHx+wFJ/M/4Mdd2riI= Received: from pcie-dev03.dhcp.broadcom.net (pcie-dev03.dhcp.broadcom.net [10.59.171.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail-lvn-it-01.lvn.broadcom.net (Postfix) with ESMTPSA id 7733318041CAC7; Thu, 1 Aug 2024 20:18:24 -0700 (PDT) From: jitendra.vegiraju@broadcom.com To: netdev@vger.kernel.org Cc: alexandre.torgue@foss.st.com, joabreu@synopsys.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, jitendra.vegiraju@broadcom.com, bcm-kernel-feedback-list@broadcom.com, richardcochran@gmail.com, ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org, john.fastabend@gmail.com, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, horms@kernel.org, florian.fainelli@broadcom.com Subject: [PATCH net-next v3 2/3] net: stmmac: Integrate dwxgmac4 into stmmac hwif handling Date: Thu, 1 Aug 2024 20:18:21 -0700 Message-Id: <20240802031822.1862030-3-jitendra.vegiraju@broadcom.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240802031822.1862030-1-jitendra.vegiraju@broadcom.com> References: <20240802031822.1862030-1-jitendra.vegiraju@broadcom.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240801_201829_608579_AEE73D1E X-CRM114-Status: GOOD ( 18.66 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Jitendra Vegiraju Integrate dwxgmac4 support into stmmac hardware interface handling. A dwxgmac4 is an xgmac device and hence it inherits properties from existing stmmac_hw table entry. The quirks handling facility is used to update dma_ops field to point to dwxgmac400_dma_ops when the user version field matches. Signed-off-by: Jitendra Vegiraju --- drivers/net/ethernet/stmicro/stmmac/common.h | 4 +++ drivers/net/ethernet/stmicro/stmmac/hwif.c | 26 +++++++++++++++++++- drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index cd36ff4da68c..9bf278e11704 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -37,11 +37,15 @@ #define DWXGMAC_CORE_2_10 0x21 #define DWXGMAC_CORE_2_20 0x22 #define DWXLGMAC_CORE_2_00 0x20 +#define DWXGMAC_CORE_4_00 0x40 /* Device ID */ #define DWXGMAC_ID 0x76 #define DWXLGMAC_ID 0x27 +/* User Version */ +#define DWXGMAC_USER_VER_X22 0x22 + #define STMMAC_CHAN0 0 /* Always supported and default for all chips */ /* TX and RX Descriptor Length, these need to be power of two. diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index 29367105df54..713cb5aa2c3e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -36,6 +36,18 @@ static u32 stmmac_get_dev_id(struct stmmac_priv *priv, u32 id_reg) return (reg & GENMASK(15, 8)) >> 8; } +static u32 stmmac_get_user_version(struct stmmac_priv *priv, u32 id_reg) +{ + u32 reg = readl(priv->ioaddr + id_reg); + + if (!reg) { + dev_info(priv->device, "User Version not available\n"); + return 0x0; + } + + return (reg & GENMASK(23, 16)) >> 16; +} + static void stmmac_dwmac_mode_quirk(struct stmmac_priv *priv) { struct mac_device_info *mac = priv->hw; @@ -82,6 +94,18 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv) return 0; } +static int stmmac_dwxgmac_quirks(struct stmmac_priv *priv) +{ + struct mac_device_info *mac = priv->hw; + u32 user_ver; + + user_ver = stmmac_get_user_version(priv, GMAC4_VERSION); + if (priv->synopsys_id == DWXGMAC_CORE_4_00 && + user_ver == DWXGMAC_USER_VER_X22) + mac->dma = &dwxgmac400_dma_ops; + return 0; +} + static int stmmac_dwxlgmac_quirks(struct stmmac_priv *priv) { priv->hw->xlgmac = true; @@ -256,7 +280,7 @@ static const struct stmmac_hwif_entry { .mmc = &dwxgmac_mmc_ops, .est = &dwmac510_est_ops, .setup = dwxgmac2_setup, - .quirks = NULL, + .quirks = stmmac_dwxgmac_quirks, }, { .gmac = false, .gmac4 = false, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index e53c32362774..6213c496385c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -683,6 +683,7 @@ extern const struct stmmac_desc_ops dwxgmac210_desc_ops; extern const struct stmmac_mmc_ops dwmac_mmc_ops; extern const struct stmmac_mmc_ops dwxgmac_mmc_ops; extern const struct stmmac_est_ops dwmac510_est_ops; +extern const struct stmmac_dma_ops dwxgmac400_dma_ops; #define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ #define GMAC4_VERSION 0x00000110 /* GMAC4+ CORE Version */ From patchwork Fri Aug 2 03:18:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jitendra Vegiraju X-Patchwork-Id: 13751056 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CF0A5C49EA1 for ; Fri, 2 Aug 2024 03:20:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=g2QkOgSuPcUqaAuwV+bNk/hCDisqFHJ5JdTWs0abE+U=; b=Mb2fzbNd8Nvsm57hjdyD2AR6wl 3sEogHMv7phrjetlaUX+nj0Y0o0kT5kjWB19Tl05HdhbwMI4GjUxTYkK3jDbGDWMWD7Ftfd8o5rdx dr4h7HKPc0c9keQvu8n+A5SZnCQIdQqfswMPlmhuSy83WP067EYOnWWlVeAvUjjkl0j3aVEHg71sJ ylvkPaoXnRH3e8G8f1noer3omue9naUf3fN0i6JlVgkfjmJiShCgh5ZtS6Rlfg8Xhsp5EtHHZ6oZI /hy+lGcIjief90wfs0kbe/AOTtELaguAMyh9lTxGqA0dm+d4Lv/+3+/4Zlf4ww+LEaQ+dCVVvng5K FsuAmgwA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZiq7-00000007T9z-1GVa; Fri, 02 Aug 2024 03:20:23 +0000 Received: from saphodev.broadcom.com ([192.19.144.205] helo=relay.smtp-ext.broadcom.com) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZioH-00000007Soz-1jH1 for linux-arm-kernel@lists.infradead.org; Fri, 02 Aug 2024 03:18:33 +0000 Received: from mail-lvn-it-01.lvn.broadcom.net (mail-lvn-it-01.lvn.broadcom.net [10.36.132.253]) by relay.smtp-ext.broadcom.com (Postfix) with ESMTP id A7FB7C0000FB; Thu, 1 Aug 2024 20:18:27 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 relay.smtp-ext.broadcom.com A7FB7C0000FB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com; s=dkimrelay; t=1722568707; bh=Byi4hFC4zQfURMvG9HJsbqs4CTUUYXVawmUffe2MvgU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V01bo855974jyILx11o6rArID2xgFGTAfUwUD6a+EB/gxzkG4TVLjiVhkLtONwmtQ i/ogUHwtru0oMGOXzfGtkEOAYWmqMDwN0582E/BdtkqwWU1WUDFKt4d68M2T8Ra53H M8OidI2gKYuhqJJaJUWDmOHFWko7LF7YcxO9NA60= Received: from pcie-dev03.dhcp.broadcom.net (pcie-dev03.dhcp.broadcom.net [10.59.171.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail-lvn-it-01.lvn.broadcom.net (Postfix) with ESMTPSA id D2A0818041CAC4; Thu, 1 Aug 2024 20:18:24 -0700 (PDT) From: jitendra.vegiraju@broadcom.com To: netdev@vger.kernel.org Cc: alexandre.torgue@foss.st.com, joabreu@synopsys.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mcoquelin.stm32@gmail.com, jitendra.vegiraju@broadcom.com, bcm-kernel-feedback-list@broadcom.com, richardcochran@gmail.com, ast@kernel.org, daniel@iogearbox.net, hawk@kernel.org, john.fastabend@gmail.com, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org, andrew@lunn.ch, linux@armlinux.org.uk, horms@kernel.org, florian.fainelli@broadcom.com Subject: [PATCH net-next v3 3/3] net: stmmac: Add PCI driver support for BCM8958x Date: Thu, 1 Aug 2024 20:18:22 -0700 Message-Id: <20240802031822.1862030-4-jitendra.vegiraju@broadcom.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240802031822.1862030-1-jitendra.vegiraju@broadcom.com> References: <20240802031822.1862030-1-jitendra.vegiraju@broadcom.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240801_201829_654959_C8038437 X-CRM114-Status: GOOD ( 29.05 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Jitendra Vegiraju Add PCI ethernet driver support for Broadcom BCM8958x SoC devices used in automotive applications. This SoC device has PCIe ethernet MAC attached to an integrated ethernet switch using XGMII interface. The PCIe ethernet controller is presented to the Linux host as PCI network device. The following block diagram gives an overview of the application. +=================================+ | Host CPU/Linux | +=================================+ || PCIe || +==========================================+ | +--------------+ | | | PCIE Endpoint| | | | Ethernet | | | | Controller | | | | DMA | | | +--------------+ | | | MAC | BCM8958X | | +--------------+ SoC | | || XGMII | | || | | +--------------+ | | | Ethernet | | | | switch | | | +--------------+ | | || || || || | +==========================================+ || || || || More external interfaces The MAC block on BCM8958x is based on Synopsis XGMAC 4.00a core. This driver uses common dwxgmac2 code where applicable. Driver functionality specific to this MAC is implemented in dwxgmac4.c. Management of integrated ethernet switch on this SoC is not handled by the PCIe interface. This SoC device has PCIe ethernet MAC directly attached to an integrated ethernet switch using XGMII interface. Since device tree support is not available on this platform, a software node is created to enable fixed-link support using phylink driver. Signed-off-by: Jitendra Vegiraju --- MAINTAINERS | 8 + drivers/net/ethernet/stmicro/stmmac/Kconfig | 11 + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../net/ethernet/stmicro/stmmac/dwmac-brcm.c | 517 ++++++++++++++++++ 4 files changed, 537 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-brcm.c diff --git a/MAINTAINERS b/MAINTAINERS index 8766f3e5e87e..cce3d2e9eb22 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4350,6 +4350,14 @@ N: brcmstb N: bcm7038 N: bcm7120 +BROADCOM BCM8958X ETHERNET DRIVER +M: Jitendra Vegiraju +R: Broadcom internal kernel review list +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ethernet/stmicro/stmmac/dwmac-brcm.c +F: drivers/net/ethernet/stmicro/stmmac/dwxgmac4.* + BROADCOM BCMBCA ARM ARCHITECTURE M: William Zhang M: Anand Gore diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 05cc07b8f48c..47c9db123b03 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -298,6 +298,17 @@ config DWMAC_LOONGSON This selects the LOONGSON PCI bus support for the stmmac driver, Support for ethernet controller on Loongson-2K1000 SoC and LS7A1000 bridge. +config DWMAC_BRCM + tristate "Broadcom XGMAC support" + depends on STMMAC_ETH && PCI + depends on COMMON_CLK + help + Support for ethernet controllers on Broadcom BCM8958x SoCs. + + This selects Broadcom XGMAC specific PCI bus support for the + stmmac driver. This driver provides the glue layer on top of the + stmmac driver required for the Broadcom BCM8958x SoC devices. + config STMMAC_PCI tristate "STMMAC PCI bus support" depends on STMMAC_ETH && PCI diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 2f637612513d..90c135ea25eb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -41,4 +41,5 @@ dwmac-altr-socfpga-objs := dwmac-socfpga.o obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o obj-$(CONFIG_DWMAC_INTEL) += dwmac-intel.o obj-$(CONFIG_DWMAC_LOONGSON) += dwmac-loongson.o +obj-$(CONFIG_DWMAC_BRCM) += dwmac-brcm.o stmmac-pci-objs:= stmmac_pci.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-brcm.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-brcm.c new file mode 100644 index 000000000000..a7b0031506b8 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-brcm.c @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2024 Broadcom Corporation + * + * PCI driver for ethernet interface of BCM8958X automotive switch chip. + * + * High level block diagram of the device. + * +=================================+ + * | Host CPU/Linux | + * +=================================+ + * || PCIe + * || + * +==========================================+ + * | +--------------+ | + * | | PCIE Endpoint| | + * | | Ethernet | | + * | | Controller | | + * | | DMA | | + * | +--------------+ | + * | | MAC | BCM8958X | + * | +--------------+ SoC | + * | || XGMII | + * | || | + * | +--------------+ | + * | | Ethernet | | + * | | switch | | + * | +--------------+ | + * | || || || || | + * +==========================================+ + * || || || || More external interfaces + * + * This SoC device has PCIe ethernet MAC directly attached to an integrated + * ethernet switch using XGMII interface. Since devicetree support is not + * available on this platform, a software node is created to enable + * fixed-link support using phylink driver. + */ + +#include +#include +#include +#include + +#include "stmmac.h" +#include "dwxgmac2.h" + +#define PCI_DEVICE_ID_BROADCOM_BCM8958X 0xa00d +#define BRCM_MAX_MTU 1500 +#define READ_POLL_DELAY_US 100 +#define READ_POLL_TIMEOUT_US 10000 +#define DWMAC_125MHZ 125000000 +#define DWMAC_250MHZ 250000000 +#define BRCM_XGMAC_NUM_VLAN_FILTERS 32 + +/* TX and RX Queue counts */ +#define BRCM_TX_Q_COUNT 4 +#define BRCM_RX_Q_COUNT 4 + +#define BRCM_XGMAC_DMA_TX_SIZE 1024 +#define BRCM_XGMAC_DMA_RX_SIZE 1024 +#define BRCM_XGMAC_BAR0_MASK BIT(0) + +#define BRCM_XGMAC_IOMEM_MISC_REG_OFFSET 0x0 +#define BRCM_XGMAC_IOMEM_MBOX_REG_OFFSET 0x1000 +#define BRCM_XGMAC_IOMEM_CFG_REG_OFFSET 0x3000 + +#define XGMAC_MMC_CTRL_RCHM_DISABLE BIT(31) +#define XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_LOW 0x940 +#define XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_LO_VALUE 0x00000001 +#define XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_HIGH 0x944 +#define XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_HI_VALUE 0x88000000 + +#define XGMAC_PCIE_MISC_MII_CTRL 0x4 +#define XGMAC_PCIE_MISC_MII_CTRL_VALUE 0x7 +#define XGMAC_PCIE_MISC_PCIESS_CTRL 0x8 +#define XGMAC_PCIE_MISC_PCIESS_CTRL_VALUE 0x200 +#define XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_LO 0x90 +#define XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_LO_VALUE 0x00000001 +#define XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_HI 0x94 +#define XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_HI_VALUE 0x88000000 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST0 0x700 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST0_VALUE 1 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST1 0x704 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST1_VALUE 1 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST_DBELL 0x728 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST_DBELL_VALUE 1 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_SBD_ALL 0x740 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_SBD_ALL_VALUE 0 + +#define XGMAC_PCIE_MISC_FUNC_RESOURCES_PF0 0x804 + +/* MSIX Vector map register starting offsets */ +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_RX0_PF0 0x840 +#define XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_TX0_PF0 0x890 +#define BRCM_MAX_DMA_CHANNEL_PAIRS 4 + +#define BRCM_XGMAC_MSI_MAC_VECTOR 0 +#define BRCM_XGMAC_MSI_RX_VECTOR_START 9 +#define BRCM_XGMAC_MSI_TX_VECTOR_START 10 + +static const struct software_node phy_handle_node = { + .name = "bcm8958x-fixed-link", +}; + +static const struct property_entry fixed_link_properties[] = { + PROPERTY_ENTRY_U32("speed", 10000), + PROPERTY_ENTRY_BOOL("full-duplex"), + PROPERTY_ENTRY_BOOL("pause"), + { } +}; + +static const struct software_node fixed_link_node = { + .name = "fixed-link", + .parent = &phy_handle_node, + .properties = fixed_link_properties, +}; + +static const struct software_node *fixed_link_node_group[] = { + &phy_handle_node, + &fixed_link_node, + NULL +}; + +static int num_instances; + +struct brcm_priv_data { + void __iomem *mbox_regs; /* MBOX Registers*/ + void __iomem *misc_regs; /* MISC Registers*/ + void __iomem *xgmac_regs; /* XGMAC Registers*/ +}; + +struct dwxgmac_brcm_pci_info { + int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); +}; + +static void misc_iowrite(struct brcm_priv_data *brcm_priv, + u32 reg, u32 val) +{ + iowrite32(val, brcm_priv->misc_regs + reg); +} + +static struct mac_device_info *dwxgmac_brcm_setup(void *ppriv) +{ + struct stmmac_priv *priv = ppriv; + struct mac_device_info *mac; + + mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL); + if (!mac) + return NULL; + + priv->synopsys_id = DWXGMAC_CORE_4_00; + priv->dma_conf.dma_tx_size = BRCM_XGMAC_DMA_TX_SIZE; + priv->dma_conf.dma_rx_size = BRCM_XGMAC_DMA_RX_SIZE; + priv->plat->rss_en = 1; + mac->pcsr = priv->ioaddr; + priv->dev->priv_flags |= IFF_UNICAST_FLT; + mac->multicast_filter_bins = priv->plat->multicast_filter_bins; + mac->unicast_filter_entries = priv->plat->unicast_filter_entries; + mac->mcast_bits_log2 = 0; + + if (mac->multicast_filter_bins) + mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + + mac->link.duplex = DUPLEX_FULL; + mac->link.caps = (MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10000FD); + mac->link.xgmii.speed10000 = XGMAC_CONFIG_SS_10000; + mac->link.speed_mask = XGMAC_CONFIG_SS_MASK; + + return mac; +} + +static void dwxgmac_brcm_common_default_data(struct plat_stmmacenet_data *plat) +{ + int i; + + plat->has_xgmac = 1; + plat->force_sf_dma_mode = 1; + plat->mac_port_sel_speed = SPEED_10000; + plat->clk_ptp_rate = DWMAC_125MHZ; + plat->clk_ref_rate = DWMAC_250MHZ; + plat->setup = dwxgmac_brcm_setup; + plat->tx_coe = 1; + plat->rx_coe = 1; + plat->max_speed = SPEED_10000; + + /* Set default value for multicast hash bins */ + plat->multicast_filter_bins = HASH_TABLE_SIZE; + + /* Set default value for unicast filter entries */ + plat->unicast_filter_entries = 1; + + /* Set the maxmtu to device's default */ + plat->maxmtu = BRCM_MAX_MTU; + + /* Set default number of RX and TX queues to use */ + plat->tx_queues_to_use = BRCM_TX_Q_COUNT; + plat->rx_queues_to_use = BRCM_RX_Q_COUNT; + + plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP; + for (i = 0; i < plat->tx_queues_to_use; i++) { + plat->tx_queues_cfg[i].use_prio = false; + plat->tx_queues_cfg[i].prio = 0; + plat->tx_queues_cfg[i].mode_to_use = MTL_QUEUE_AVB; + } + + plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; + for (i = 0; i < plat->rx_queues_to_use; i++) { + plat->rx_queues_cfg[i].use_prio = false; + plat->rx_queues_cfg[i].mode_to_use = MTL_QUEUE_AVB; + plat->rx_queues_cfg[i].pkt_route = 0x0; + plat->rx_queues_cfg[i].chan = i; + } +} + +static int dwxgmac_brcm_default_data(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat) +{ + /* Set common default data first */ + dwxgmac_brcm_common_default_data(plat); + + plat->bus_id = 0; + plat->phy_addr = 0; + plat->phy_interface = PHY_INTERFACE_MODE_USXGMII; + + plat->dma_cfg->pbl = 32; + plat->dma_cfg->pblx8 = 0; + plat->dma_cfg->aal = 0; + plat->dma_cfg->eame = 1; + + plat->axi->axi_wr_osr_lmt = 31; + plat->axi->axi_rd_osr_lmt = 31; + plat->axi->axi_fb = 0; + plat->axi->axi_blen[0] = 4; + plat->axi->axi_blen[1] = 8; + plat->axi->axi_blen[2] = 16; + plat->axi->axi_blen[3] = 32; + plat->axi->axi_blen[4] = 64; + plat->axi->axi_blen[5] = 128; + plat->axi->axi_blen[6] = 256; + + plat->msi_mac_vec = BRCM_XGMAC_MSI_MAC_VECTOR; + plat->msi_rx_base_vec = BRCM_XGMAC_MSI_RX_VECTOR_START; + plat->msi_tx_base_vec = BRCM_XGMAC_MSI_TX_VECTOR_START; + + return 0; +} + +static struct dwxgmac_brcm_pci_info dwxgmac_brcm_pci_info = { + .setup = dwxgmac_brcm_default_data, +}; + +static int brcm_config_multi_msi(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res) +{ + int ret; + int i; + + if (plat->msi_rx_base_vec >= STMMAC_MSI_VEC_MAX || + plat->msi_tx_base_vec >= STMMAC_MSI_VEC_MAX) { + dev_err(&pdev->dev, "%s: Invalid RX & TX vector defined\n", + __func__); + return -EINVAL; + } + + ret = pci_alloc_irq_vectors(pdev, 2, STMMAC_MSI_VEC_MAX, + PCI_IRQ_MSI | PCI_IRQ_MSIX); + if (ret < 0) { + dev_err(&pdev->dev, "%s: multi MSI enablement failed\n", + __func__); + return ret; + } + + /* For RX MSI */ + for (i = 0; i < plat->rx_queues_to_use; i++) + res->rx_irq[i] = pci_irq_vector(pdev, + plat->msi_rx_base_vec + i * 2); + + /* For TX MSI */ + for (i = 0; i < plat->tx_queues_to_use; i++) + res->tx_irq[i] = pci_irq_vector(pdev, + plat->msi_tx_base_vec + i * 2); + + if (plat->msi_mac_vec < STMMAC_MSI_VEC_MAX) + res->irq = pci_irq_vector(pdev, plat->msi_mac_vec); + + plat->flags |= STMMAC_FLAG_MULTI_MSI_EN; + plat->flags |= STMMAC_FLAG_TSO_EN; + + return 0; +} + +static int dwxgmac_brcm_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct dwxgmac_brcm_pci_info *info = + (struct dwxgmac_brcm_pci_info *)id->driver_data; + struct plat_stmmacenet_data *plat; + struct brcm_priv_data *brcm_priv; + struct stmmac_resources res; + int rx_offset; + int tx_offset; + int vector; + int ret; + + brcm_priv = devm_kzalloc(&pdev->dev, sizeof(*brcm_priv), GFP_KERNEL); + if (!brcm_priv) + return -ENOMEM; + + plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); + if (!plat) + return -ENOMEM; + + plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), + GFP_KERNEL); + if (!plat->dma_cfg) + return -ENOMEM; + + plat->axi = devm_kzalloc(&pdev->dev, sizeof(*plat->axi), GFP_KERNEL); + if (!plat->axi) + return -ENOMEM; + + /* This device is directly attached to the switch chip internal to the + * SoC using XGMII interface. Since no MDIO is present, register + * fixed-link software_node to create phylink. + */ + if (num_instances == 0) { + ret = software_node_register_node_group(fixed_link_node_group); + if (ret) { + dev_err(&pdev->dev, + "%s: failed to register software node\n", + __func__); + return ret; + } + } + num_instances++; + plat->port_node = software_node_fwnode(&phy_handle_node); + + /* Disable D3COLD as our device does not support it */ + pci_d3cold_disable(pdev); + + /* Enable PCI device */ + ret = pcim_enable_device(pdev); + if (ret) { + dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n", + __func__); + return ret; + } + + /* Get the base address of device */ + ret = pcim_iomap_regions(pdev, BRCM_XGMAC_BAR0_MASK, pci_name(pdev)); + if (ret) + goto err_disable_device; + pci_set_master(pdev); + + memset(&res, 0, sizeof(res)); + res.addr = pcim_iomap_table(pdev)[0]; + /* MISC Regs */ + brcm_priv->misc_regs = res.addr + BRCM_XGMAC_IOMEM_MISC_REG_OFFSET; + /* MBOX Regs */ + brcm_priv->mbox_regs = res.addr + BRCM_XGMAC_IOMEM_MBOX_REG_OFFSET; + /* XGMAC config Regs */ + res.addr += BRCM_XGMAC_IOMEM_CFG_REG_OFFSET; + brcm_priv->xgmac_regs = res.addr; + + plat->bsp_priv = brcm_priv; + + /* Initialize all MSI vectors to invalid so that it can be set + * according to platform data settings below. + * Note: MSI vector takes value from 0 up to 31 (STMMAC_MSI_VEC_MAX) + */ + plat->msi_mac_vec = STMMAC_MSI_VEC_MAX; + plat->msi_wol_vec = STMMAC_MSI_VEC_MAX; + plat->msi_lpi_vec = STMMAC_MSI_VEC_MAX; + plat->msi_sfty_ce_vec = STMMAC_MSI_VEC_MAX; + plat->msi_sfty_ue_vec = STMMAC_MSI_VEC_MAX; + plat->msi_rx_base_vec = STMMAC_MSI_VEC_MAX; + plat->msi_tx_base_vec = STMMAC_MSI_VEC_MAX; + + ret = info->setup(pdev, plat); + if (ret) + goto err_disable_device; + + pci_write_config_dword(pdev, XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_LOW, + XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_LO_VALUE); + pci_write_config_dword(pdev, XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_HIGH, + XGMAC_PCIE_CFG_MSIX_ADDR_MATCH_HI_VALUE); + + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_LO, + XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_LO_VALUE); + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_HI, + XGMAC_PCIE_MISC_MSIX_ADDR_MATCH_HI_VALUE); + + /* SBD Interrupt */ + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_SBD_ALL, + XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_SBD_ALL_VALUE); + /* EP_DOORBELL Interrupt */ + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST_DBELL, + XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST_DBELL_VALUE); + /* EP_H0 Interrupt */ + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST0, + XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST0_VALUE); + /* EP_H1 Interrupt */ + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST1, + XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_EP2HOST1_VALUE); + + rx_offset = XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_RX0_PF0; + tx_offset = XGMAC_PCIE_MISC_MSIX_VECTOR_MAP_TX0_PF0; + vector = BRCM_XGMAC_MSI_RX_VECTOR_START; + for (int i = 0; i < BRCM_MAX_DMA_CHANNEL_PAIRS; i++) { + /* RX Interrupt */ + misc_iowrite(brcm_priv, rx_offset, vector++); + /* TX Interrupt */ + misc_iowrite(brcm_priv, tx_offset, vector++); + rx_offset += 4; + tx_offset += 4; + } + + /* Enable Switch Link */ + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_MII_CTRL, + XGMAC_PCIE_MISC_MII_CTRL_VALUE); + /* Enable MSI-X */ + misc_iowrite(brcm_priv, XGMAC_PCIE_MISC_PCIESS_CTRL, + XGMAC_PCIE_MISC_PCIESS_CTRL_VALUE); + + ret = brcm_config_multi_msi(pdev, plat, &res); + if (ret) { + dev_err(&pdev->dev, + "%s: ERROR: failed to enable IRQ\n", __func__); + goto err_disable_msi; + } + + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); + if (ret) + goto err_disable_msi; + + return ret; + +err_disable_msi: + pci_free_irq_vectors(pdev); +err_disable_device: + pci_disable_device(pdev); + + return ret; +} + +static void dwxgmac_brcm_pci_remove(struct pci_dev *pdev) +{ + stmmac_dvr_remove(&pdev->dev); + pci_free_irq_vectors(pdev); + pcim_iounmap_regions(pdev, BRCM_XGMAC_BAR0_MASK); + pci_clear_master(pdev); + + if (num_instances == 1) + software_node_unregister_node_group(fixed_link_node_group); + num_instances--; +} + +static int __maybe_unused dwxgmac_brcm_pci_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int ret; + + ret = stmmac_suspend(dev); + if (ret) + return ret; + + ret = pci_save_state(pdev); + if (ret) + return ret; + + pci_disable_device(pdev); + pci_wake_from_d3(pdev, true); + + return 0; +} + +static int __maybe_unused dwxgmac_brcm_pci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int ret; + + pci_restore_state(pdev); + pci_set_power_state(pdev, PCI_D0); + + ret = pci_enable_device(pdev); + if (ret) + return ret; + + pci_set_master(pdev); + + return stmmac_resume(dev); +} + +static SIMPLE_DEV_PM_OPS(dwxgmac_brcm_pm_ops, + dwxgmac_brcm_pci_suspend, + dwxgmac_brcm_pci_resume); + +static const struct pci_device_id dwxgmac_brcm_id_table[] = { + { PCI_DEVICE_DATA(BROADCOM, BCM8958X, &dwxgmac_brcm_pci_info) }, + {} +}; + +MODULE_DEVICE_TABLE(pci, dwxgmac_brcm_id_table); + +static struct pci_driver dwxgmac_brcm_pci_driver = { + .name = "brcm-bcm8958x", + .id_table = dwxgmac_brcm_id_table, + .probe = dwxgmac_brcm_pci_probe, + .remove = dwxgmac_brcm_pci_remove, + .driver = { + .pm = &dwxgmac_brcm_pm_ops, + }, +}; + +module_pci_driver(dwxgmac_brcm_pci_driver); + +MODULE_DESCRIPTION("Broadcom 10G Automotive Ethernet PCIe driver"); +MODULE_LICENSE("GPL");