bcm4908: backport recent bcm_sf2 changes

One 5.12 link fix and 5.13 crossbar support.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
(cherry picked from commit e1b4fd52a8)
This commit is contained in:
Rafał Miłecki 2021-03-17 07:40:49 +01:00
parent 86eb3de66e
commit 15d142262a
7 changed files with 265 additions and 8 deletions

View File

@ -0,0 +1,33 @@
From 8373a0fe9c7160a55482effa8a3f725efd3f8434 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Wed, 10 Mar 2021 13:51:59 +0100
Subject: [PATCH] net: dsa: bcm_sf2: use 2 Gbps IMP port link on BCM4908
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BCM4908 uses 2 Gbps link between switch and the Ethernet interface.
Without this BCM4908 devices were able to achieve only 2 x ~895 Mb/s.
This allows handling e.g. NAT traffic with 940 Mb/s.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/bcm_sf2.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -70,7 +70,10 @@ static void bcm_sf2_imp_setup(struct dsa
/* Force link status for IMP port */
reg = core_readl(priv, offset);
reg |= (MII_SW_OR | LINK_STS);
- reg &= ~GMII_SPEED_UP_2G;
+ if (priv->type == BCM4908_DEVICE_ID)
+ reg |= GMII_SPEED_UP_2G;
+ else
+ reg &= ~GMII_SPEED_UP_2G;
core_writel(priv, reg, offset);
/* Enable Broadcast, Multicast, Unicast forwarding to IMP port */

View File

@ -0,0 +1,72 @@
From 01488a0ccd9abe15565bed50a45afcddbb0fe199 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Fri, 12 Mar 2021 11:41:07 +0100
Subject: [PATCH] net: dsa: bcm_sf2: store PHY interface/mode in port structure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It's needed later for proper switch / crossbar setup.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/bcm_sf2.c | 16 ++++++++++++----
drivers/net/dsa/bcm_sf2.h | 1 +
2 files changed, 13 insertions(+), 4 deletions(-)
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -385,8 +385,9 @@ static void bcm_sf2_intr_disable(struct
static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
struct device_node *dn)
{
+ struct device *dev = priv->dev->ds->dev;
+ struct bcm_sf2_port_status *port_st;
struct device_node *port;
- int mode;
unsigned int port_num;
priv->moca_port = -1;
@@ -395,19 +396,26 @@ static void bcm_sf2_identify_ports(struc
if (of_property_read_u32(port, "reg", &port_num))
continue;
+ if (port_num >= DSA_MAX_PORTS) {
+ dev_err(dev, "Invalid port number %d\n", port_num);
+ continue;
+ }
+
+ port_st = &priv->port_sts[port_num];
+
/* Internal PHYs get assigned a specific 'phy-mode' property
* value: "internal" to help flag them before MDIO probing
* has completed, since they might be turned off at that
* time
*/
- mode = of_get_phy_mode(port);
- if (mode < 0)
+ port_st->mode = of_get_phy_mode(port);
+ if (port_st->mode < 0)
continue;
- if (mode == PHY_INTERFACE_MODE_INTERNAL)
+ if (port_st->mode == PHY_INTERFACE_MODE_INTERNAL)
priv->int_phy_mask |= 1 << port_num;
- if (mode == PHY_INTERFACE_MODE_MOCA)
+ if (port_st->mode == PHY_INTERFACE_MODE_MOCA)
priv->moca_port = port_num;
if (of_property_read_bool(port, "brcm,use-bcm-hdr"))
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -43,6 +43,7 @@ struct bcm_sf2_hw_params {
#define BCM_SF2_REGS_NUM 6
struct bcm_sf2_port_status {
+ int mode;
unsigned int link;
};

View File

@ -0,0 +1,152 @@
From a9349f08ec6c1251d41ef167d27a15cc39bc5b97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Fri, 12 Mar 2021 11:41:08 +0100
Subject: [PATCH] net: dsa: bcm_sf2: setup BCM4908 internal crossbar
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On some SoCs (e.g. BCM4908, BCM631[345]8) SF2 has an integrated
crossbar. It allows connecting its selected external ports to internal
ports. It's used by vendors to handle custom Ethernet setups.
BCM4908 has following 3x2 crossbar. On Asus GT-AC5300 rgmii is used for
connecting external BCM53134S switch. GPHY4 is usually used for WAN
port. More fancy devices use SerDes for 2.5 Gbps Ethernet.
┌──────────┐
SerDes ─── 0 ─┤ │
│ 3x2 ├─ 0 ─── switch port 7
GPHY4 ─── 1 ─┤ │
│ crossbar ├─ 1 ─── runner (accelerator)
rgmii ─── 2 ─┤ │
└──────────┘
Use setup data based on DT info to configure BCM4908's switch port 7.
Right now only GPHY and rgmii variants are supported. Handling SerDes
can be implemented later.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/bcm_sf2.c | 45 ++++++++++++++++++++++++++++++++++
drivers/net/dsa/bcm_sf2.h | 1 +
drivers/net/dsa/bcm_sf2_regs.h | 7 ++++++
3 files changed, 53 insertions(+)
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -374,6 +374,44 @@ static int bcm_sf2_sw_rst(struct bcm_sf2
return 0;
}
+static void bcm_sf2_crossbar_setup(struct bcm_sf2_priv *priv)
+{
+ struct device *dev = priv->dev->ds->dev;
+ int shift;
+ u32 mask;
+ u32 reg;
+ int i;
+
+ mask = BIT(priv->num_crossbar_int_ports) - 1;
+
+ reg = reg_readl(priv, REG_CROSSBAR);
+ switch (priv->type) {
+ case BCM4908_DEVICE_ID:
+ shift = CROSSBAR_BCM4908_INT_P7 * priv->num_crossbar_int_ports;
+ reg &= ~(mask << shift);
+ if (0) /* FIXME */
+ reg |= CROSSBAR_BCM4908_EXT_SERDES << shift;
+ else if (priv->int_phy_mask & BIT(7))
+ reg |= CROSSBAR_BCM4908_EXT_GPHY4 << shift;
+ else if (phy_interface_mode_is_rgmii(priv->port_sts[7].mode))
+ reg |= CROSSBAR_BCM4908_EXT_RGMII << shift;
+ else if (WARN(1, "Invalid port mode\n"))
+ return;
+ break;
+ default:
+ return;
+ }
+ reg_writel(priv, reg, REG_CROSSBAR);
+
+ reg = reg_readl(priv, REG_CROSSBAR);
+ for (i = 0; i < priv->num_crossbar_int_ports; i++) {
+ shift = i * priv->num_crossbar_int_ports;
+
+ dev_dbg(dev, "crossbar int port #%d - ext port #%d\n", i,
+ (reg >> shift) & mask);
+ }
+}
+
static void bcm_sf2_intr_disable(struct bcm_sf2_priv *priv)
{
intrl2_0_mask_set(priv, 0xffffffff);
@@ -737,6 +775,8 @@ static int bcm_sf2_sw_resume(struct dsa_
return ret;
}
+ bcm_sf2_crossbar_setup(priv);
+
ret = bcm_sf2_cfp_resume(ds);
if (ret)
return ret;
@@ -999,6 +1039,7 @@ struct bcm_sf2_of_data {
const u16 *reg_offsets;
unsigned int core_reg_align;
unsigned int num_cfp_rules;
+ unsigned int num_crossbar_int_ports;
};
static const u16 bcm_sf2_4908_reg_offsets[] = {
@@ -1023,6 +1064,7 @@ static const struct bcm_sf2_of_data bcm_
.core_reg_align = 0,
.reg_offsets = bcm_sf2_4908_reg_offsets,
.num_cfp_rules = 0, /* FIXME */
+ .num_crossbar_int_ports = 2,
};
/* Register offsets for the SWITCH_REG_* block */
@@ -1133,6 +1175,7 @@ static int bcm_sf2_sw_probe(struct platf
priv->reg_offsets = data->reg_offsets;
priv->core_reg_align = data->core_reg_align;
priv->num_cfp_rules = data->num_cfp_rules;
+ priv->num_crossbar_int_ports = data->num_crossbar_int_ports;
/* Auto-detection using standard registers will not work, so
* provide an indication of what kind of device we are for
@@ -1187,6 +1230,8 @@ static int bcm_sf2_sw_probe(struct platf
return ret;
}
+ bcm_sf2_crossbar_setup(priv);
+
bcm_sf2_gphy_enable_set(priv->dev->ds, true);
ret = bcm_sf2_mdio_register(ds);
--- a/drivers/net/dsa/bcm_sf2.h
+++ b/drivers/net/dsa/bcm_sf2.h
@@ -70,6 +70,7 @@ struct bcm_sf2_priv {
const u16 *reg_offsets;
unsigned int core_reg_align;
unsigned int num_cfp_rules;
+ unsigned int num_crossbar_int_ports;
/* spinlock protecting access to the indirect registers */
spinlock_t indir_lock;
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -48,6 +48,13 @@ enum bcm_sf2_reg_offs {
#define PHY_PHYAD_SHIFT 8
#define PHY_PHYAD_MASK 0x1F
+/* Relative to REG_CROSSBAR */
+#define CROSSBAR_BCM4908_INT_P7 0
+#define CROSSBAR_BCM4908_INT_RUNNER 1
+#define CROSSBAR_BCM4908_EXT_SERDES 0
+#define CROSSBAR_BCM4908_EXT_GPHY4 1
+#define CROSSBAR_BCM4908_EXT_RGMII 2
+
#define REG_RGMII_CNTRL_P(x) (REG_RGMII_0_CNTRL + (x))
/* Relative to REG_RGMII_CNTRL */

View File

@ -29,7 +29,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1234,10 +1234,14 @@ static int bcm_sf2_sw_probe(struct platf
@@ -1290,10 +1290,14 @@ static int bcm_sf2_sw_probe(struct platf
rev = reg_readl(priv, REG_PHY_REVISION);
priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;

View File

@ -15,7 +15,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1248,6 +1248,12 @@ static int bcm_sf2_sw_probe(struct platf
@@ -1304,6 +1304,12 @@ static int bcm_sf2_sw_probe(struct platf
priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
priv->irq0, priv->irq1);

View File

@ -16,7 +16,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -543,10 +543,19 @@ static void bcm_sf2_sw_mac_config(struct
@@ -592,10 +592,19 @@ static void bcm_sf2_sw_mac_config(struct
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
u32 id_mode_dis = 0, port_mode;
u32 reg, offset;
@ -36,7 +36,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
if (priv->type == BCM4908_DEVICE_ID ||
priv->type == BCM7445_DEVICE_ID)
offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
@@ -574,7 +583,7 @@ static void bcm_sf2_sw_mac_config(struct
@@ -623,7 +632,7 @@ static void bcm_sf2_sw_mac_config(struct
/* Clear id_mode_dis bit, and the existing port mode, let
* RGMII_MODE_EN bet set by mac_link_{up,down}
*/
@ -45,7 +45,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
reg &= ~ID_MODE_DIS;
reg &= ~(PORT_MODE_MASK << PORT_MODE_SHIFT);
reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
@@ -589,7 +598,7 @@ static void bcm_sf2_sw_mac_config(struct
@@ -638,7 +647,7 @@ static void bcm_sf2_sw_mac_config(struct
reg |= RX_PAUSE_EN;
}
@ -54,7 +54,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
force_link:
/* Force link settings detected from the PHY */
@@ -615,6 +624,7 @@ static void bcm_sf2_sw_mac_link_set(stru
@@ -664,6 +673,7 @@ static void bcm_sf2_sw_mac_link_set(stru
phy_interface_t interface, bool link)
{
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
@ -62,7 +62,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
u32 reg;
if (!phy_interface_mode_is_rgmii(interface) &&
@@ -622,13 +632,21 @@ static void bcm_sf2_sw_mac_link_set(stru
@@ -671,13 +681,21 @@ static void bcm_sf2_sw_mac_link_set(stru
interface != PHY_INTERFACE_MODE_REVMII)
return;
@ -86,7 +86,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
}
static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port,
@@ -999,9 +1017,7 @@ static const u16 bcm_sf2_4908_reg_offset
@@ -1051,9 +1069,7 @@ static const u16 bcm_sf2_4908_reg_offset
[REG_PHY_REVISION] = 0x14,
[REG_SPHY_CNTRL] = 0x24,
[REG_CROSSBAR] = 0xc8,