Skip to content

Commit

Permalink
net: dsa: ocelot: add external ocelot switch control
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Colin Foster authored and Jakub Kicinski committed Jan 31, 2023
1 parent 11fc80c commit 3d7316a
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 0 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -15155,6 +15155,7 @@ M: Colin Foster <colin.foster@in-advantage.com>
S: Supported
F: Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml
F: drivers/mfd/ocelot*
F: drivers/net/dsa/ocelot/ocelot_ext.c
F: include/linux/mfd/ocelot.h

OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
Expand Down
20 changes: 20 additions & 0 deletions drivers/net/dsa/ocelot/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ config NET_DSA_MSCC_FELIX_DSA_LIB
Its name comes from the first hardware chip to make use of it
(VSC9959), code named Felix.

config NET_DSA_MSCC_OCELOT_EXT
tristate "Ocelot External Ethernet switch support"
depends on NET_DSA && SPI
depends on NET_VENDOR_MICROSEMI
select MDIO_MSCC_MIIM
select MFD_OCELOT_CORE
select MSCC_OCELOT_SWITCH_LIB
select NET_DSA_MSCC_FELIX_DSA_LIB
select NET_DSA_TAG_OCELOT_8021Q
select NET_DSA_TAG_OCELOT
help
This driver supports the VSC7511, VSC7512, VSC7513 and VSC7514 chips
when controlled through SPI.

The Ocelot switch family is a set of multi-port networking chips. All
of these chips have the ability to be controlled externally through
SPI or PCIe interfaces.

Say "Y" here to enable external control to these chips.

config NET_DSA_MSCC_FELIX
tristate "Ocelot / Felix Ethernet switch support"
depends on NET_DSA && PCI
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/dsa/ocelot/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_NET_DSA_MSCC_FELIX_DSA_LIB) += mscc_felix_dsa_lib.o
obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
obj-$(CONFIG_NET_DSA_MSCC_OCELOT_EXT) += mscc_ocelot_ext.o
obj-$(CONFIG_NET_DSA_MSCC_SEVILLE) += mscc_seville.o

mscc_felix_dsa_lib-objs := felix.o
mscc_felix-objs := felix_vsc9959.o
mscc_ocelot_ext-objs := ocelot_ext.o
mscc_seville-objs := seville_vsc9953.o
163 changes: 163 additions & 0 deletions drivers/net/dsa/ocelot/ocelot_ext.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright 2021-2022 Innovative Advantage Inc.
*/

#include <linux/mfd/ocelot.h>
#include <linux/phylink.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <soc/mscc/ocelot.h>
#include <soc/mscc/vsc7514_regs.h>
#include "felix.h"

#define VSC7514_NUM_PORTS 11

#define OCELOT_PORT_MODE_SERDES (OCELOT_PORT_MODE_SGMII | \
OCELOT_PORT_MODE_QSGMII)

static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = {
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_INTERNAL,
OCELOT_PORT_MODE_NONE,
OCELOT_PORT_MODE_NONE,
OCELOT_PORT_MODE_NONE,
OCELOT_PORT_MODE_NONE,
OCELOT_PORT_MODE_NONE,
OCELOT_PORT_MODE_NONE,
OCELOT_PORT_MODE_NONE,
};

static const struct ocelot_ops ocelot_ext_ops = {
.reset = ocelot_reset,
.wm_enc = ocelot_wm_enc,
.wm_dec = ocelot_wm_dec,
.wm_stat = ocelot_wm_stat,
.port_to_netdev = felix_port_to_netdev,
.netdev_to_port = felix_netdev_to_port,
};

static const char * const vsc7512_resource_names[TARGET_MAX] = {
[SYS] = "sys",
[REW] = "rew",
[S0] = "s0",
[S1] = "s1",
[S2] = "s2",
[QS] = "qs",
[QSYS] = "qsys",
[ANA] = "ana",
};

static const struct felix_info vsc7512_info = {
.resource_names = vsc7512_resource_names,
.regfields = vsc7514_regfields,
.map = vsc7514_regmap,
.ops = &ocelot_ext_ops,
.vcap = vsc7514_vcap_props,
.num_mact_rows = 1024,
.num_ports = VSC7514_NUM_PORTS,
.num_tx_queues = OCELOT_NUM_TC,
.port_modes = vsc7512_port_modes,
};

static int ocelot_ext_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dsa_switch *ds;
struct ocelot *ocelot;
struct felix *felix;
int err;

felix = kzalloc(sizeof(*felix), GFP_KERNEL);
if (!felix)
return -ENOMEM;

dev_set_drvdata(dev, felix);

ocelot = &felix->ocelot;
ocelot->dev = dev;

ocelot->num_flooding_pgids = 1;

felix->info = &vsc7512_info;

ds = kzalloc(sizeof(*ds), GFP_KERNEL);
if (!ds) {
err = -ENOMEM;
dev_err_probe(dev, err, "Failed to allocate DSA switch\n");
goto err_free_felix;
}

ds->dev = dev;
ds->num_ports = felix->info->num_ports;
ds->num_tx_queues = felix->info->num_tx_queues;

ds->ops = &felix_switch_ops;
ds->priv = ocelot;
felix->ds = ds;
felix->tag_proto = DSA_TAG_PROTO_OCELOT;

err = dsa_register_switch(ds);
if (err) {
dev_err_probe(dev, err, "Failed to register DSA switch\n");
goto err_free_ds;
}

return 0;

err_free_ds:
kfree(ds);
err_free_felix:
kfree(felix);
return err;
}

static int ocelot_ext_remove(struct platform_device *pdev)
{
struct felix *felix = dev_get_drvdata(&pdev->dev);

if (!felix)
return 0;

dsa_unregister_switch(felix->ds);

kfree(felix->ds);
kfree(felix);

return 0;
}

static void ocelot_ext_shutdown(struct platform_device *pdev)
{
struct felix *felix = dev_get_drvdata(&pdev->dev);

if (!felix)
return;

dsa_switch_shutdown(felix->ds);

dev_set_drvdata(&pdev->dev, NULL);
}

static const struct of_device_id ocelot_ext_switch_of_match[] = {
{ .compatible = "mscc,vsc7512-switch" },
{ },
};
MODULE_DEVICE_TABLE(of, ocelot_ext_switch_of_match);

static struct platform_driver ocelot_ext_switch_driver = {
.driver = {
.name = "ocelot-switch",
.of_match_table = of_match_ptr(ocelot_ext_switch_of_match),
},
.probe = ocelot_ext_probe,
.remove = ocelot_ext_remove,
.shutdown = ocelot_ext_shutdown,
};
module_platform_driver(ocelot_ext_switch_driver);

MODULE_DESCRIPTION("External Ocelot Switch driver");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(MFD_OCELOT);

0 comments on commit 3d7316a

Please sign in to comment.