Skip to content

Commit 41e8c70

Browse files
committed
Merge branch 'bcm7278'
Florian Fainelli says: ==================== net: dsa: bcm_sf2: Add support for BCM7278 This patch series adds support for the Broadcom BCM7278 integrated switch which is a successor of the BCM7445 switch. We have a little bit of register shuffling going on, which is why most of the functional changes are to deal with that. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b20b564 + 039a7b8 commit 41e8c70

File tree

8 files changed

+261
-57
lines changed

8 files changed

+261
-57
lines changed

Documentation/devicetree/bindings/net/brcm,bcm7445-switch-v4.0.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Required properties:
44

5-
- compatible: should be "brcm,bcm7445-switch-v4.0"
5+
- compatible: should be "brcm,bcm7445-switch-v4.0" or "brcm,bcm7278-switch-v4.0"
66
- reg: addresses and length of the register sets for the device, must be 6
77
pairs of register addresses and lengths
88
- interrupts: interrupts for the devices, must be two interrupts
@@ -41,6 +41,13 @@ Optional properties:
4141
Admission Control Block supports reporting the number of packets in-flight in a
4242
switch queue
4343

44+
Port subnodes:
45+
46+
Optional properties:
47+
48+
- brcm,use-bcm-hdr: boolean property, if present, indicates that the switch
49+
port has Broadcom tags enabled (per-packet metadata)
50+
4451
Example:
4552

4653
switch_top@f0b00000 {
@@ -114,6 +121,7 @@ switch_top@f0b00000 {
114121
port@0 {
115122
label = "gphy";
116123
reg = <0>;
124+
brcm,use-bcm-hdr;
117125
};
118126
...
119127
};

drivers/net/dsa/b53/b53_common.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,18 @@ static const struct b53_chip_data b53_switch_chips[] = {
16851685
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
16861686
.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
16871687
},
1688+
{
1689+
.chip_id = BCM7278_DEVICE_ID,
1690+
.dev_name = "BCM7278",
1691+
.vlans = 4096,
1692+
.enabled_ports = 0x1ff,
1693+
.arl_entries= 4,
1694+
.cpu_port = B53_CPU_PORT,
1695+
.vta_regs = B53_VTA_REGS,
1696+
.duplex_reg = B53_DUPLEX_STAT_GE,
1697+
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
1698+
.jumbo_size_reg = B53_JUMBO_MAX_SIZE,
1699+
},
16881700
};
16891701

16901702
static int b53_switch_init(struct b53_device *dev)

drivers/net/dsa/b53/b53_priv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum {
6262
BCM53019_DEVICE_ID = 0x53019,
6363
BCM58XX_DEVICE_ID = 0x5800,
6464
BCM7445_DEVICE_ID = 0x7445,
65+
BCM7278_DEVICE_ID = 0x7278,
6566
};
6667

6768
#define B53_N_PORTS 9
@@ -179,7 +180,8 @@ static inline int is5301x(struct b53_device *dev)
179180
static inline int is58xx(struct b53_device *dev)
180181
{
181182
return dev->chip_id == BCM58XX_DEVICE_ID ||
182-
dev->chip_id == BCM7445_DEVICE_ID;
183+
dev->chip_id == BCM7445_DEVICE_ID ||
184+
dev->chip_id == BCM7278_DEVICE_ID;
183185
}
184186

185187
#define B53_CPU_PORT_25 5

drivers/net/dsa/bcm_sf2.c

Lines changed: 133 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -61,30 +61,10 @@ static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
6161
}
6262
}
6363

