Skip to content

Commit 3d7316a

Browse files
colin-foster-in-advantagekuba-moo
authored andcommitted
net: dsa: ocelot: add external ocelot switch control
Add control of an external VSC7512 chip. Currently the four copper phy ports are fully functional. Communication to external phys is also functional, but the SGMII / QSGMII interfaces are currently non-functional. Signed-off-by: Colin Foster <colin.foster@in-advantage.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> # regression Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 11fc80c commit 3d7316a

File tree

4 files changed

+186
-0
lines changed

4 files changed

+186
-0
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15155,6 +15155,7 @@ M: Colin Foster <colin.foster@in-advantage.com>
1515515155
S: Supported
1515615156
F: Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml
1515715157
F: drivers/mfd/ocelot*
15158+
F: drivers/net/dsa/ocelot/ocelot_ext.c
1515815159
F: include/linux/mfd/ocelot.h
1515915160

1516015161
OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER

drivers/net/dsa/ocelot/Kconfig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@ config NET_DSA_MSCC_FELIX_DSA_LIB
88
Its name comes from the first hardware chip to make use of it
99
(VSC9959), code named Felix.
1010

11+
config NET_DSA_MSCC_OCELOT_EXT
12+
tristate "Ocelot External Ethernet switch support"
13+
depends on NET_DSA && SPI
14+
depends on NET_VENDOR_MICROSEMI
15+
select MDIO_MSCC_MIIM
16+
select MFD_OCELOT_CORE
17+
select MSCC_OCELOT_SWITCH_LIB
18+
select NET_DSA_MSCC_FELIX_DSA_LIB
19+
select NET_DSA_TAG_OCELOT_8021Q
20+
select NET_DSA_TAG_OCELOT
21+
help
22+
This driver supports the VSC7511, VSC7512, VSC7513 and VSC7514 chips
23+
when controlled through SPI.
24+
25+
The Ocelot switch family is a set of multi-port networking chips. All
26+
of these chips have the ability to be controlled externally through
27+
SPI or PCIe interfaces.
28+
29+
Say "Y" here to enable external control to these chips.
30+
1131
config NET_DSA_MSCC_FELIX
1232
tristate "Ocelot / Felix Ethernet switch support"
1333
depends on NET_DSA && PCI

drivers/net/dsa/ocelot/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-$(CONFIG_NET_DSA_MSCC_FELIX_DSA_LIB) += mscc_felix_dsa_lib.o
33
obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
4+
obj-$(CONFIG_NET_DSA_MSCC_OCELOT_EXT) += mscc_ocelot_ext.o
45
obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o
56

