diff options
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 45 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2.h | 1 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2_regs.h | 7 |
3 files changed, 53 insertions, 0 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 416f8deffb20..3a3050e85af7 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -432,6 +432,44 @@ static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv) 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); @@ -864,6 +902,8 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) return ret; } + bcm_sf2_crossbar_setup(priv); + ret = bcm_sf2_cfp_resume(ds); if (ret) return ret; @@ -1136,6 +1176,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[] = { @@ -1160,6 +1201,7 @@ static const struct bcm_sf2_of_data bcm_sf2_4908_data = { .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 */ @@ -1270,6 +1312,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) 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; priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev, "switch"); @@ -1343,6 +1386,8 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) goto out_clk_mdiv; } + bcm_sf2_crossbar_setup(priv); + bcm_sf2_gphy_enable_set(priv->dev->ds, true); ret = bcm_sf2_mdio_register(ds); diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index a0fe0bf46d9f..0d48402068d3 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -74,6 +74,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; diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h index 1d2d55c9f8aa..e297b09411f3 100644 --- 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 */ |