Commit 3bb884a4 authored by David S. Miller's avatar David S. Miller

Merge branch 'DSA-driver-for-Vitesse-Felix-switch'

Vladimir Oltean says:

====================
DSA driver for Vitesse Felix switch

This series builds upon the previous "Accomodate DSA front-end into
Ocelot" topic and does the following:

- Reworks the Ocelot (VSC7514) driver to support one more switching core
  (VSC9959), used in NPI mode. Some code which was thought to be
  SoC-specific (ocelot_board.c) wasn't, and vice versa, so it is being
  accordingly moved.
- Exports ocelot driver structures and functions to include/soc/mscc.
- Adds a DSA ocelot front-end for VSC9959, which is a PCI device and
  uses the exported ocelot functionality for hardware configuration.
- Adds a tagger driver for the Vitesse injection/extraction DSA headers.
  This is known to be compatible with at least Ocelot and Felix.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e7be235f 56051948
...@@ -10834,6 +10834,7 @@ M: Microchip Linux Driver Support <UNGLinuxDriver@microchip.com> ...@@ -10834,6 +10834,7 @@ M: Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
S: Supported S: Supported
F: drivers/net/ethernet/mscc/ F: drivers/net/ethernet/mscc/
F: include/soc/mscc/ocelot*
MICROSOFT SURFACE PRO 3 BUTTON DRIVER MICROSOFT SURFACE PRO 3 BUTTON DRIVER
M: Chen Yu <yu.c.chen@intel.com> M: Chen Yu <yu.c.chen@intel.com>
...@@ -17359,6 +17360,14 @@ S: Maintained ...@@ -17359,6 +17360,14 @@ S: Maintained
F: drivers/input/serio/userio.c F: drivers/input/serio/userio.c
F: include/uapi/linux/userio.h F: include/uapi/linux/userio.h
VITESSE FELIX ETHERNET SWITCH DRIVER
M: Vladimir Oltean <vladimir.oltean@nxp.com>
M: Claudiu Manoil <claudiu.manoil@nxp.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/dsa/ocelot/*
F: net/dsa/tag_ocelot.c
VIVID VIRTUAL VIDEO DRIVER VIVID VIRTUAL VIDEO DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl> M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
......
...@@ -52,6 +52,8 @@ source "drivers/net/dsa/microchip/Kconfig" ...@@ -52,6 +52,8 @@ source "drivers/net/dsa/microchip/Kconfig"
source "drivers/net/dsa/mv88e6xxx/Kconfig" source "drivers/net/dsa/mv88e6xxx/Kconfig"
source "drivers/net/dsa/ocelot/Kconfig"
source "drivers/net/dsa/sja1105/Kconfig" source "drivers/net/dsa/sja1105/Kconfig"
config NET_DSA_QCA8K config NET_DSA_QCA8K
......
...@@ -20,4 +20,5 @@ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_SPI) += vitesse-vsc73xx-spi.o ...@@ -20,4 +20,5 @@ obj-$(CONFIG_NET_DSA_VITESSE_VSC73XX_SPI) += vitesse-vsc73xx-spi.o
obj-y += b53/ obj-y += b53/
obj-y += microchip/ obj-y += microchip/
obj-y += mv88e6xxx/ obj-y += mv88e6xxx/
obj-y += ocelot/
obj-y += sja1105/ obj-y += sja1105/
# SPDX-License-Identifier: GPL-2.0-only
config NET_DSA_MSCC_FELIX
tristate "Ocelot / Felix Ethernet switch support"
depends on NET_DSA && PCI
select MSCC_OCELOT_SWITCH
select NET_DSA_TAG_OCELOT
help
This driver supports the VSC9959 network switch, which is a member of
the Vitesse / Microsemi / Microchip Ocelot family of switching cores.
It is embedded as a PCIe function of the NXP LS1028A ENETC integrated
endpoint.
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_NET_DSA_MSCC_FELIX) += mscc_felix.o
mscc_felix-objs := \
felix.o \
felix_vsc9959.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2019 NXP Semiconductors
*/
#ifndef _MSCC_FELIX_H
#define _MSCC_FELIX_H
#define ocelot_to_felix(o) container_of((o), struct felix, ocelot)
/* Platform-specific information */
struct felix_info {
struct resource *target_io_res;
struct resource *port_io_res;
const struct reg_field *regfields;
const u32 *const *map;
const struct ocelot_ops *ops;
int shared_queue_sz;
const struct ocelot_stat_layout *stats_layout;
unsigned int num_stats;
int num_ports;
int pci_bar;
};
extern struct felix_info felix_info_vsc9959;
enum felix_instance {
FELIX_INSTANCE_VSC9959 = 0,
};
/* DSA glue / front-end for struct ocelot */
struct felix {
struct dsa_switch *ds;
struct pci_dev *pdev;
struct felix_info *info;
struct ocelot ocelot;
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -105,7 +105,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) ...@@ -105,7 +105,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
int sz, len, buf_len; int sz, len, buf_len;
struct sk_buff *skb; struct sk_buff *skb;
for (i = 0; i < IFH_LEN; i++) { for (i = 0; i < OCELOT_TAG_LEN / 4; i++) {
err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]); err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
if (err != 4) if (err != 4)
break; break;
...@@ -254,6 +254,57 @@ static const struct of_device_id mscc_ocelot_match[] = { ...@@ -254,6 +254,57 @@ static const struct of_device_id mscc_ocelot_match[] = {
}; };
MODULE_DEVICE_TABLE(of, mscc_ocelot_match); MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
static void ocelot_port_pcs_init(struct ocelot *ocelot, int port)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
/* Disable HDX fast control */
ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
DEV_PORT_MISC);
/* SGMII only for now */
ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
PCS1G_MODE_CFG);
ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
/* Enable PCS */
ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
/* No aneg on SGMII */
ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
/* No loopback */
ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
}
static int ocelot_reset(struct ocelot *ocelot)
{
int retries = 100;
u32 val;
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
do {
msleep(1);
regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
&val);
} while (val && --retries);
if (!retries)
return -ETIMEDOUT;
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
return 0;
}
static const struct ocelot_ops ocelot_ops = {
.pcs_init = ocelot_port_pcs_init,
.reset = ocelot_reset,
};
static int mscc_ocelot_probe(struct platform_device *pdev) static int mscc_ocelot_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
...@@ -262,13 +313,12 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -262,13 +313,12 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
struct ocelot *ocelot; struct ocelot *ocelot;
struct regmap *hsio; struct regmap *hsio;
unsigned int i; unsigned int i;
u32 val;
struct { struct {
enum ocelot_target id; enum ocelot_target id;
char *name; char *name;
u8 optional:1; u8 optional:1;
} res[] = { } io_target[] = {
{ SYS, "sys" }, { SYS, "sys" },
{ REW, "rew" }, { REW, "rew" },
{ QSYS, "qsys" }, { QSYS, "qsys" },
...@@ -288,20 +338,23 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -288,20 +338,23 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ocelot); platform_set_drvdata(pdev, ocelot);
ocelot->dev = &pdev->dev; ocelot->dev = &pdev->dev;
for (i = 0; i < ARRAY_SIZE(res); i++) { for (i = 0; i < ARRAY_SIZE(io_target); i++) {
struct regmap *target; struct regmap *target;
struct resource *res;
target = ocelot_io_platform_init(ocelot, pdev, res[i].name); res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
io_target[i].name);
target = ocelot_regmap_init(ocelot, res);
if (IS_ERR(target)) { if (IS_ERR(target)) {
if (res[i].optional) { if (io_target[i].optional) {
ocelot->targets[res[i].id] = NULL; ocelot->targets[io_target[i].id] = NULL;
continue; continue;
} }
return PTR_ERR(target); return PTR_ERR(target);
} }
ocelot->targets[res[i].id] = target; ocelot->targets[io_target[i].id] = target;
} }
hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio"); hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio");
...@@ -312,7 +365,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -312,7 +365,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
ocelot->targets[HSIO] = hsio; ocelot->targets[HSIO] = hsio;
err = ocelot_chip_init(ocelot); err = ocelot_chip_init(ocelot, &ocelot_ops);
if (err) if (err)
return err; return err;
...@@ -339,18 +392,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ...@@ -339,18 +392,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
ocelot->ptp = 1; ocelot->ptp = 1;
} }
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
do {
msleep(1);
regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
&val);
} while (val);
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */ ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */
ports = of_get_child_by_name(np, "ethernet-ports"); ports = of_get_child_by_name(np, "ethernet-ports");
......
...@@ -97,20 +97,16 @@ static struct regmap_config ocelot_regmap_config = { ...@@ -97,20 +97,16 @@ static struct regmap_config ocelot_regmap_config = {
.reg_stride = 4, .reg_stride = 4,
}; };
struct regmap *ocelot_io_platform_init(struct ocelot *ocelot, struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
struct platform_device *pdev,
const char *name)
{ {
struct resource *res;
void __iomem *regs; void __iomem *regs;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
regs = devm_ioremap_resource(ocelot->dev, res); regs = devm_ioremap_resource(ocelot->dev, res);
if (IS_ERR(regs)) if (IS_ERR(regs))
return ERR_CAST(regs); return ERR_CAST(regs);
ocelot_regmap_config.name = name; ocelot_regmap_config.name = res->name;
return devm_regmap_init_mmio(ocelot->dev, regs,
&ocelot_regmap_config); return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
} }
EXPORT_SYMBOL(ocelot_io_platform_init); EXPORT_SYMBOL(ocelot_regmap_init);
...@@ -423,7 +423,7 @@ static void ocelot_pll5_init(struct ocelot *ocelot) ...@@ -423,7 +423,7 @@ static void ocelot_pll5_init(struct ocelot *ocelot)
HSIO_PLL5G_CFG2_AMPC_SEL(0x10)); HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
} }
int ocelot_chip_init(struct ocelot *ocelot) int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
{ {
int ret; int ret;
...@@ -431,6 +431,7 @@ int ocelot_chip_init(struct ocelot *ocelot) ...@@ -431,6 +431,7 @@ int ocelot_chip_init(struct ocelot *ocelot)
ocelot->stats_layout = ocelot_stats_layout; ocelot->stats_layout = ocelot_stats_layout;
ocelot->num_stats = ARRAY_SIZE(ocelot_stats_layout); ocelot->num_stats = ARRAY_SIZE(ocelot_stats_layout);
ocelot->shared_queue_sz = 224 * 1024; ocelot->shared_queue_sz = 224 * 1024;
ocelot->ops = ops;
ret = ocelot_regfields_init(ocelot, ocelot_regfields); ret = ocelot_regfields_init(ocelot, ocelot_regfields);
if (ret) if (ret)
......
...@@ -42,6 +42,7 @@ struct phylink_link_state; ...@@ -42,6 +42,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_8021Q_VALUE 12 #define DSA_TAG_PROTO_8021Q_VALUE 12
#define DSA_TAG_PROTO_SJA1105_VALUE 13 #define DSA_TAG_PROTO_SJA1105_VALUE 13
#define DSA_TAG_PROTO_KSZ8795_VALUE 14 #define DSA_TAG_PROTO_KSZ8795_VALUE 14
#define DSA_TAG_PROTO_OCELOT_VALUE 15
enum dsa_tag_protocol { enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
...@@ -59,6 +60,7 @@ enum dsa_tag_protocol { ...@@ -59,6 +60,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE, DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE,
DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE, DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE,
DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE, DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE,
DSA_TAG_PROTO_OCELOT = DSA_TAG_PROTO_OCELOT_VALUE,
}; };
struct packet_type; struct packet_type;
......
This diff is collapsed.
...@@ -79,6 +79,13 @@ config NET_DSA_TAG_KSZ ...@@ -79,6 +79,13 @@ config NET_DSA_TAG_KSZ
Say Y if you want to enable support for tagging frames for the Say Y if you want to enable support for tagging frames for the
Microchip 8795/9477/9893 families of switches. Microchip 8795/9477/9893 families of switches.
config NET_DSA_TAG_OCELOT
tristate "Tag driver for Ocelot family of switches"
select PACKING
help
Say Y or M if you want to enable support for tagging frames for the
Ocelot switches (VSC7511, VSC7512, VSC7513, VSC7514, VSC9959).
config NET_DSA_TAG_QCA config NET_DSA_TAG_QCA
tristate "Tag driver for Qualcomm Atheros QCA8K switches" tristate "Tag driver for Qualcomm Atheros QCA8K switches"
help help
......
...@@ -12,6 +12,7 @@ obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
obj-$(CONFIG_NET_DSA_TAG_OCELOT) += tag_ocelot.o
obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment