mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
net: bcmasp: Add support for ASP2.0 Ethernet controller
Add support for the Broadcom ASP 2.0 Ethernet controller which is first introduced with 72165. This controller features two distinct Ethernet ports that can be independently operated. Reviewed-by: Simon Horman <simon.horman@corigine.com> Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com> Signed-off-by: Justin Chen <justin.chen@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a29401be8c
commit
490cb41200
@ -255,4 +255,15 @@ config BNXT_HWMON
|
||||
Say Y if you want to expose the thermal sensor data on NetXtreme-C/E
|
||||
devices, via the hwmon sysfs interface.
|
||||
|
||||
config BCMASP
|
||||
tristate "Broadcom ASP 2.0 Ethernet support"
|
||||
default ARCH_BRCMSTB
|
||||
depends on OF
|
||||
select MII
|
||||
select PHYLIB
|
||||
select MDIO_BCM_UNIMAC
|
||||
help
|
||||
This configuration enables the Broadcom ASP 2.0 Ethernet controller
|
||||
driver which is present in Broadcom STB SoCs such as 72165.
|
||||
|
||||
endif # NET_VENDOR_BROADCOM
|
||||
|
@ -17,3 +17,4 @@ obj-$(CONFIG_BGMAC_BCMA) += bgmac-bcma.o bgmac-bcma-mdio.o
|
||||
obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o
|
||||
obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
|
||||
obj-$(CONFIG_BNXT) += bnxt/
|
||||
obj-$(CONFIG_BCMASP) += asp2/
|
||||
|
2
drivers/net/ethernet/broadcom/asp2/Makefile
Normal file
2
drivers/net/ethernet/broadcom/asp2/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_BCMASP) += bcm-asp.o
|
||||
bcm-asp-objs := bcmasp.o bcmasp_intf.o bcmasp_ethtool.o
|
696
drivers/net/ethernet/broadcom/asp2/bcmasp.c
Normal file
696
drivers/net/ethernet/broadcom/asp2/bcmasp.c
Normal file
@ -0,0 +1,696 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Broadcom STB ASP 2.0 Driver
|
||||
*
|
||||
* Copyright (c) 2023 Broadcom
|
||||
*/
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "bcmasp.h"
|
||||
#include "bcmasp_intf_defs.h"
|
||||
|
||||
static void _intr2_mask_clear(struct bcmasp_priv *priv, u32 mask)
|
||||
{
|
||||
intr2_core_wl(priv, mask, ASP_INTR2_MASK_CLEAR);
|
||||
priv->irq_mask &= ~mask;
|
||||
}
|
||||
|
||||
static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask)
|
||||
{
|
||||
intr2_core_wl(priv, mask, ASP_INTR2_MASK_SET);
|
||||
priv->irq_mask |= mask;
|
||||
}
|
||||
|
||||
void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
|
||||
if (en)
|
||||
_intr2_mask_clear(priv, ASP_INTR2_TX_DESC(intf->channel));
|
||||
else
|
||||
_intr2_mask_set(priv, ASP_INTR2_TX_DESC(intf->channel));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcmasp_enable_tx_irq);
|
||||
|
||||
void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
|
||||
if (en)
|
||||
_intr2_mask_clear(priv, ASP_INTR2_RX_ECH(intf->channel));
|
||||
else
|
||||
_intr2_mask_set(priv, ASP_INTR2_RX_ECH(intf->channel));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcmasp_enable_rx_irq);
|
||||
|
||||
static void bcmasp_intr2_mask_set_all(struct bcmasp_priv *priv)
|
||||
{
|
||||
_intr2_mask_set(priv, 0xffffffff);
|
||||
priv->irq_mask = 0xffffffff;
|
||||
}
|
||||
|
||||
static void bcmasp_intr2_clear_all(struct bcmasp_priv *priv)
|
||||
{
|
||||
intr2_core_wl(priv, 0xffffffff, ASP_INTR2_CLEAR);
|
||||
}
|
||||
|
||||
static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status)
|
||||
{
|
||||
if (status & ASP_INTR2_RX_ECH(intf->channel)) {
|
||||
if (likely(napi_schedule_prep(&intf->rx_napi))) {
|
||||
bcmasp_enable_rx_irq(intf, 0);
|
||||
__napi_schedule_irqoff(&intf->rx_napi);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & ASP_INTR2_TX_DESC(intf->channel)) {
|
||||
if (likely(napi_schedule_prep(&intf->tx_napi))) {
|
||||
bcmasp_enable_tx_irq(intf, 0);
|
||||
__napi_schedule_irqoff(&intf->tx_napi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t bcmasp_isr(int irq, void *data)
|
||||
{
|
||||
struct bcmasp_priv *priv = data;
|
||||
struct bcmasp_intf *intf;
|
||||
u32 status;
|
||||
|
||||
status = intr2_core_rl(priv, ASP_INTR2_STATUS) &
|
||||
~intr2_core_rl(priv, ASP_INTR2_MASK_STATUS);
|
||||
|
||||
intr2_core_wl(priv, status, ASP_INTR2_CLEAR);
|
||||
|
||||
if (unlikely(status == 0)) {
|
||||
dev_warn(&priv->pdev->dev, "l2 spurious interrupt\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Handle intferfaces */
|
||||
list_for_each_entry(intf, &priv->intfs, list)
|
||||
bcmasp_intr2_handling(intf, status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void bcmasp_flush_rx_port(struct bcmasp_intf *intf)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
u32 mask;
|
||||
|
||||
switch (intf->port) {
|
||||
case 0:
|
||||
mask = ASP_CTRL_UMAC0_FLUSH_MASK;
|
||||
break;
|
||||
case 1:
|
||||
mask = ASP_CTRL_UMAC1_FLUSH_MASK;
|
||||
break;
|
||||
case 2:
|
||||
mask = ASP_CTRL_SPB_FLUSH_MASK;
|
||||
break;
|
||||
default:
|
||||
/* Not valid port */
|
||||
return;
|
||||
}
|
||||
|
||||
rx_ctrl_core_wl(priv, mask, priv->hw_info->rx_ctrl_flush);
|
||||
}
|
||||
|
||||
static void bcmasp_addr_to_uint(unsigned char *addr, u32 *high, u32 *low)
|
||||
{
|
||||
*high = (u32)(addr[0] << 8 | addr[1]);
|
||||
*low = (u32)(addr[2] << 24 | addr[3] << 16 | addr[4] << 8 |
|
||||
addr[5]);
|
||||
}
|
||||
|
||||
static void bcmasp_set_mda_filter(struct bcmasp_intf *intf,
|
||||
const unsigned char *addr,
|
||||
unsigned char *mask,
|
||||
unsigned int i)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
u32 addr_h, addr_l, mask_h, mask_l;
|
||||
|
||||
/* Set local copy */
|
||||
ether_addr_copy(priv->mda_filters[i].mask, mask);
|
||||
ether_addr_copy(priv->mda_filters[i].addr, addr);
|
||||
|
||||
/* Write to HW */
|
||||
bcmasp_addr_to_uint(priv->mda_filters[i].mask, &mask_h, &mask_l);
|
||||
bcmasp_addr_to_uint(priv->mda_filters[i].addr, &addr_h, &addr_l);
|
||||
rx_filter_core_wl(priv, addr_h, ASP_RX_FILTER_MDA_PAT_H(i));
|
||||
rx_filter_core_wl(priv, addr_l, ASP_RX_FILTER_MDA_PAT_L(i));
|
||||
rx_filter_core_wl(priv, mask_h, ASP_RX_FILTER_MDA_MSK_H(i));
|
||||
rx_filter_core_wl(priv, mask_l, ASP_RX_FILTER_MDA_MSK_L(i));
|
||||
}
|
||||
|
||||
static void bcmasp_en_mda_filter(struct bcmasp_intf *intf, bool en,
|
||||
unsigned int i)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
|
||||
if (priv->mda_filters[i].en == en)
|
||||
return;
|
||||
|
||||
priv->mda_filters[i].en = en;
|
||||
priv->mda_filters[i].port = intf->port;
|
||||
|
||||
rx_filter_core_wl(priv, ((intf->channel + 8) |
|
||||
(en << ASP_RX_FILTER_MDA_CFG_EN_SHIFT) |
|
||||
ASP_RX_FILTER_MDA_CFG_UMC_SEL(intf->port)),
|
||||
ASP_RX_FILTER_MDA_CFG(i));
|
||||
}
|
||||
|
||||
/* There are 32 MDA filters shared between all ports, we reserve 4 filters per
|
||||
* port for the following.
|
||||
* - Promisc: Filter to allow all packets when promisc is enabled
|
||||
* - All Multicast
|
||||
* - Broadcast
|
||||
* - Own address
|
||||
*
|
||||
* The reserved filters are identified as so.
|
||||
* - Promisc: (index * 4) + 0
|
||||
* - All Multicast: (index * 4) + 1
|
||||
* - Broadcast: (index * 4) + 2
|
||||
* - Own address: (index * 4) + 3
|
||||
*/
|
||||
enum asp_rx_filter_id {
|
||||
ASP_RX_FILTER_MDA_PROMISC = 0,
|
||||
ASP_RX_FILTER_MDA_ALLMULTI,
|
||||
ASP_RX_FILTER_MDA_BROADCAST,
|
||||
ASP_RX_FILTER_MDA_OWN_ADDR,
|
||||
ASP_RX_FILTER_MDA_RES_MAX,
|
||||
};
|
||||
|
||||
#define ASP_RX_FILT_MDA(intf, name) (((intf)->index * \
|
||||
ASP_RX_FILTER_MDA_RES_MAX) \
|
||||
+ ASP_RX_FILTER_MDA_##name)
|
||||
|
||||
static int bcmasp_total_res_mda_cnt(struct bcmasp_priv *priv)
|
||||
{
|
||||
return list_count_nodes(&priv->intfs) * ASP_RX_FILTER_MDA_RES_MAX;
|
||||
}
|
||||
|
||||
void bcmasp_set_promisc(struct bcmasp_intf *intf, bool en)
|
||||
{
|
||||
unsigned int i = ASP_RX_FILT_MDA(intf, PROMISC);
|
||||
unsigned char promisc[ETH_ALEN];
|
||||
|
||||
eth_zero_addr(promisc);
|
||||
/* Set mask to 00:00:00:00:00:00 to match all packets */
|
||||
bcmasp_set_mda_filter(intf, promisc, promisc, i);
|
||||
bcmasp_en_mda_filter(intf, en, i);
|
||||
}
|
||||
|
||||
void bcmasp_set_allmulti(struct bcmasp_intf *intf, bool en)
|
||||
{
|
||||
unsigned char allmulti[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned int i = ASP_RX_FILT_MDA(intf, ALLMULTI);
|
||||
|
||||
/* Set mask to 01:00:00:00:00:00 to match all multicast */
|
||||
bcmasp_set_mda_filter(intf, allmulti, allmulti, i);
|
||||
bcmasp_en_mda_filter(intf, en, i);
|
||||
}
|
||||
|
||||
void bcmasp_set_broad(struct bcmasp_intf *intf, bool en)
|
||||
{
|
||||
unsigned int i = ASP_RX_FILT_MDA(intf, BROADCAST);
|
||||
unsigned char addr[ETH_ALEN];
|
||||
|
||||
eth_broadcast_addr(addr);
|
||||
bcmasp_set_mda_filter(intf, addr, addr, i);
|
||||
bcmasp_en_mda_filter(intf, en, i);
|
||||
}
|
||||
|
||||
void bcmasp_set_oaddr(struct bcmasp_intf *intf, const unsigned char *addr,
|
||||
bool en)
|
||||
{
|
||||
unsigned char mask[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
unsigned int i = ASP_RX_FILT_MDA(intf, OWN_ADDR);
|
||||
|
||||
bcmasp_set_mda_filter(intf, addr, mask, i);
|
||||
bcmasp_en_mda_filter(intf, en, i);
|
||||
}
|
||||
|
||||
void bcmasp_disable_all_filters(struct bcmasp_intf *intf)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
unsigned int i;
|
||||
int res_count;
|
||||
|
||||
res_count = bcmasp_total_res_mda_cnt(intf->parent);
|
||||
|
||||
/* Disable all filters held by this port */
|
||||
for (i = res_count; i < NUM_MDA_FILTERS; i++) {
|
||||
if (priv->mda_filters[i].en &&
|
||||
priv->mda_filters[i].port == intf->port)
|
||||
bcmasp_en_mda_filter(intf, 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
static int bcmasp_combine_set_filter(struct bcmasp_intf *intf,
|
||||
unsigned char *addr, unsigned char *mask,
|
||||
int i)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
u64 addr1, addr2, mask1, mask2, mask3;
|
||||
|
||||
/* Switch to u64 to help with the calculations */
|
||||
addr1 = ether_addr_to_u64(priv->mda_filters[i].addr);
|
||||
mask1 = ether_addr_to_u64(priv->mda_filters[i].mask);
|
||||
addr2 = ether_addr_to_u64(addr);
|
||||
mask2 = ether_addr_to_u64(mask);
|
||||
|
||||
/* Check if one filter resides within the other */
|
||||
mask3 = mask1 & mask2;
|
||||
if (mask3 == mask1 && ((addr1 & mask1) == (addr2 & mask1))) {
|
||||
/* Filter 2 resides within filter 1, so everything is good */
|
||||
return 0;
|
||||
} else if (mask3 == mask2 && ((addr1 & mask2) == (addr2 & mask2))) {
|
||||
/* Filter 1 resides within filter 2, so swap filters */
|
||||
bcmasp_set_mda_filter(intf, addr, mask, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unable to combine */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr,
|
||||
unsigned char *mask)
|
||||
{
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
int ret, res_count;
|
||||
unsigned int i;
|
||||
|
||||
res_count = bcmasp_total_res_mda_cnt(intf->parent);
|
||||
|
||||
for (i = res_count; i < NUM_MDA_FILTERS; i++) {
|
||||
/* If filter not enabled or belongs to another port skip */
|
||||
if (!priv->mda_filters[i].en ||
|
||||
priv->mda_filters[i].port != intf->port)
|
||||
continue;
|
||||
|
||||
/* Attempt to combine filters */
|
||||
ret = bcmasp_combine_set_filter(intf, addr, mask, i);
|
||||
if (!ret)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create new filter if possible */
|
||||
for (i = res_count; i < NUM_MDA_FILTERS; i++) {
|
||||
if (priv->mda_filters[i].en)
|
||||
continue;
|
||||
|
||||
bcmasp_set_mda_filter(intf, addr, mask, i);
|
||||
bcmasp_en_mda_filter(intf, 1, i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No room for new filter */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void bcmasp_core_init_filters(struct bcmasp_priv *priv)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Disable all filters and reset software view since the HW
|
||||
* can lose context while in deep sleep suspend states
|
||||
*/
|
||||
for (i = 0; i < NUM_MDA_FILTERS; i++) {
|
||||
rx_filter_core_wl(priv, 0x0, ASP_RX_FILTER_MDA_CFG(i));
|
||||
priv->mda_filters[i].en = 0;
|
||||
}
|
||||
|
||||
/* Top level filter enable bit should be enabled at all times, set
|
||||
* GEN_WAKE_CLEAR to clear the network filter wake-up which would
|
||||
* otherwise be sticky
|
||||
*/
|
||||
rx_filter_core_wl(priv, (ASP_RX_FILTER_OPUT_EN |
|
||||
ASP_RX_FILTER_MDA_EN |
|
||||
ASP_RX_FILTER_GEN_WK_CLR |
|
||||
ASP_RX_FILTER_NT_FLT_EN),
|
||||
ASP_RX_FILTER_BLK_CTRL);
|
||||
}
|
||||
|
||||
/* ASP core initialization */
|
||||
static void bcmasp_core_init(struct bcmasp_priv *priv)
|
||||
{
|
||||
tx_analytics_core_wl(priv, 0x0, ASP_TX_ANALYTICS_CTRL);
|
||||
rx_analytics_core_wl(priv, 0x4, ASP_RX_ANALYTICS_CTRL);
|
||||
|
||||
rx_edpkt_core_wl(priv, (ASP_EDPKT_HDR_SZ_128 << ASP_EDPKT_HDR_SZ_SHIFT),
|
||||
ASP_EDPKT_HDR_CFG);
|
||||
rx_edpkt_core_wl(priv,
|
||||
(ASP_EDPKT_ENDI_BT_SWP_WD << ASP_EDPKT_ENDI_DESC_SHIFT),
|
||||
ASP_EDPKT_ENDI);
|
||||
|
||||
rx_edpkt_core_wl(priv, 0x1b, ASP_EDPKT_BURST_BUF_PSCAL_TOUT);
|
||||
rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_WRITE_TOUT);
|
||||
rx_edpkt_core_wl(priv, 0x3e8, ASP_EDPKT_BURST_BUF_READ_TOUT);
|
||||
|
||||
rx_edpkt_core_wl(priv, ASP_EDPKT_ENABLE_EN, ASP_EDPKT_ENABLE);
|
||||
|
||||
/* Disable and clear both UniMAC's wake-up interrupts to avoid
|
||||
* sticky interrupts.
|
||||
*/
|
||||
_intr2_mask_set(priv, ASP_INTR2_UMC0_WAKE | ASP_INTR2_UMC1_WAKE);
|
||||
intr2_core_wl(priv, ASP_INTR2_UMC0_WAKE | ASP_INTR2_UMC1_WAKE,
|
||||
ASP_INTR2_CLEAR);
|
||||
}
|
||||
|
||||
static void bcmasp_core_clock_select(struct bcmasp_priv *priv, bool slow)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = ctrl_core_rl(priv, ASP_CTRL_CORE_CLOCK_SELECT);
|
||||
if (slow)
|
||||
reg &= ~ASP_CTRL_CORE_CLOCK_SELECT_MAIN;
|
||||
else
|
||||
reg |= ASP_CTRL_CORE_CLOCK_SELECT_MAIN;
|
||||
ctrl_core_wl(priv, reg, ASP_CTRL_CORE_CLOCK_SELECT);
|
||||
}
|
||||
|
||||
static void bcmasp_core_clock_set_ll(struct bcmasp_priv *priv, u32 clr, u32 set)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = ctrl_core_rl(priv, ASP_CTRL_CLOCK_CTRL);
|
||||
reg &= ~clr;
|
||||
reg |= set;
|
||||
ctrl_core_wl(priv, reg, ASP_CTRL_CLOCK_CTRL);
|
||||
|
||||
reg = ctrl_core_rl(priv, ASP_CTRL_SCRATCH_0);
|
||||
reg &= ~clr;
|
||||
reg |= set;
|
||||
ctrl_core_wl(priv, reg, ASP_CTRL_SCRATCH_0);
|
||||
}
|
||||
|
||||
static void bcmasp_core_clock_set(struct bcmasp_priv *priv, u32 clr, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->clk_lock, flags);
|
||||
bcmasp_core_clock_set_ll(priv, clr, set);
|
||||
spin_unlock_irqrestore(&priv->clk_lock, flags);
|
||||
}
|
||||
|
||||
void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en)
|
||||
{
|
||||
u32 intf_mask = ASP_CTRL_CLOCK_CTRL_ASP_RGMII_DIS(intf->port);
|
||||
struct bcmasp_priv *priv = intf->parent;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
/* When enabling an interface, if the RX or TX clocks were not enabled,
|
||||
* enable them. Conversely, while disabling an interface, if this is
|
||||
* the last one enabled, we can turn off the shared RX and TX clocks as
|
||||
* well. We control enable bits which is why we test for equality on
|
||||
* the RGMII clock bit mask.
|
||||
*/
|
||||
spin_lock_irqsave(&priv->clk_lock, flags);
|
||||
if (en) {
|
||||
intf_mask |= ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE |
|
||||
ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE;
|
||||
bcmasp_core_clock_set_ll(priv, intf_mask, 0);
|
||||
} else {
|
||||
reg = ctrl_core_rl(priv, ASP_CTRL_SCRATCH_0) | intf_mask;
|
||||
if ((reg & ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK) ==
|
||||
ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK)
|
||||
intf_mask |= ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE |
|
||||
ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE;
|
||||
bcmasp_core_clock_set_ll(priv, 0, intf_mask);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->clk_lock, flags);
|
||||
}
|
||||
|
||||
static struct bcmasp_hw_info v20_hw_info = {
|
||||
.rx_ctrl_flush = ASP_RX_CTRL_FLUSH,
|
||||
.umac2fb = UMAC2FB_OFFSET,
|
||||
.rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT,
|
||||
.rx_ctrl_fb_filt_out_frame_count = ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT,
|
||||
.rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH,
|
||||
};
|
||||
|
||||
static const struct bcmasp_plat_data v20_plat_data = {
|
||||
.hw_info = &v20_hw_info,
|
||||
};
|
||||
|
||||
static struct bcmasp_hw_info v21_hw_info = {
|
||||
.rx_ctrl_flush = ASP_RX_CTRL_FLUSH_2_1,
|
||||
.umac2fb = UMAC2FB_OFFSET_2_1,
|
||||
.rx_ctrl_fb_out_frame_count = ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1,
|
||||
.rx_ctrl_fb_filt_out_frame_count =
|
||||
ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1,
|
||||
.rx_ctrl_fb_rx_fifo_depth = ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1,
|
||||
};
|
||||
|
||||
static const struct bcmasp_plat_data v21_plat_data = {
|
||||
.hw_info = &v21_hw_info,
|
||||
};
|
||||
|
||||
static const struct of_device_id bcmasp_of_match[] = {
|
||||
{ .compatible = "brcm,asp-v2.0", .data = &v20_plat_data },
|
||||
{ .compatible = "brcm,asp-v2.1", .data = &v21_plat_data },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcmasp_of_match);
|
||||
|
||||
static const struct of_device_id bcmasp_mdio_of_match[] = {
|
||||
{ .compatible = "brcm,asp-v2.1-mdio", },
|
||||
{ .compatible = "brcm,asp-v2.0-mdio", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcmasp_mdio_of_match);
|
||||
|
||||
static void bcmasp_remove_intfs(struct bcmasp_priv *priv)
|
||||
{
|
||||
struct bcmasp_intf *intf, *n;
|
||||
|
||||
list_for_each_entry_safe(intf, n, &priv->intfs, list) {
|
||||
list_del(&intf->list);
|
||||
bcmasp_interface_destroy(intf);
|
||||
}
|
||||
}
|
||||
|
||||
static int bcmasp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *ports_node, *intf_node;
|
||||
const struct bcmasp_plat_data *pdata;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct bcmasp_priv *priv;
|
||||
struct bcmasp_intf *intf;
|
||||
int ret = 0, count = 0;
|
||||
unsigned int i;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->irq = platform_get_irq(pdev, 0);
|
||||
if (priv->irq <= 0)
|
||||
return dev_err_probe(dev, -EINVAL, "invalid interrupt\n");
|
||||
|
||||
priv->clk = devm_clk_get_optional_enabled(dev, "sw_asp");
|
||||
if (IS_ERR(priv->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->clk),
|
||||
"failed to request clock\n");
|
||||
|
||||
/* Base from parent node */
|
||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->base))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->base), "failed to iomap\n");
|
||||
|
||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "unable to set DMA mask: %d\n", ret);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, priv);
|
||||
priv->pdev = pdev;
|
||||
spin_lock_init(&priv->mda_lock);
|
||||
spin_lock_init(&priv->clk_lock);
|
||||
INIT_LIST_HEAD(&priv->intfs);
|
||||
|
||||
pdata = device_get_match_data(&pdev->dev);
|
||||
if (!pdata)
|
||||
return dev_err_probe(dev, -EINVAL, "unable to find platform data\n");
|
||||
|
||||
priv->hw_info = pdata->hw_info;
|
||||
|
||||
/* Enable all clocks to ensure successful probing */
|
||||
bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
|
||||
|
||||
/* Switch to the main clock */
|
||||
bcmasp_core_clock_select(priv, false);
|
||||
|
||||
bcmasp_intr2_mask_set_all(priv);
|
||||
bcmasp_intr2_clear_all(priv);
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, priv->irq, bcmasp_isr, 0,
|
||||
pdev->name, priv);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to request ASP interrupt: %d", ret);
|
||||
|
||||
/* Register mdio child nodes */
|
||||
of_platform_populate(dev->of_node, bcmasp_mdio_of_match, NULL, dev);
|
||||
|
||||
/* ASP specific initialization, Needs to be done regardless of
|
||||
* how many interfaces come up.
|
||||
*/
|
||||
bcmasp_core_init(priv);
|
||||
bcmasp_core_init_filters(priv);
|
||||
|
||||
ports_node = of_find_node_by_name(dev->of_node, "ethernet-ports");
|
||||
if (!ports_node) {
|
||||
dev_warn(dev, "No ports found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for_each_available_child_of_node(ports_node, intf_node) {
|
||||
intf = bcmasp_interface_create(priv, intf_node, i);
|
||||
if (!intf) {
|
||||
dev_err(dev, "Cannot create eth interface %d\n", i);
|
||||
bcmasp_remove_intfs(priv);
|
||||
goto of_put_exit;
|
||||
}
|
||||
list_add_tail(&intf->list, &priv->intfs);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Drop the clock reference count now and let ndo_open()/ndo_close()
|
||||
* manage it for us from now on.
|
||||
*/
|
||||
bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE);
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
/* Now do the registration of the network ports which will take care
|
||||
* of managing the clock properly.
|
||||
*/
|
||||
list_for_each_entry(intf, &priv->intfs, list) {
|
||||
ret = register_netdev(intf->ndev);
|
||||
if (ret) {
|
||||
netdev_err(intf->ndev,
|
||||
"failed to register net_device: %d\n", ret);
|
||||
bcmasp_remove_intfs(priv);
|
||||
goto of_put_exit;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
dev_info(dev, "Initialized %d port(s)\n", count);
|
||||
|
||||
of_put_exit:
|
||||
of_node_put(ports_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bcmasp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bcmasp_priv *priv = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
if (!priv)
|
||||
return 0;
|
||||
|
||||
bcmasp_remove_intfs(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcmasp_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
bcmasp_remove(pdev);
|
||||
}
|
||||
|
||||
static int __maybe_unused bcmasp_suspend(struct device *d)
|
||||
{
|
||||
struct bcmasp_priv *priv = dev_get_drvdata(d);
|
||||
struct bcmasp_intf *intf;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(intf, &priv->intfs, list) {
|
||||
ret = bcmasp_interface_suspend(intf);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Whether Wake-on-LAN is enabled or not, we can always disable
|
||||
* the shared TX clock
|
||||
*/
|
||||
bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE);
|
||||
|
||||
bcmasp_core_clock_select(priv, true);
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused bcmasp_resume(struct device *d)
|
||||
{
|
||||
struct bcmasp_priv *priv = dev_get_drvdata(d);
|
||||
struct bcmasp_intf *intf;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Switch to the main clock domain */
|
||||
bcmasp_core_clock_select(priv, false);
|
||||
|
||||
/* Re-enable all clocks for re-initialization */
|
||||
bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
|
||||
|
||||
bcmasp_core_init(priv);
|
||||
bcmasp_core_init_filters(priv);
|
||||
|
||||
/* And disable them to let the network devices take care of them */
|
||||
bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE);
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
list_for_each_entry(intf, &priv->intfs, list) {
|
||||
ret = bcmasp_interface_resume(intf);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(bcmasp_pm_ops,
|
||||
bcmasp_suspend, bcmasp_resume);
|
||||
|
||||
static struct platform_driver bcmasp_driver = {
|
||||
.probe = bcmasp_probe,
|
||||
.remove = bcmasp_remove,
|
||||
.shutdown = bcmasp_shutdown,
|
||||
.driver = {
|
||||
.name = "brcm,asp-v2",
|
||||
.of_match_table = bcmasp_of_match,
|
||||
.pm = &bcmasp_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(bcmasp_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Broadcom ASP 2.0 Ethernet controller driver");
|
||||
MODULE_ALIAS("platform:brcm,asp-v2");
|
||||
MODULE_LICENSE("GPL");
|
503
drivers/net/ethernet/broadcom/asp2/bcmasp.h
Normal file
503
drivers/net/ethernet/broadcom/asp2/bcmasp.h
Normal file
@ -0,0 +1,503 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __BCMASP_H
|
||||
#define __BCMASP_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/io-64-nonatomic-hi-lo.h>
|
||||
#include <uapi/linux/ethtool.h>
|
||||
|
||||
#define ASP_INTR2_OFFSET 0x1000
|
||||
#define ASP_INTR2_STATUS 0x0
|
||||
#define ASP_INTR2_SET 0x4
|
||||
#define ASP_INTR2_CLEAR 0x8
|
||||
#define ASP_INTR2_MASK_STATUS 0xc
|
||||
#define ASP_INTR2_MASK_SET 0x10
|
||||
#define ASP_INTR2_MASK_CLEAR 0x14
|
||||
|
||||
#define ASP_INTR2_RX_ECH(intr) BIT(intr)
|
||||
#define ASP_INTR2_TX_DESC(intr) BIT((intr) + 14)
|
||||
#define ASP_INTR2_UMC0_WAKE BIT(22)
|
||||
#define ASP_INTR2_UMC1_WAKE BIT(28)
|
||||
|
||||
#define ASP_WAKEUP_INTR2_OFFSET 0x1200
|
||||
#define ASP_WAKEUP_INTR2_STATUS 0x0
|
||||
#define ASP_WAKEUP_INTR2_SET 0x4
|
||||
#define ASP_WAKEUP_INTR2_CLEAR 0x8
|
||||
#define ASP_WAKEUP_INTR2_MASK_STATUS 0xc
|
||||
#define ASP_WAKEUP_INTR2_MASK_SET 0x10
|
||||
#define ASP_WAKEUP_INTR2_MASK_CLEAR 0x14
|
||||
#define ASP_WAKEUP_INTR2_MPD_0 BIT(0)
|
||||
#define ASP_WAKEUP_INTR2_MPD_1 BIT(1)
|
||||
#define ASP_WAKEUP_INTR2_FILT_0 BIT(2)
|
||||
#define ASP_WAKEUP_INTR2_FILT_1 BIT(3)
|
||||
#define ASP_WAKEUP_INTR2_FW BIT(4)
|
||||
|
||||
#define ASP_TX_ANALYTICS_OFFSET 0x4c000
|
||||
#define ASP_TX_ANALYTICS_CTRL 0x0
|
||||
|
||||
#define ASP_RX_ANALYTICS_OFFSET 0x98000
|
||||
#define ASP_RX_ANALYTICS_CTRL 0x0
|
||||
|
||||
#define ASP_RX_CTRL_OFFSET 0x9f000
|
||||
#define ASP_RX_CTRL_UMAC_0_FRAME_COUNT 0x8
|
||||
#define ASP_RX_CTRL_UMAC_1_FRAME_COUNT 0xc
|
||||
#define ASP_RX_CTRL_FB_0_FRAME_COUNT 0x14
|
||||
#define ASP_RX_CTRL_FB_1_FRAME_COUNT 0x18
|
||||
#define ASP_RX_CTRL_FB_8_FRAME_COUNT 0x1c
|
||||
/* asp2.1 diverges offsets here */
|
||||
/* ASP2.0 */
|
||||
#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT 0x20
|
||||
#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT 0x24
|
||||
#define ASP_RX_CTRL_FLUSH 0x28
|
||||
#define ASP_CTRL_UMAC0_FLUSH_MASK (BIT(0) | BIT(12))
|
||||
#define ASP_CTRL_UMAC1_FLUSH_MASK (BIT(1) | BIT(13))
|
||||
#define ASP_CTRL_SPB_FLUSH_MASK (BIT(8) | BIT(20))
|
||||
#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH 0x30
|
||||
/* ASP2.1 */
|
||||
#define ASP_RX_CTRL_FB_9_FRAME_COUNT_2_1 0x20
|
||||
#define ASP_RX_CTRL_FB_10_FRAME_COUNT_2_1 0x24
|
||||
#define ASP_RX_CTRL_FB_OUT_FRAME_COUNT_2_1 0x28
|
||||
#define ASP_RX_CTRL_FB_FILT_OUT_FRAME_COUNT_2_1 0x2c
|
||||
#define ASP_RX_CTRL_FLUSH_2_1 0x30
|
||||
#define ASP_RX_CTRL_FB_RX_FIFO_DEPTH_2_1 0x38
|
||||
|
||||
#define ASP_RX_FILTER_OFFSET 0x80000
|
||||
#define ASP_RX_FILTER_BLK_CTRL 0x0
|
||||
#define ASP_RX_FILTER_OPUT_EN BIT(0)
|
||||
#define ASP_RX_FILTER_MDA_EN BIT(1)
|
||||
#define ASP_RX_FILTER_LNR_MD BIT(2)
|
||||
#define ASP_RX_FILTER_GEN_WK_EN BIT(3)
|
||||
#define ASP_RX_FILTER_GEN_WK_CLR BIT(4)
|
||||
#define ASP_RX_FILTER_NT_FLT_EN BIT(5)
|
||||
#define ASP_RX_FILTER_MDA_CFG(sel) (((sel) * 0x14) + 0x100)
|
||||
#define ASP_RX_FILTER_MDA_CFG_EN_SHIFT 8
|
||||
#define ASP_RX_FILTER_MDA_CFG_UMC_SEL(sel) ((sel) > 1 ? BIT(17) : \
|
||||
BIT((sel) + 9))
|
||||
#define ASP_RX_FILTER_MDA_PAT_H(sel) (((sel) * 0x14) + 0x104)
|
||||
#define ASP_RX_FILTER_MDA_PAT_L(sel) (((sel) * 0x14) + 0x108)
|
||||
#define ASP_RX_FILTER_MDA_MSK_H(sel) (((sel) * 0x14) + 0x10c)
|
||||
#define ASP_RX_FILTER_MDA_MSK_L(sel) (((sel) * 0x14) + 0x110)
|
||||
#define ASP_RX_FILTER_MDA_CFG(sel) (((sel) * 0x14) + 0x100)
|
||||
#define ASP_RX_FILTER_MDA_PAT_H(sel) (((sel) * 0x14) + 0x104)
|
||||
#define ASP_RX_FILTER_MDA_PAT_L(sel) (((sel) * 0x14) + 0x108)
|
||||
#define ASP_RX_FILTER_MDA_MSK_H(sel) (((sel) * 0x14) + 0x10c)
|
||||
#define ASP_RX_FILTER_MDA_MSK_L(sel) (((sel) * 0x14) + 0x110)
|
||||
#define ASP_RX_FILTER_NET_CFG(sel) (((sel) * 0xa04) + 0x400)
|
||||
#define ASP_RX_FILTER_NET_CFG_CH(sel) ((sel) << 0)
|
||||
#define ASP_RX_FILTER_NET_CFG_EN BIT(9)
|
||||
#define ASP_RX_FILTER_NET_CFG_L2_EN BIT(10)
|
||||
#define ASP_RX_FILTER_NET_CFG_L3_EN BIT(11)
|
||||
#define ASP_RX_FILTER_NET_CFG_L4_EN BIT(12)
|
||||
#define ASP_RX_FILTER_NET_CFG_L3_FRM(sel) ((sel) << 13)
|
||||
#define ASP_RX_FILTER_NET_CFG_L4_FRM(sel) ((sel) << 15)
|
||||
#define ASP_RX_FILTER_NET_CFG_UMC(sel) BIT((sel) + 19)
|
||||
#define ASP_RX_FILTER_NET_CFG_DMA_EN BIT(27)
|
||||
|
||||
#define ASP_RX_FILTER_NET_OFFSET_MAX 32
|
||||
#define ASP_RX_FILTER_NET_PAT(sel, block, off) \
|
||||
(((sel) * 0xa04) + ((block) * 0x200) + (off) + 0x600)
|
||||
#define ASP_RX_FILTER_NET_MASK(sel, block, off) \
|
||||
(((sel) * 0xa04) + ((block) * 0x200) + (off) + 0x700)
|
||||
|
||||
#define ASP_RX_FILTER_NET_OFFSET(sel) (((sel) * 0xa04) + 0xe00)
|
||||
#define ASP_RX_FILTER_NET_OFFSET_L2(val) ((val) << 0)
|
||||
#define ASP_RX_FILTER_NET_OFFSET_L3_0(val) ((val) << 8)
|
||||
#define ASP_RX_FILTER_NET_OFFSET_L3_1(val) ((val) << 16)
|
||||
#define ASP_RX_FILTER_NET_OFFSET_L4(val) ((val) << 24)
|
||||
|
||||
#define ASP_EDPKT_OFFSET 0x9c000
|
||||
#define ASP_EDPKT_ENABLE 0x4
|
||||
#define ASP_EDPKT_ENABLE_EN BIT(0)
|
||||
#define ASP_EDPKT_HDR_CFG 0xc
|
||||
#define ASP_EDPKT_HDR_SZ_SHIFT 2
|
||||
#define ASP_EDPKT_HDR_SZ_32 0
|
||||
#define ASP_EDPKT_HDR_SZ_64 1
|
||||
#define ASP_EDPKT_HDR_SZ_96 2
|
||||
#define ASP_EDPKT_HDR_SZ_128 3
|
||||
#define ASP_EDPKT_BURST_BUF_PSCAL_TOUT 0x10
|
||||
#define ASP_EDPKT_BURST_BUF_WRITE_TOUT 0x14
|
||||
#define ASP_EDPKT_BURST_BUF_READ_TOUT 0x18
|
||||
#define ASP_EDPKT_RX_TS_COUNTER 0x38
|
||||
#define ASP_EDPKT_ENDI 0x48
|
||||
#define ASP_EDPKT_ENDI_DESC_SHIFT 8
|
||||
#define ASP_EDPKT_ENDI_NO_BT_SWP 0
|
||||
#define ASP_EDPKT_ENDI_BT_SWP_WD 1
|
||||
#define ASP_EDPKT_RX_PKT_CNT 0x138
|
||||
#define ASP_EDPKT_HDR_EXTR_CNT 0x13c
|
||||
#define ASP_EDPKT_HDR_OUT_CNT 0x140
|
||||
|
||||
#define ASP_CTRL 0x101000
|
||||
#define ASP_CTRL_ASP_SW_INIT 0x04
|
||||
#define ASP_CTRL_ASP_SW_INIT_ACPUSS_CORE BIT(0)
|
||||
#define ASP_CTRL_ASP_SW_INIT_ASP_TX BIT(1)
|
||||
#define ASP_CTRL_ASP_SW_INIT_AS_RX BIT(2)
|
||||
#define ASP_CTRL_ASP_SW_INIT_ASP_RGMII_UMAC0 BIT(3)
|
||||
#define ASP_CTRL_ASP_SW_INIT_ASP_RGMII_UMAC1 BIT(4)
|
||||
#define ASP_CTRL_ASP_SW_INIT_ASP_XMEMIF BIT(5)
|
||||
#define ASP_CTRL_CLOCK_CTRL 0x04
|
||||
#define ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE BIT(0)
|
||||
#define ASP_CTRL_CLOCK_CTRL_ASP_RX_DISABLE BIT(1)
|
||||
#define ASP_CTRL_CLOCK_CTRL_ASP_RGMII_SHIFT 2
|
||||
#define ASP_CTRL_CLOCK_CTRL_ASP_RGMII_MASK (0x7 << ASP_CTRL_CLOCK_CTRL_ASP_RGMII_SHIFT)
|
||||
#define ASP_CTRL_CLOCK_CTRL_ASP_RGMII_DIS(x) BIT(ASP_CTRL_CLOCK_CTRL_ASP_RGMII_SHIFT + (x))
|
||||
#define ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE GENMASK(4, 0)
|
||||
#define ASP_CTRL_CORE_CLOCK_SELECT 0x08
|
||||
#define ASP_CTRL_CORE_CLOCK_SELECT_MAIN BIT(0)
|
||||
#define ASP_CTRL_SCRATCH_0 0x0c
|
||||
|
||||
struct bcmasp_tx_cb {
|
||||
struct sk_buff *skb;
|
||||
unsigned int bytes_sent;
|
||||
bool last;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma_addr);
|
||||
DEFINE_DMA_UNMAP_LEN(dma_len);
|
||||
};
|
||||
|
||||
struct bcmasp_res {
|
||||
/* Per interface resources */
|
||||
/* Port */
|
||||
void __iomem *umac;
|
||||
void __iomem *umac2fb;
|
||||
void __iomem *rgmii;
|
||||
|
||||
/* TX slowpath/configuration */
|
||||
void __iomem *tx_spb_ctrl;
|
||||
void __iomem *tx_spb_top;
|
||||
void __iomem *tx_epkt_core;
|
||||
void __iomem *tx_pause_ctrl;
|
||||
};
|
||||
|
||||
#define DESC_ADDR(x) ((x) & GENMASK_ULL(39, 0))
|
||||
#define DESC_FLAGS(x) ((x) & GENMASK_ULL(63, 40))
|
||||
|
||||
struct bcmasp_desc {
|
||||
u64 buf;
|
||||
#define DESC_CHKSUM BIT_ULL(40)
|
||||
#define DESC_CRC_ERR BIT_ULL(41)
|
||||
#define DESC_RX_SYM_ERR BIT_ULL(42)
|
||||
#define DESC_NO_OCT_ALN BIT_ULL(43)
|
||||
#define DESC_PKT_TRUC BIT_ULL(44)
|
||||
/* 39:0 (TX/RX) bits 0-39 of buf addr
|
||||
* 40 (RX) checksum
|
||||
* 41 (RX) crc_error
|
||||
* 42 (RX) rx_symbol_error
|
||||
* 43 (RX) non_octet_aligned
|
||||
* 44 (RX) pkt_truncated
|
||||
* 45 Reserved
|
||||
* 56:46 (RX) mac_filter_id
|
||||
* 60:57 (RX) rx_port_num (0-unicmac0, 1-unimac1)
|
||||
* 61 Reserved
|
||||
* 63:62 (TX) forward CRC, overwrite CRC
|
||||
*/
|
||||
u32 size;
|
||||
u32 flags;
|
||||
#define DESC_INT_EN BIT(0)
|
||||
#define DESC_SOF BIT(1)
|
||||
#define DESC_EOF BIT(2)
|
||||
#define DESC_EPKT_CMD BIT(3)
|
||||
#define DESC_SCRAM_ST BIT(8)
|
||||
#define DESC_SCRAM_END BIT(9)
|
||||
#define DESC_PCPP BIT(10)
|
||||
#define DESC_PPPP BIT(11)
|
||||
/* 0 (TX) tx_int_en
|
||||
* 1 (TX/RX) SOF
|
||||
* 2 (TX/RX) EOF
|
||||
* 3 (TX) epkt_command
|
||||
* 6:4 (TX) PA
|
||||
* 7 (TX) pause at desc end
|
||||
* 8 (TX) scram_start
|
||||
* 9 (TX) scram_end
|
||||
* 10 (TX) PCPP
|
||||
* 11 (TX) PPPP
|
||||
* 14:12 Reserved
|
||||
* 15 (TX) pid ch Valid
|
||||
* 19:16 (TX) data_pkt_type
|
||||
* 32:20 (TX) pid_channel (RX) nw_filter_id
|
||||
*/
|
||||
};
|
||||
|
||||
struct bcmasp_intf;
|
||||
|
||||
struct bcmasp_intf_stats64 {
|
||||
/* Rx Stats */
|
||||
u64_stats_t rx_packets;
|
||||
u64_stats_t rx_bytes;
|
||||
u64_stats_t rx_errors;
|
||||
u64_stats_t rx_dropped;
|
||||
u64_stats_t rx_crc_errs;
|
||||
u64_stats_t rx_sym_errs;
|
||||
|
||||
/* Tx Stats*/
|
||||
u64_stats_t tx_packets;
|
||||
u64_stats_t tx_bytes;
|
||||
|
||||
struct u64_stats_sync syncp;
|
||||
};
|
||||
|
||||
struct bcmasp_intf_ops {
|
||||
unsigned long (*rx_desc_read)(struct bcmasp_intf *intf);
|
||||
void (*rx_buffer_write)(struct bcmasp_intf *intf, dma_addr_t addr);
|
||||
void (*rx_desc_write)(struct bcmasp_intf *intf, dma_addr_t addr);
|
||||
unsigned long (*tx_read)(struct bcmasp_intf *intf);
|
||||
void (*tx_write)(struct bcmasp_intf *intf, dma_addr_t addr);
|
||||
};
|
||||
|
||||
struct bcmasp_priv;
|
||||
|
||||
struct bcmasp_intf {
|
||||
struct list_head list;
|
||||
struct net_device *ndev;
|
||||
struct bcmasp_priv *parent;
|
||||
|
||||
/* ASP Ch */
|
||||
int channel;
|
||||
int port;
|
||||
const struct bcmasp_intf_ops *ops;
|
||||
|
||||
/* Used for splitting shared resources */
|
||||
int index;
|
||||
|
||||
struct napi_struct tx_napi;
|
||||
/* TX ring, starts on a new cacheline boundary */
|
||||
void __iomem *tx_spb_dma;
|
||||
int tx_spb_index;
|
||||
int tx_spb_clean_index;
|
||||
struct bcmasp_desc *tx_spb_cpu;
|
||||
dma_addr_t tx_spb_dma_addr;
|
||||
dma_addr_t tx_spb_dma_valid;
|
||||
dma_addr_t tx_spb_dma_read;
|
||||
struct bcmasp_tx_cb *tx_cbs;
|
||||
|
||||
/* RX ring, starts on a new cacheline boundary */
|
||||
void __iomem *rx_edpkt_cfg;
|
||||
void __iomem *rx_edpkt_dma;
|
||||
int rx_edpkt_index;
|
||||
int rx_buf_order;
|
||||
struct bcmasp_desc *rx_edpkt_cpu;
|
||||
dma_addr_t rx_edpkt_dma_addr;
|
||||
dma_addr_t rx_edpkt_dma_read;
|
||||
|
||||
/* RX buffer prefetcher ring*/
|
||||
void *rx_ring_cpu;
|
||||
dma_addr_t rx_ring_dma;
|
||||
dma_addr_t rx_ring_dma_valid;
|
||||
struct napi_struct rx_napi;
|
||||
|
||||
struct bcmasp_res res;
|
||||
unsigned int crc_fwd;
|
||||
|
||||
/* PHY device */
|
||||
struct device_node *phy_dn;
|
||||
struct device_node *ndev_dn;
|
||||
phy_interface_t phy_interface;
|
||||
bool internal_phy;
|
||||
int old_pause;
|
||||
int old_link;
|
||||
int old_duplex;
|
||||
|
||||
u32 msg_enable;
|
||||
|
||||
/* Statistics */
|
||||
struct bcmasp_intf_stats64 stats64;
|
||||
};
|
||||
|
||||
#define NUM_MDA_FILTERS 32
|
||||
struct bcmasp_mda_filter {
|
||||
/* Current owner of this filter */
|
||||
int port;
|
||||
bool en;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 mask[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct bcmasp_hw_info {
|
||||
u32 rx_ctrl_flush;
|
||||
u32 umac2fb;
|
||||
u32 rx_ctrl_fb_out_frame_count;
|
||||
u32 rx_ctrl_fb_filt_out_frame_count;
|
||||
u32 rx_ctrl_fb_rx_fifo_depth;
|
||||
};
|
||||
|
||||
struct bcmasp_plat_data {
|
||||
struct bcmasp_hw_info *hw_info;
|
||||
};
|
||||
|
||||
struct bcmasp_priv {
|
||||
struct platform_device *pdev;
|
||||
struct clk *clk;
|
||||
|
||||
int irq;
|
||||
u32 irq_mask;
|
||||
|
||||
void __iomem *base;
|
||||
struct bcmasp_hw_info *hw_info;
|
||||
|
||||
struct list_head intfs;
|
||||
|
||||
struct bcmasp_mda_filter mda_filters[NUM_MDA_FILTERS];
|
||||
|
||||
/* MAC destination address filters lock */
|
||||
spinlock_t mda_lock;
|
||||
|
||||
/* Protects accesses to ASP_CTRL_CLOCK_CTRL */
|
||||
spinlock_t clk_lock;
|
||||
};
|
||||
|
||||
static inline unsigned long bcmasp_intf_rx_desc_read(struct bcmasp_intf *intf)
|
||||
{
|
||||
return intf->ops->rx_desc_read(intf);
|
||||
}
|
||||
|
||||
static inline void bcmasp_intf_rx_buffer_write(struct bcmasp_intf *intf,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
intf->ops->rx_buffer_write(intf, addr);
|
||||
}
|
||||
|
||||
static inline void bcmasp_intf_rx_desc_write(struct bcmasp_intf *intf,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
intf->ops->rx_desc_write(intf, addr);
|
||||
}
|
||||
|
||||
static inline unsigned long bcmasp_intf_tx_read(struct bcmasp_intf *intf)
|
||||
{
|
||||
return intf->ops->tx_read(intf);
|
||||
}
|
||||
|
||||
static inline void bcmasp_intf_tx_write(struct bcmasp_intf *intf,
|
||||
dma_addr_t addr)
|
||||
{
|
||||
intf->ops->tx_write(intf, addr);
|
||||
}
|
||||
|
||||
#define __BCMASP_IO_MACRO(name, m) \
|
||||
static inline u32 name##_rl(struct bcmasp_intf *intf, u32 off) \
|
||||
{ \
|
||||
u32 reg = readl_relaxed(intf->m + off); \
|
||||
return reg; \
|
||||
} \
|
||||
static inline void name##_wl(struct bcmasp_intf *intf, u32 val, u32 off)\
|
||||
{ \
|
||||
writel_relaxed(val, intf->m + off); \
|
||||
}
|
||||
|
||||
#define BCMASP_IO_MACRO(name) __BCMASP_IO_MACRO(name, res.name)
|
||||
#define BCMASP_FP_IO_MACRO(name) __BCMASP_IO_MACRO(name, name)
|
||||
|
||||
BCMASP_IO_MACRO(umac);
|
||||
BCMASP_IO_MACRO(umac2fb);
|
||||
BCMASP_IO_MACRO(rgmii);
|
||||
BCMASP_FP_IO_MACRO(tx_spb_dma);
|
||||
BCMASP_IO_MACRO(tx_spb_ctrl);
|
||||
BCMASP_IO_MACRO(tx_spb_top);
|
||||
BCMASP_IO_MACRO(tx_epkt_core);
|
||||
BCMASP_IO_MACRO(tx_pause_ctrl);
|
||||
BCMASP_FP_IO_MACRO(rx_edpkt_dma);
|
||||
BCMASP_FP_IO_MACRO(rx_edpkt_cfg);
|
||||
|
||||
#define __BCMASP_FP_IO_MACRO_Q(name, m) \
|
||||
static inline u64 name##_rq(struct bcmasp_intf *intf, u32 off) \
|
||||
{ \
|
||||
u64 reg = readq_relaxed(intf->m + off); \
|
||||
return reg; \
|
||||
} \
|
||||
static inline void name##_wq(struct bcmasp_intf *intf, u64 val, u32 off)\
|
||||
{ \
|
||||
writeq_relaxed(val, intf->m + off); \
|
||||
}
|
||||
|
||||
#define BCMASP_FP_IO_MACRO_Q(name) __BCMASP_FP_IO_MACRO_Q(name, name)
|
||||
|
||||
BCMASP_FP_IO_MACRO_Q(tx_spb_dma);
|
||||
BCMASP_FP_IO_MACRO_Q(rx_edpkt_dma);
|
||||
BCMASP_FP_IO_MACRO_Q(rx_edpkt_cfg);
|
||||
|
||||
#define PKT_OFFLOAD_NOP (0 << 28)
|
||||
#define PKT_OFFLOAD_HDR_OP (1 << 28)
|
||||
#define PKT_OFFLOAD_HDR_WRBACK BIT(19)
|
||||
#define PKT_OFFLOAD_HDR_COUNT(x) ((x) << 16)
|
||||
#define PKT_OFFLOAD_HDR_SIZE_1(x) ((x) << 4)
|
||||
#define PKT_OFFLOAD_HDR_SIZE_2(x) (x)
|
||||
#define PKT_OFFLOAD_HDR2_SIZE_2(x) ((x) << 24)
|
||||
#define PKT_OFFLOAD_HDR2_SIZE_3(x) ((x) << 12)
|
||||
#define PKT_OFFLOAD_HDR2_SIZE_4(x) (x)
|
||||
#define PKT_OFFLOAD_EPKT_OP (2 << 28)
|
||||
#define PKT_OFFLOAD_EPKT_WRBACK BIT(23)
|
||||
#define PKT_OFFLOAD_EPKT_IP(x) ((x) << 21)
|
||||
#define PKT_OFFLOAD_EPKT_TP(x) ((x) << 19)
|
||||
#define PKT_OFFLOAD_EPKT_LEN(x) ((x) << 16)
|
||||
#define PKT_OFFLOAD_EPKT_CSUM_L3 BIT(15)
|
||||
#define PKT_OFFLOAD_EPKT_CSUM_L2 BIT(14)
|
||||
#define PKT_OFFLOAD_EPKT_ID(x) ((x) << 12)
|
||||
#define PKT_OFFLOAD_EPKT_SEQ(x) ((x) << 10)
|
||||
#define PKT_OFFLOAD_EPKT_TS(x) ((x) << 8)
|
||||
#define PKT_OFFLOAD_EPKT_BLOC(x) (x)
|
||||
#define PKT_OFFLOAD_END_OP (7 << 28)
|
||||
|
||||
struct bcmasp_pkt_offload {
|
||||
__be32 nop;
|
||||
__be32 header;
|
||||
__be32 header2;
|
||||
__be32 epkt;
|
||||
__be32 end;
|
||||
};
|
||||
|
||||
#define BCMASP_CORE_IO_MACRO(name, offset) \
|
||||
static inline u32 name##_core_rl(struct bcmasp_priv *priv, \
|
||||
u32 off) \
|
||||
{ \
|
||||
u32 reg = readl_relaxed(priv->base + (offset) + off); \
|
||||
return reg; \
|
||||
} \
|
||||
static inline void name##_core_wl(struct bcmasp_priv *priv, \
|
||||
u32 val, u32 off) \
|
||||
{ \
|
||||
writel_relaxed(val, priv->base + (offset) + off); \
|
||||
}
|
||||
|
||||
BCMASP_CORE_IO_MACRO(intr2, ASP_INTR2_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(wakeup_intr2, ASP_WAKEUP_INTR2_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(tx_analytics, ASP_TX_ANALYTICS_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(rx_analytics, ASP_RX_ANALYTICS_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(rx_ctrl, ASP_RX_CTRL_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(rx_filter, ASP_RX_FILTER_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(rx_edpkt, ASP_EDPKT_OFFSET);
|
||||
BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL);
|
||||
|
||||
struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv,
|
||||
struct device_node *ndev_dn, int i);
|
||||
|
||||
void bcmasp_interface_destroy(struct bcmasp_intf *intf);
|
||||
|
||||
void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en);
|
||||
|
||||
void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en);
|
||||
|
||||
void bcmasp_flush_rx_port(struct bcmasp_intf *intf);
|
||||
|
||||
extern const struct ethtool_ops bcmasp_ethtool_ops;
|
||||
|
||||
int bcmasp_interface_suspend(struct bcmasp_intf *intf);
|
||||
|
||||
int bcmasp_interface_resume(struct bcmasp_intf *intf);
|
||||
|
||||
void bcmasp_set_promisc(struct bcmasp_intf *intf, bool en);
|
||||
|
||||
void bcmasp_set_allmulti(struct bcmasp_intf *intf, bool en);
|
||||
|
||||
void bcmasp_set_broad(struct bcmasp_intf *intf, bool en);
|
||||
|
||||
void bcmasp_set_oaddr(struct bcmasp_intf *intf, const unsigned char *addr,
|
||||
bool en);
|
||||
|
||||
int bcmasp_set_en_mda_filter(struct bcmasp_intf *intf, unsigned char *addr,
|
||||
unsigned char *mask);
|
||||
|
||||
void bcmasp_disable_all_filters(struct bcmasp_intf *intf);
|
||||
|
||||
void bcmasp_core_clock_set_intf(struct bcmasp_intf *intf, bool en);
|
||||
|
||||
#endif
|
40
drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c
Normal file
40
drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c
Normal file
@ -0,0 +1,40 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#define pr_fmt(fmt) "bcmasp_ethtool: " fmt
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "bcmasp.h"
|
||||
#include "bcmasp_intf_defs.h"
|
||||
|
||||
static void bcmasp_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
strscpy(info->driver, "bcmasp", sizeof(info->driver));
|
||||
strscpy(info->bus_info, dev_name(dev->dev.parent),
|
||||
sizeof(info->bus_info));
|
||||
}
|
||||
|
||||
static u32 bcmasp_get_msglevel(struct net_device *dev)
|
||||
{
|
||||
struct bcmasp_intf *intf = netdev_priv(dev);
|
||||
|
||||
return intf->msg_enable;
|
||||
}
|
||||
|
||||
static void bcmasp_set_msglevel(struct net_device *dev, u32 level)
|
||||
{
|
||||
struct bcmasp_intf *intf = netdev_priv(dev);
|
||||
|
||||
intf->msg_enable = level;
|
||||
}
|
||||
|
||||
const struct ethtool_ops bcmasp_ethtool_ops = {
|
||||
.get_drvinfo = bcmasp_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_link_ksettings = phy_ethtool_get_link_ksettings,
|
||||
.set_link_ksettings = phy_ethtool_set_link_ksettings,
|
||||
.get_msglevel = bcmasp_get_msglevel,
|
||||
.set_msglevel = bcmasp_set_msglevel,
|
||||
};
|
1342
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
Normal file
1342
drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
Normal file
File diff suppressed because it is too large
Load Diff
196
drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h
Normal file
196
drivers/net/ethernet/broadcom/asp2/bcmasp_intf_defs.h
Normal file
@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __BCMASP_INTF_DEFS_H
|
||||
#define __BCMASP_INTF_DEFS_H
|
||||
|
||||
#define UMC_OFFSET(intf) \
|
||||
((((intf)->port) * 0x800) + 0xc000)
|
||||
#define UMC_CMD 0x008
|
||||
#define UMC_CMD_TX_EN BIT(0)
|
||||
#define UMC_CMD_RX_EN BIT(1)
|
||||
#define UMC_CMD_SPEED_SHIFT 0x2
|
||||
#define UMC_CMD_SPEED_MASK 0x3
|
||||
#define UMC_CMD_SPEED_10 0x0
|
||||
#define UMC_CMD_SPEED_100 0x1
|
||||
#define UMC_CMD_SPEED_1000 0x2
|
||||
#define UMC_CMD_SPEED_2500 0x3
|
||||
#define UMC_CMD_PROMISC BIT(4)
|
||||
#define UMC_CMD_PAD_EN BIT(5)
|
||||
#define UMC_CMD_CRC_FWD BIT(6)
|
||||
#define UMC_CMD_PAUSE_FWD BIT(7)
|
||||
#define UMC_CMD_RX_PAUSE_IGNORE BIT(8)
|
||||
#define UMC_CMD_TX_ADDR_INS BIT(9)
|
||||
#define UMC_CMD_HD_EN BIT(10)
|
||||
#define UMC_CMD_SW_RESET BIT(13)
|
||||
#define UMC_CMD_LCL_LOOP_EN BIT(15)
|
||||
#define UMC_CMD_AUTO_CONFIG BIT(22)
|
||||
#define UMC_CMD_CNTL_FRM_EN BIT(23)
|
||||
#define UMC_CMD_NO_LEN_CHK BIT(24)
|
||||
#define UMC_CMD_RMT_LOOP_EN BIT(25)
|
||||
#define UMC_CMD_PRBL_EN BIT(27)
|
||||
#define UMC_CMD_TX_PAUSE_IGNORE BIT(28)
|
||||
#define UMC_CMD_TX_RX_EN BIT(29)
|
||||
#define UMC_CMD_RUNT_FILTER_DIS BIT(30)
|
||||
#define UMC_MAC0 0x0c
|
||||
#define UMC_MAC1 0x10
|
||||
#define UMC_FRM_LEN 0x14
|
||||
#define UMC_EEE_CTRL 0x64
|
||||
#define EN_LPI_RX_PAUSE BIT(0)
|
||||
#define EN_LPI_TX_PFC BIT(1)
|
||||
#define EN_LPI_TX_PAUSE BIT(2)
|
||||
#define EEE_EN BIT(3)
|
||||
#define RX_FIFO_CHECK BIT(4)
|
||||
#define EEE_TX_CLK_DIS BIT(5)
|
||||
#define DIS_EEE_10M BIT(6)
|
||||
#define LP_IDLE_PREDICTION_MODE BIT(7)
|
||||
#define UMC_EEE_LPI_TIMER 0x68
|
||||
#define UMC_PAUSE_CNTRL 0x330
|
||||
#define UMC_TX_FLUSH 0x334
|
||||
#define UMC_MIB_START 0x400
|
||||
#define UMC_MIB_CNTRL 0x580
|
||||
#define UMC_MIB_CNTRL_RX_CNT_RST BIT(0)
|
||||
#define UMC_MIB_CNTRL_RUNT_CNT_RST BIT(1)
|
||||
#define UMC_MIB_CNTRL_TX_CNT_RST BIT(2)
|
||||
#define UMC_RX_MAX_PKT_SZ 0x608
|
||||
#define UMC_MPD_CTRL 0x620
|
||||
#define UMC_MPD_CTRL_MPD_EN BIT(0)
|
||||
#define UMC_MPD_CTRL_PSW_EN BIT(27)
|
||||
#define UMC_PSW_MS 0x624
|
||||
#define UMC_PSW_LS 0x628
|
||||
|
||||
#define UMAC2FB_OFFSET_2_1 0x9f044
|
||||
#define UMAC2FB_OFFSET 0x9f03c
|
||||
#define UMAC2FB_CFG 0x0
|
||||
#define UMAC2FB_CFG_OPUT_EN BIT(0)
|
||||
#define UMAC2FB_CFG_VLAN_EN BIT(1)
|
||||
#define UMAC2FB_CFG_SNAP_EN BIT(2)
|
||||
#define UMAC2FB_CFG_BCM_TG_EN BIT(3)
|
||||
#define UMAC2FB_CFG_IPUT_EN BIT(4)
|
||||
#define UMAC2FB_CFG_CHID_SHIFT 8
|
||||
#define UMAC2FB_CFG_OK_SEND_SHIFT 24
|
||||
#define UMAC2FB_CFG_DEFAULT_EN \
|
||||
(UMAC2FB_CFG_OPUT_EN | UMAC2FB_CFG_VLAN_EN \
|
||||
| UMAC2FB_CFG_SNAP_EN | UMAC2FB_CFG_IPUT_EN)
|
||||
|
||||
#define RGMII_OFFSET(intf) \
|
||||
((((intf)->port) * 0x100) + 0xd000)
|
||||
#define RGMII_EPHY_CNTRL 0x00
|
||||
#define RGMII_EPHY_CFG_IDDQ_BIAS BIT(0)
|
||||
#define RGMII_EPHY_CFG_EXT_PWRDOWN BIT(1)
|
||||
#define RGMII_EPHY_CFG_FORCE_DLL_EN BIT(2)
|
||||
#define RGMII_EPHY_CFG_IDDQ_GLOBAL BIT(3)
|
||||
#define RGMII_EPHY_CK25_DIS BIT(4)
|
||||
#define RGMII_EPHY_RESET BIT(7)
|
||||
#define RGMII_OOB_CNTRL 0x0c
|
||||
#define RGMII_LINK BIT(4)
|
||||
#define RGMII_OOB_DIS BIT(5)
|
||||
#define RGMII_MODE_EN BIT(6)
|
||||
#define RGMII_ID_MODE_DIS BIT(16)
|
||||
|
||||
#define RGMII_PORT_CNTRL 0x60
|
||||
#define RGMII_PORT_MODE_EPHY 0
|
||||
#define RGMII_PORT_MODE_GPHY 1
|
||||
#define RGMII_PORT_MODE_EXT_EPHY 2
|
||||
#define RGMII_PORT_MODE_EXT_GPHY 3
|
||||
#define RGMII_PORT_MODE_EXT_RVMII 4
|
||||
#define RGMII_PORT_MODE_MASK GENMASK(2, 0)
|
||||
|
||||
#define RGMII_SYS_LED_CNTRL 0x74
|
||||
#define RGMII_SYS_LED_CNTRL_LINK_OVRD BIT(15)
|
||||
|
||||
#define TX_SPB_DMA_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x30) + 0x48180)
|
||||
#define TX_SPB_DMA_READ 0x00
|
||||
#define TX_SPB_DMA_BASE 0x08
|
||||
#define TX_SPB_DMA_END 0x10
|
||||
#define TX_SPB_DMA_VALID 0x18
|
||||
#define TX_SPB_DMA_FIFO_CTRL 0x20
|
||||
#define TX_SPB_DMA_FIFO_FLUSH BIT(0)
|
||||
#define TX_SPB_DMA_FIFO_STATUS 0x24
|
||||
|
||||
#define TX_SPB_CTRL_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x68) + 0x49340)
|
||||
#define TX_SPB_CTRL_ENABLE 0x0
|
||||
#define TX_SPB_CTRL_ENABLE_EN BIT(0)
|
||||
#define TX_SPB_CTRL_XF_CTRL2 0x20
|
||||
#define TX_SPB_CTRL_XF_BID_SHIFT 16
|
||||
|
||||
#define TX_SPB_TOP_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x1c) + 0x4a0e0)
|
||||
#define TX_SPB_TOP_BLKOUT 0x0
|
||||
#define TX_SPB_TOP_SPRE_BW_CTRL 0x4
|
||||
|
||||
#define TX_EPKT_C_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x120) + 0x40900)
|
||||
#define TX_EPKT_C_CFG_MISC 0x0
|
||||
#define TX_EPKT_C_CFG_MISC_EN BIT(0)
|
||||
#define TX_EPKT_C_CFG_MISC_PT BIT(1)
|
||||
#define TX_EPKT_C_CFG_MISC_PS_SHIFT 14
|
||||
#define TX_EPKT_C_CFG_MISC_FD_SHIFT 20
|
||||
|
||||
#define TX_PAUSE_CTRL_OFFSET(intf) \
|
||||
((((intf)->channel * 0xc) + 0x49a20))
|
||||
#define TX_PAUSE_MAP_VECTOR 0x8
|
||||
|
||||
#define RX_EDPKT_DMA_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x38) + 0x9ca00)
|
||||
#define RX_EDPKT_DMA_WRITE 0x00
|
||||
#define RX_EDPKT_DMA_READ 0x08
|
||||
#define RX_EDPKT_DMA_BASE 0x10
|
||||
#define RX_EDPKT_DMA_END 0x18
|
||||
#define RX_EDPKT_DMA_VALID 0x20
|
||||
#define RX_EDPKT_DMA_FULLNESS 0x28
|
||||
#define RX_EDPKT_DMA_MIN_THRES 0x2c
|
||||
#define RX_EDPKT_DMA_CH_XONOFF 0x30
|
||||
|
||||
#define RX_EDPKT_CFG_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x70) + 0x9c600)
|
||||
#define RX_EDPKT_CFG_CFG0 0x0
|
||||
#define RX_EDPKT_CFG_CFG0_DBUF_SHIFT 9
|
||||
#define RX_EDPKT_CFG_CFG0_RBUF 0x0
|
||||
#define RX_EDPKT_CFG_CFG0_RBUF_4K 0x1
|
||||
#define RX_EDPKT_CFG_CFG0_BUF_4K 0x2
|
||||
/* EFRM STUFF, 0 = no byte stuff, 1 = two byte stuff */
|
||||
#define RX_EDPKT_CFG_CFG0_EFRM_STUF BIT(11)
|
||||
#define RX_EDPKT_CFG_CFG0_BALN_SHIFT 12
|
||||
#define RX_EDPKT_CFG_CFG0_NO_ALN 0
|
||||
#define RX_EDPKT_CFG_CFG0_4_ALN 2
|
||||
#define RX_EDPKT_CFG_CFG0_64_ALN 6
|
||||
#define RX_EDPKT_RING_BUFFER_WRITE 0x38
|
||||
#define RX_EDPKT_RING_BUFFER_READ 0x40
|
||||
#define RX_EDPKT_RING_BUFFER_BASE 0x48
|
||||
#define RX_EDPKT_RING_BUFFER_END 0x50
|
||||
#define RX_EDPKT_RING_BUFFER_VALID 0x58
|
||||
#define RX_EDPKT_CFG_ENABLE 0x6c
|
||||
#define RX_EDPKT_CFG_ENABLE_EN BIT(0)
|
||||
|
||||
#define RX_SPB_DMA_OFFSET(intf) \
|
||||
((((intf)->channel) * 0x30) + 0xa0000)
|
||||
#define RX_SPB_DMA_READ 0x00
|
||||
#define RX_SPB_DMA_BASE 0x08
|
||||
#define RX_SPB_DMA_END 0x10
|
||||
#define RX_SPB_DMA_VALID 0x18
|
||||
#define RX_SPB_DMA_FIFO_CTRL 0x20
|
||||
#define RX_SPB_DMA_FIFO_FLUSH BIT(0)
|
||||
#define RX_SPB_DMA_FIFO_STATUS 0x24
|
||||
|
||||
#define RX_SPB_CTRL_OFFSET(intf) \
|
||||
((((intf)->channel - 6) * 0x68) + 0xa1000)
|
||||
#define RX_SPB_CTRL_ENABLE 0x00
|
||||
#define RX_SPB_CTRL_ENABLE_EN BIT(0)
|
||||
|
||||
#define RX_PAUSE_CTRL_OFFSET(intf) \
|
||||
((((intf)->channel - 6) * 0x4) + 0xa1138)
|
||||
#define RX_PAUSE_MAP_VECTOR 0x00
|
||||
|
||||
#define RX_SPB_TOP_CTRL_OFFSET(intf) \
|
||||
((((intf)->channel - 6) * 0x14) + 0xa2000)
|
||||
#define RX_SPB_TOP_BLKOUT 0x00
|
||||
|
||||
#define NUM_4K_BUFFERS 32
|
||||
#define RING_BUFFER_SIZE (PAGE_SIZE * NUM_4K_BUFFERS)
|
||||
|
||||
#define DESC_RING_COUNT (64 * NUM_4K_BUFFERS)
|
||||
#define DESC_SIZE 16
|
||||
#define DESC_RING_SIZE (DESC_RING_COUNT * DESC_SIZE)
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user