64-
static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
64+
static void bcm_sf2_brcm_hdr_setup(struct bcm_sf2_priv *priv, int port)
6565
{
66-
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
6766
u32 reg, val;
6867

69-
/* Enable the port memories */
70-
reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
71-
reg &= ~P_TXQ_PSM_VDD(port);
72-
core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
73-
74-
/* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
75-
reg = core_readl(priv, CORE_IMP_CTL);
76-
reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
77-
reg &= ~(RX_DIS | TX_DIS);
78-
core_writel(priv, reg, CORE_IMP_CTL);
79-
80-
/* Enable forwarding */
81-
core_writel(priv, SW_FWDG_EN, CORE_SWMODE);
82-
83-
/* Enable IMP port in dumb mode */
84-
reg = core_readl(priv, CORE_SWITCH_CTRL);
85-
reg |= MII_DUMB_FWDG_EN;
86-
core_writel(priv, reg, CORE_SWITCH_CTRL);
87-
8868
/* Resolve which bit controls the Broadcom tag */
8969
switch (port) {
9070
case 8:
@@ -119,11 +99,43 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
11999
reg = core_readl(priv, CORE_BRCM_HDR_TX_DIS);
120100
reg &= ~(1 << port);
121101
core_writel(priv, reg, CORE_BRCM_HDR_TX_DIS);
102+
}
103+
104+
static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
105+
{
106+
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
107+
u32 reg, offset;
108+
109+
if (priv->type == BCM7445_DEVICE_ID)
110+
offset = CORE_STS_OVERRIDE_IMP;
111+
else
112+
offset = CORE_STS_OVERRIDE_IMP2;
113+
114+
/* Enable the port memories */
115+
reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
116+
reg &= ~P_TXQ_PSM_VDD(port);
117+
core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
118+
119+
/* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
120+
reg = core_readl(priv, CORE_IMP_CTL);
121+
reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
122+
reg &= ~(RX_DIS | TX_DIS);
123+
core_writel(priv, reg, CORE_IMP_CTL);
124+
125+
/* Enable forwarding */
126+
core_writel(priv, SW_FWDG_EN, CORE_SWMODE);
127+
128+
/* Enable IMP port in dumb mode */
129+
reg = core_readl(priv, CORE_SWITCH_CTRL);
130+
reg |= MII_DUMB_FWDG_EN;
131+
core_writel(priv, reg, CORE_SWITCH_CTRL);
132+
133+
bcm_sf2_brcm_hdr_setup(priv, port);
122134

123135
/* Force link status for IMP port */
124-
reg = core_readl(priv, CORE_STS_OVERRIDE_IMP);
136+
reg = core_readl(priv, offset);
125137
reg |= (MII_SW_OR | LINK_STS);
126-
core_writel(priv, reg, CORE_STS_OVERRIDE_IMP);
138+
core_writel(priv, reg, offset);
127139
}
128140

129141
static void bcm_sf2_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
@@ -224,6 +236,10 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
224236
reg &= ~P_TXQ_PSM_VDD(port);
225237
core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
226238

239+
/* Enable Broadcom tags for that port if requested */
240+
if (priv->brcm_tag_mask & BIT(port))
241+
bcm_sf2_brcm_hdr_setup(priv, port);
242+
227243
/* Clear the Rx and Tx disable bits and set to no spanning tree */
228244
core_writel(priv, 0, CORE_G_PCTL_PORT(port));
229245

@@ -503,6 +519,9 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
503519

504520
if (mode == PHY_INTERFACE_MODE_MOCA)
505521
priv->moca_port = port_num;
522+
523+
if (of_property_read_bool(port, "brcm,use-bcm-hdr"))
524+
priv->brcm_tag_mask |= 1 << port_num;
506525
}
507526
}
508527

@@ -591,7 +610,12 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
591610
struct ethtool_eee *p = &priv->port_sts[port].eee;
592611
u32 id_mode_dis = 0, port_mode;
593612
const char *str = NULL;
594-
u32 reg;
613+
u32 reg, offset;
614+
615+
if (priv->type == BCM7445_DEVICE_ID)
616+
offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
617+
else
618+
offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port);
595619

596620
switch (phydev->interface) {
597621
case PHY_INTERFACE_MODE_RGMII:
@@ -662,7 +686,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
662686
if (phydev->duplex == DUPLEX_FULL)
663687
reg |= DUPLX_MODE;
664688

665-
core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
689+
core_writel(priv, reg, offset);
666690

667691
if (!phydev->is_pseudo_fixed_link)
668692
p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev);
@@ -672,9 +696,14 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
672696
struct fixed_phy_status *status)
673697
{
674698
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
675-
u32 duplex, pause;
699+
u32 duplex, pause, offset;
676700
u32 reg;
677701

702+
if (priv->type == BCM7445_DEVICE_ID)
703+
offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
704+
else
705+
offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port);
706+
678707
duplex = core_readl(priv, CORE_DUPSTS);
679708
pause = core_readl(priv, CORE_PAUSESTS);
680709

@@ -703,13 +732,13 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
703732
status->duplex = !!(duplex & (1 << port));
704733
}
705734

706-
reg = core_readl(priv, CORE_STS_OVERRIDE_GMIIP_PORT(port));
735+
reg = core_readl(priv, offset);
707736
reg |= SW_OVERRIDE;
708737
if (status->link)
709738
reg |= LINK_STS;
710739
else
711740
reg &= ~LINK_STS;
712-
core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
741+
core_writel(priv, reg, offset);
713742