67
mscc_felix_dsa_lib-objs := felix.o
78
mscc_felix-objs := felix_vsc9959.o
9+
mscc_ocelot_ext-objs := ocelot_ext.o
810
mscc_seville-objs := seville_vsc9953.o
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2+
/*
3+
* Copyright 2021-2022 Innovative Advantage Inc.
4+
*/
5+
6+
#include <linux/mfd/ocelot.h>
7+
#include <linux/phylink.h>
8+
#include <linux/platform_device.h>
9+
#include <linux/regmap.h>
10+
#include <soc/mscc/ocelot.h>
11+
#include <soc/mscc/vsc7514_regs.h>
12+
#include "felix.h"
13+
14+
#define VSC7514_NUM_PORTS 11
15+
16+
#define OCELOT_PORT_MODE_SERDES (OCELOT_PORT_MODE_SGMII | \
17+
OCELOT_PORT_MODE_QSGMII)
18+
19+
static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = {
20+
OCELOT_PORT_MODE_INTERNAL,
21+
OCELOT_PORT_MODE_INTERNAL,
22+
OCELOT_PORT_MODE_INTERNAL,
23+
OCELOT_PORT_MODE_INTERNAL,
24+
OCELOT_PORT_MODE_NONE,
25+
OCELOT_PORT_MODE_NONE,
26+
OCELOT_PORT_MODE_NONE,
27+
OCELOT_PORT_MODE_NONE,
28+
OCELOT_PORT_MODE_NONE,
29+
OCELOT_PORT_MODE_NONE,
30+
OCELOT_PORT_MODE_NONE,
31+
};
32+
33+
static const struct ocelot_ops ocelot_ext_ops = {
34+
.reset = ocelot_reset,
35+
.wm_enc = ocelot_wm_enc,
36+
.wm_dec = ocelot_wm_dec,
37+
.wm_stat = ocelot_wm_stat,
38+
.port_to_netdev = felix_port_to_netdev,
39+
.netdev_to_port = felix_netdev_to_port,
40+
};
41+
42+
static const char * const vsc7512_resource_names[TARGET_MAX] = {
43+
[SYS] = "sys",
44+
[REW] = "rew",
45+
[S0] = "s0",
46+
[S1] = "s1",
47+
[S2] = "s2",
48+
[QS] = "qs",
49+
[QSYS] = "qsys",
50+
[ANA] = "ana",
51+
};
52+
53+
static const struct felix_info vsc7512_info = {
54+
.resource_names = vsc7512_resource_names,
55+
.regfields = vsc7514_regfields,
56+
.map = vsc7514_regmap,
57+
.ops = &ocelot_ext_ops,
58+
.vcap = vsc7514_vcap_props,
59+
.num_mact_rows = 1024,
60+
.num_ports = VSC7514_NUM_PORTS,
61+
.num_tx_queues = OCELOT_NUM_TC,
62+
.port_modes = vsc7512_port_modes,
63+
};
64+
65+
static int ocelot_ext_probe(struct platform_device *pdev)
66+
{
67+
struct device *dev = &pdev->dev;
68+
struct dsa_switch *ds;
69+
struct ocelot *ocelot;
70+
struct felix *felix;
71+
int err;
72+
73+
felix = kzalloc(sizeof(*felix), GFP_KERNEL);
74+
if (!felix)
75+
return -ENOMEM;
76+
77+
dev_set_drvdata(dev, felix);
78+
79+
ocelot = &felix->ocelot;
80+
ocelot->dev = dev;
81+
82+
ocelot->num_flooding_pgids = 1;
83+
84+
felix->info = &vsc7512_info;
85+
86+
ds = kzalloc(sizeof(*ds), GFP_KERNEL);
87+
if (!ds) {
88+
err = -ENOMEM;
89+
dev_err_probe(dev, err, "Failed to allocate DSA switch\n");
90+
goto err_free_felix;
91+
}
92+
93+
ds->dev = dev;
94+
ds->num_ports = felix->info->num_ports;
95+
ds->num_tx_queues = felix->info->num_tx_queues;
96+
97+
ds->ops = &felix_switch_ops;
98+
ds->priv = ocelot;
99+
felix->ds = ds;
100+
felix->tag_proto = DSA_TAG_PROTO_OCELOT;
101+
102+
err = dsa_register_switch(ds);
103+
if (err) {
104+
dev_err_probe(dev, err, "Failed to register DSA switch\n");
105+
goto err_free_ds;
106+
}
107+
108+
return 0;
109+
110+
err_free_ds:
111+
kfree(ds);
112+
err_free_felix:
113+
kfree(felix);
114+
return err;
115+
}
116+
117+
static int ocelot_ext_remove(struct platform_device *pdev)
118+
{
119+
struct felix *felix = dev_get_drvdata(&pdev->dev);
120+
121+
if (!felix)
122+
return 0;
123+
124+
dsa_unregister_switch(felix->ds);
125+
126+
kfree(felix->ds);
127+
kfree(felix);
128+
129+
return 0;
130+
}
131+
132+
static void ocelot_ext_shutdown(struct platform_device *pdev)
133+
{
134+
struct felix *felix = dev_get_drvdata(&pdev->dev);
135+
136+
if (!felix)
137+
return;
138+
139+
dsa_switch_shutdown(felix->ds);
140+
141+
dev_set_drvdata(&pdev->dev, NULL);
142+
}
143+
144+
static const struct of_device_id ocelot_ext_switch_of_match[] = {
145+
{ .compatible = "mscc,vsc7512-switch" },
146+
{ },
147+
};
148+
MODULE_DEVICE_TABLE(of, ocelot_ext_switch_of_match);
149+
150+
static struct platform_driver ocelot_ext_switch_driver = {
151+
.driver = {
152+
.name = "ocelot-switch",
153+
.of_match_table = of_match_ptr(ocelot_ext_switch_of_match),
154+
},
155+
.probe = ocelot_ext_probe,
156+
.remove = ocelot_ext_remove,
157+
.shutdown = ocelot_ext_shutdown,
158+
};
159+
module_platform_driver(ocelot_ext_switch_driver);
160+
161+
MODULE_DESCRIPTION("External Ocelot Switch driver");
162+
MODULE_LICENSE("GPL");
163+
MODULE_IMPORT_NS(MFD_OCELOT);

0 commit comments

Comments
 (0)