714743
if ((pause & (1 << port)) &&
715744
(pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) {
@@ -1009,10 +1038,74 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
10091038
.port_fdb_del = b53_fdb_del,
10101039
};
10111040

1041+
struct bcm_sf2_of_data {
1042+
u32 type;
1043+
const u16 *reg_offsets;
1044+
unsigned int core_reg_align;
1045+
};
1046+
1047+
/* Register offsets for the SWITCH_REG_* block */
1048+
static const u16 bcm_sf2_7445_reg_offsets[] = {
1049+
[REG_SWITCH_CNTRL] = 0x00,
1050+
[REG_SWITCH_STATUS] = 0x04,
1051+
[REG_DIR_DATA_WRITE] = 0x08,
1052+
[REG_DIR_DATA_READ] = 0x0C,
1053+
[REG_SWITCH_REVISION] = 0x18,
1054+
[REG_PHY_REVISION] = 0x1C,
1055+
[REG_SPHY_CNTRL] = 0x2C,
1056+
[REG_RGMII_0_CNTRL] = 0x34,
1057+
[REG_RGMII_1_CNTRL] = 0x40,
1058+
[REG_RGMII_2_CNTRL] = 0x4c,
1059+
[REG_LED_0_CNTRL] = 0x90,
1060+
[REG_LED_1_CNTRL] = 0x94,
1061+
[REG_LED_2_CNTRL] = 0x98,
1062+
};
1063+
1064+
static const struct bcm_sf2_of_data bcm_sf2_7445_data = {
1065+
.type = BCM7445_DEVICE_ID,
1066+
.core_reg_align = 0,
1067+
.reg_offsets = bcm_sf2_7445_reg_offsets,
1068+
};
1069+
1070+
static const u16 bcm_sf2_7278_reg_offsets[] = {
1071+
[REG_SWITCH_CNTRL] = 0x00,
1072+
[REG_SWITCH_STATUS] = 0x04,
1073+
[REG_DIR_DATA_WRITE] = 0x08,
1074+
[REG_DIR_DATA_READ] = 0x0c,
1075+
[REG_SWITCH_REVISION] = 0x10,
1076+
[REG_PHY_REVISION] = 0x14,
1077+
[REG_SPHY_CNTRL] = 0x24,
1078+
[REG_RGMII_0_CNTRL] = 0xe0,
1079+
[REG_RGMII_1_CNTRL] = 0xec,
1080+
[REG_RGMII_2_CNTRL] = 0xf8,
1081+
[REG_LED_0_CNTRL] = 0x40,
1082+
[REG_LED_1_CNTRL] = 0x4c,
1083+
[REG_LED_2_CNTRL] = 0x58,
1084+
};
1085+
1086+
static const struct bcm_sf2_of_data bcm_sf2_7278_data = {
1087+
.type = BCM7278_DEVICE_ID,
1088+
.core_reg_align = 1,
1089+
.reg_offsets = bcm_sf2_7278_reg_offsets,
1090+
};
1091+
1092+
static const struct of_device_id bcm_sf2_of_match[] = {
1093+
{ .compatible = "brcm,bcm7445-switch-v4.0",
1094+
.data = &bcm_sf2_7445_data
1095+
},
1096+
{ .compatible = "brcm,bcm7278-switch-v4.0",
1097+
.data = &bcm_sf2_7278_data
1098+
},
1099+
{ /* sentinel */ },
1100+
};
1101+
MODULE_DEVICE_TABLE(of, bcm_sf2_of_match);
1102+
10121103
static int bcm_sf2_sw_probe(struct platform_device *pdev)
10131104
{
10141105
const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
10151106
struct device_node *dn = pdev->dev.of_node;
1107+
const struct of_device_id *of_id = NULL;
1108+
const struct bcm_sf2_of_data *data;
10161109
struct b53_platform_data *pdata;
10171110
struct dsa_switch_ops *ops;
10181111
struct bcm_sf2_priv *priv;
@@ -1040,11 +1133,22 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
10401133
if (!pdata)
10411134
return -ENOMEM;
10421135

1136+
of_id = of_match_node(bcm_sf2_of_match, dn);
1137+
if (!of_id || !of_id->data)
1138+
return -EINVAL;
1139+
1140+
data = of_id->data;
1141+
1142+
/* Set SWITCH_REG register offsets and SWITCH_CORE align factor */
1143+
priv->type = data->type;
1144+
priv->reg_offsets = data->reg_offsets;
1145+
priv->core_reg_align = data->core_reg_align;
1146+
10431147
/* Auto-detection using standard registers will not work, so
10441148
* provide an indication of what kind of device we are for
10451149
* b53_common to work with
10461150
*/
1047-
pdata->chip_id = BCM7445_DEVICE_ID;
1151+
pdata->chip_id = priv->type;
10481152
dev->pdata = pdata;
10491153

10501154
priv->dev = dev;
@@ -1190,11 +1294,6 @@ static int bcm_sf2_resume(struct device *dev)
11901294
static SIMPLE_DEV_PM_OPS(bcm_sf2_pm_ops,
11911295
bcm_sf2_suspend, bcm_sf2_resume);
11921296

1193-
static const struct of_device_id bcm_sf2_of_match[] = {
1194-
{ .compatible = "brcm,bcm7445-switch-v4.0" },
1195-
{ /* sentinel */ },
1196-
};
1197-
MODULE_DEVICE_TABLE(of, bcm_sf2_of_match);
11981297

11991298
static struct platform_driver bcm_sf2_driver = {
12001299
.probe = bcm_sf2_sw_probe,

0 commit comments

Comments
 (0)