Commit d03790f5 authored by David S. Miller's avatar David S. Miller

Merge branch 'Lantiq-Intel-vrx200-support'

Hauke Mehrtens says:

====================
Add support for Lantiq / Intel vrx200 network

This adds basic support for the GSWIP (Gigabit Switch) found in the
VRX200 SoC.
There are different versions of this IP core used in different SoCs, but
this driver was currently only tested on the VRX200 SoC line, for other
SoCs this driver probably need some adoptions to work.

I also plan to add Layer 2 offloading to the DSA driver and later also
layer 3 offloading which is supported by the PPE HW block.

All these patches should go through the net-next tree.

This depends on the patch "MIPS: lantiq: dma: add dev pointer" which
should go into 4.19.

Changes since:
v2:
 * Send patch "MIPS: lantiq: dma: add dev pointer" separately
 * all: removed return in register write functions
 * switch: uses phylink
 * switch: uses hardware MDIO auto polling
 * switch: use usleep_range() in MDIO busy check
 * switch: configure MDIO bus to 2.5 MHz
 * switch: disable xMII link when it is not used
 * Ethernet: use NAPI for TX cleanups
 * Ethernet: enable clock in open callback
 * Ethernet: improve skb allocation
 * Ethernet: use net_dev->stats

v1:
 * Add "MIPS: lantiq: dma: add dev pointer"
 * checkpatch fixes a all patches
 * Added binding documentation
 * use readx_poll_timeout function and ETIMEOUT error code
 * integrate GPHY firmware loading into DSA driver
 * renamed to NET_DSA_LANTIQ_GSWIP
 * removed some needed casts
 * added of_device_id.data information about the detected switch
 * fixed John's email address
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents aaf92530 14fceff4
Lantiq GSWIP Ethernet switches
==================================
Required properties for GSWIP core:
- compatible : "lantiq,xrx200-gswip" for the embedded GSWIP in the
xRX200 SoC
- reg : memory range of the GSWIP core registers
: memory range of the GSWIP MDIO registers
: memory range of the GSWIP MII registers
See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of
additional required and optional properties.
Required properties for MDIO bus:
- compatible : "lantiq,xrx200-mdio" for the MDIO bus inside the GSWIP
core of the xRX200 SoC and the PHYs connected to it.
See Documentation/devicetree/bindings/net/mdio.txt for a list of additional
required and optional properties.
Required properties for GPHY firmware loading:
- compatible : "lantiq,gphy-fw" and "lantiq,xrx200-gphy-fw",
"lantiq,xrx200a1x-gphy-fw", "lantiq,xrx200a2x-gphy-fw",
"lantiq,xrx300-gphy-fw", or "lantiq,xrx330-gphy-fw"
for the loading of the firmware into the embedded
GPHY core of the SoC.
- lantiq,rcu : reference to the rcu syscon
The GPHY firmware loader has a list of GPHY entries, one for each
embedded GPHY
- reg : Offset of the GPHY firmware register in the RCU
register range
- resets : list of resets of the embedded GPHY
- reset-names : list of names of the resets
Example:
Ethernet switch on the VRX200 SoC:
gswip: gswip@E108000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "lantiq,xrx200-gswip";
reg = < 0xE108000 0x3000 /* switch */
0xE10B100 0x70 /* mdio */
0xE10B1D8 0x30 /* mii */
>;
dsa,member = <0 0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan3";
phy-mode = "rgmii";
phy-handle = <&phy0>;
};
port@1 {
reg = <1>;
label = "lan4";
phy-mode = "rgmii";
phy-handle = <&phy1>;
};
port@2 {
reg = <2>;
label = "lan2";
phy-mode = "internal";
phy-handle = <&phy11>;
};
port@4 {
reg = <4>;
label = "lan1";
phy-mode = "internal";
phy-handle = <&phy13>;
};
port@5 {
reg = <5>;
label = "wan";
phy-mode = "rgmii";
phy-handle = <&phy5>;
};
port@6 {
reg = <0x6>;
label = "cpu";
ethernet = <&eth0>;
};
};
mdio@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "lantiq,xrx200-mdio";
reg = <0>;
phy0: ethernet-phy@0 {
reg = <0x0>;
};
phy1: ethernet-phy@1 {
reg = <0x1>;
};
phy5: ethernet-phy@5 {
reg = <0x5>;
};
phy11: ethernet-phy@11 {
reg = <0x11>;
};
phy13: ethernet-phy@13 {
reg = <0x13>;
};
};
gphy-fw {
compatible = "lantiq,xrx200-gphy-fw", "lantiq,gphy-fw";
lantiq,rcu = <&rcu0>;
gphy@20 {
reg = <0x20>;
resets = <&reset0 31 30>;
reset-names = "gphy";
};
gphy@68 {
reg = <0x68>;
resets = <&reset0 29 28>;
reset-names = "gphy";
};
};
};
Lantiq xRX200 GSWIP PMAC Ethernet driver
==================================
Required properties:
- compatible : "lantiq,xrx200-net" for the PMAC of the embedded
: GSWIP in the xXR200
- reg : memory range of the PMAC core inside of the GSWIP core
- interrupts : TX and RX DMA interrupts. Use interrupt-names "tx" for
: the TX interrupt and "rx" for the RX interrupt.
Example:
eth0: eth@E10B308 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "lantiq,xrx200-net";
reg = <0xE10B308 0x30>;
interrupts = <73>, <72>;
interrupt-names = "tx", "rx";
};
......@@ -8167,6 +8167,15 @@ S: Maintained
F: net/l3mdev
F: include/net/l3mdev.h
LANTIQ / INTEL Ethernet drivers
M: Hauke Mehrtens <hauke@hauke-m.de>
L: netdev@vger.kernel.org
S: Maintained
F: net/dsa/tag_gswip.c
F: drivers/net/ethernet/lantiq_xrx200.c
F: drivers/net/dsa/lantiq_pce.h
F: drivers/net/dsa/intel_gswip.c
LANTIQ MIPS ARCHITECTURE
M: John Crispin <john@phrozen.org>
L: linux-mips@linux-mips.org
......
......@@ -106,7 +106,6 @@ ltq_dma_open(struct ltq_dma_channel *ch)
spin_lock_irqsave(&ltq_dma_lock, flag);
ltq_dma_w32(ch->nr, LTQ_DMA_CS);
ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL);
ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
spin_unlock_irqrestore(&ltq_dma_lock, flag);
}
EXPORT_SYMBOL_GPL(ltq_dma_open);
......
......@@ -505,7 +505,7 @@ void __init ltq_soc_init(void)
clkdev_add_pmu("1a800000.pcie", "msi", 1, 1, PMU1_PCIE2_MSI);
clkdev_add_pmu("1a800000.pcie", "pdi", 1, 1, PMU1_PCIE2_PDI);
clkdev_add_pmu("1a800000.pcie", "ctl", 1, 1, PMU1_PCIE2_CTL);
clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH | PMU_PPE_DP);
clkdev_add_pmu("1e10b308.eth", NULL, 0, 0, PMU_SWITCH | PMU_PPE_DP);
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
} else if (of_machine_is_compatible("lantiq,ar10")) {
......@@ -513,11 +513,11 @@ void __init ltq_soc_init(void)
ltq_ar10_fpi_hz(), ltq_ar10_pp32_hz());
clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0);
clkdev_add_pmu("1e106000.usb", "otg", 1, 0, PMU_USB1);
clkdev_add_pmu("1e108000.eth", NULL, 0, 0, PMU_SWITCH |
clkdev_add_pmu("1e10b308.eth", NULL, 0, 0, PMU_SWITCH |
PMU_PPE_DP | PMU_PPE_TC);
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
clkdev_add_pmu("1f203020.gphy", NULL, 1, 0, PMU_GPHY);
clkdev_add_pmu("1f203068.gphy", NULL, 1, 0, PMU_GPHY);
clkdev_add_pmu("1e108000.gswip", "gphy0", 0, 0, PMU_GPHY);
clkdev_add_pmu("1e108000.gswip", "gphy1", 0, 0, PMU_GPHY);
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE);
clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
......@@ -536,12 +536,12 @@ void __init ltq_soc_init(void)
clkdev_add_pmu(NULL, "ahb", 1, 0, PMU_AHBM | PMU_AHBS);
clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
clkdev_add_pmu("1e108000.eth", NULL, 0, 0,
clkdev_add_pmu("1e10b308.eth", NULL, 0, 0,
PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
PMU_PPE_QSB | PMU_PPE_TOP);
clkdev_add_pmu("1f203020.gphy", NULL, 0, 0, PMU_GPHY);
clkdev_add_pmu("1f203068.gphy", NULL, 0, 0, PMU_GPHY);
clkdev_add_pmu("1e108000.gswip", "gphy0", 0, 0, PMU_GPHY);
clkdev_add_pmu("1e108000.gswip", "gphy1", 0, 0, PMU_GPHY);
clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
......
......@@ -23,6 +23,14 @@ config NET_DSA_LOOP
This enables support for a fake mock-up switch chip which
exercises the DSA APIs.
config NET_DSA_LANTIQ_GSWIP
tristate "Lantiq / Intel GSWIP"
depends on NET_DSA
select NET_DSA_TAG_GSWIP
---help---
This enables support for the Lantiq / Intel GSWIP 2.1 found in
the xrx200 / VR9 SoC.
config NET_DSA_MT7530
tristate "Mediatek MT7530 Ethernet switch support"
depends on NET_DSA
......
......@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o
ifdef CONFIG_NET_DSA_LOOP
obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o
endif
obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* PCE microcode extracted from UGW 7.1.1 switch api
*
* Copyright (c) 2012, 2014, 2015 Lantiq Deutschland GmbH
* Copyright (C) 2012 John Crispin <john@phrozen.org>
* Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
*/
enum {
OUT_MAC0 = 0,
OUT_MAC1,
OUT_MAC2,
OUT_MAC3,
OUT_MAC4,
OUT_MAC5,
OUT_ETHTYP,
OUT_VTAG0,
OUT_VTAG1,
OUT_ITAG0,
OUT_ITAG1, /*10 */
OUT_ITAG2,
OUT_ITAG3,
OUT_IP0,
OUT_IP1,
OUT_IP2,
OUT_IP3,
OUT_SIP0,
OUT_SIP1,
OUT_SIP2,
OUT_SIP3, /*20*/
OUT_SIP4,
OUT_SIP5,
OUT_SIP6,
OUT_SIP7,
OUT_DIP0,
OUT_DIP1,
OUT_DIP2,
OUT_DIP3,
OUT_DIP4,
OUT_DIP5, /*30*/
OUT_DIP6,
OUT_DIP7,
OUT_SESID,
OUT_PROT,
OUT_APP0,
OUT_APP1,
OUT_IGMP0,
OUT_IGMP1,
OUT_IPOFF, /*39*/
OUT_NONE = 63,
};
/* parser's microcode length type */
#define INSTR 0
#define IPV6 1
#define LENACCU 2
/* parser's microcode flag type */
enum {
FLAG_ITAG = 0,
FLAG_VLAN,
FLAG_SNAP,
FLAG_PPPOE,
FLAG_IPV6,
FLAG_IPV6FL,
FLAG_IPV4,
FLAG_IGMP,
FLAG_TU,
FLAG_HOP,
FLAG_NN1, /*10 */
FLAG_NN2,
FLAG_END,
FLAG_NO, /*13*/
};
struct gswip_pce_microcode {
u16 val_3;
u16 val_2;
u16 val_1;
u16 val_0;
};
#define MC_ENTRY(val, msk, ns, out, len, type, flags, ipv4_len) \
{ val, msk, ((ns) << 10 | (out) << 4 | (len) >> 1),\
((len) & 1) << 15 | (type) << 13 | (flags) << 9 | (ipv4_len) << 8 }
static const struct gswip_pce_microcode gswip_pce_microcode[] = {
/* value mask ns fields L type flags ipv4_len */
MC_ENTRY(0x88c3, 0xFFFF, 1, OUT_ITAG0, 4, INSTR, FLAG_ITAG, 0),
MC_ENTRY(0x8100, 0xFFFF, 2, OUT_VTAG0, 2, INSTR, FLAG_VLAN, 0),
MC_ENTRY(0x88A8, 0xFFFF, 1, OUT_VTAG0, 2, INSTR, FLAG_VLAN, 0),
MC_ENTRY(0x8100, 0xFFFF, 1, OUT_VTAG0, 2, INSTR, FLAG_VLAN, 0),
MC_ENTRY(0x8864, 0xFFFF, 17, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0800, 0xFFFF, 21, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x86DD, 0xFFFF, 22, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x8863, 0xFFFF, 16, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0xF800, 10, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 40, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0600, 0x0600, 40, OUT_ETHTYP, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 12, OUT_NONE, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0xAAAA, 0xFFFF, 14, OUT_NONE, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0300, 0xFF00, 41, OUT_NONE, 0, INSTR, FLAG_SNAP, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_DIP7, 3, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 18, OUT_DIP7, 3, INSTR, FLAG_PPPOE, 0),
MC_ENTRY(0x0021, 0xFFFF, 21, OUT_NONE, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0057, 0xFFFF, 22, OUT_NONE, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 40, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x4000, 0xF000, 24, OUT_IP0, 4, INSTR, FLAG_IPV4, 1),
MC_ENTRY(0x6000, 0xF000, 27, OUT_IP0, 3, INSTR, FLAG_IPV6, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 25, OUT_IP3, 2, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 26, OUT_SIP0, 4, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 40, OUT_NONE, 0, LENACCU, FLAG_NO, 0),
MC_ENTRY(0x1100, 0xFF00, 39, OUT_PROT, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0600, 0xFF00, 39, OUT_PROT, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0xFF00, 33, OUT_IP3, 17, INSTR, FLAG_HOP, 0),
MC_ENTRY(0x2B00, 0xFF00, 33, OUT_IP3, 17, INSTR, FLAG_NN1, 0),
MC_ENTRY(0x3C00, 0xFF00, 33, OUT_IP3, 17, INSTR, FLAG_NN2, 0),
MC_ENTRY(0x0000, 0x0000, 39, OUT_PROT, 1, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x00E0, 35, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 40, OUT_NONE, 0, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0xFF00, 33, OUT_NONE, 0, IPV6, FLAG_HOP, 0),
MC_ENTRY(0x2B00, 0xFF00, 33, OUT_NONE, 0, IPV6, FLAG_NN1, 0),
MC_ENTRY(0x3C00, 0xFF00, 33, OUT_NONE, 0, IPV6, FLAG_NN2, 0),
MC_ENTRY(0x0000, 0x0000, 40, OUT_PROT, 1, IPV6, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 40, OUT_SIP0, 16, INSTR, FLAG_NO, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_APP0, 4, INSTR, FLAG_IGMP, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
MC_ENTRY(0x0000, 0x0000, 41, OUT_NONE, 0, INSTR, FLAG_END, 0),
};
......@@ -108,6 +108,13 @@ config LANTIQ_ETOP
---help---
Support for the MII0 inside the Lantiq SoC
config LANTIQ_XRX200
tristate "Lantiq / Intel xRX200 PMAC network driver"
depends on SOC_TYPE_XWAY
---help---
Support for the PMAC of the Gigabit switch (GSWIP) inside the
Lantiq / Intel VRX200 VDSL SoC
source "drivers/net/ethernet/marvell/Kconfig"
source "drivers/net/ethernet/mediatek/Kconfig"
source "drivers/net/ethernet/mellanox/Kconfig"
......
......@@ -49,6 +49,7 @@ obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/
obj-$(CONFIG_JME) += jme.o
obj-$(CONFIG_KORINA) += korina.o
obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
obj-$(CONFIG_LANTIQ_XRX200) += lantiq_xrx200.o
obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/
obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
......
......@@ -432,6 +432,7 @@ ltq_etop_open(struct net_device *dev)
if (!IS_TX(i) && (!IS_RX(i)))
continue;
ltq_dma_open(&ch->dma);
ltq_dma_enable_irq(&ch->dma);
napi_enable(&ch->napi);
}
phy_start(dev->phydev);
......
This diff is collapsed.
......@@ -35,6 +35,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_BRCM_PREPEND,
DSA_TAG_PROTO_DSA,
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_GSWIP,
DSA_TAG_PROTO_KSZ,
DSA_TAG_PROTO_LAN9303,
DSA_TAG_PROTO_MTK,
......
......@@ -38,6 +38,9 @@ config NET_DSA_TAG_DSA
config NET_DSA_TAG_EDSA
bool
config NET_DSA_TAG_GSWIP
bool
config NET_DSA_TAG_KSZ
bool
......
......@@ -9,6 +9,7 @@ dsa_core-$(CONFIG_NET_DSA_TAG_BRCM) += tag_brcm.o
dsa_core-$(CONFIG_NET_DSA_TAG_BRCM_PREPEND) += tag_brcm.o
dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
dsa_core-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
dsa_core-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
dsa_core-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
......
......@@ -52,6 +52,9 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
#ifdef CONFIG_NET_DSA_TAG_EDSA
[DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
#endif
#ifdef CONFIG_NET_DSA_TAG_GSWIP
[DSA_TAG_PROTO_GSWIP] = &gswip_netdev_ops,
#endif
#ifdef CONFIG_NET_DSA_TAG_KSZ
[DSA_TAG_PROTO_KSZ] = &ksz_netdev_ops,
#endif
......
......@@ -206,6 +206,9 @@ extern const struct dsa_device_ops dsa_netdev_ops;
/* tag_edsa.c */
extern const struct dsa_device_ops edsa_netdev_ops;
/* tag_gswip.c */
extern const struct dsa_device_ops gswip_netdev_ops;
/* tag_ksz.c */
extern const struct dsa_device_ops ksz_netdev_ops;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Intel / Lantiq GSWIP V2.0 PMAC tag support
*
* Copyright (C) 2017 - 2018 Hauke Mehrtens <hauke@hauke-m.de>
*/
#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <net/dsa.h>
#include "dsa_priv.h"
#define GSWIP_TX_HEADER_LEN 4
/* special tag in TX path header */
/* Byte 0 */
#define GSWIP_TX_SLPID_SHIFT 0 /* source port ID */
#define GSWIP_TX_SLPID_CPU 2
#define GSWIP_TX_SLPID_APP1 3
#define GSWIP_TX_SLPID_APP2 4
#define GSWIP_TX_SLPID_APP3 5
#define GSWIP_TX_SLPID_APP4 6
#define GSWIP_TX_SLPID_APP5 7
/* Byte 1 */
#define GSWIP_TX_CRCGEN_DIS BIT(7)
#define GSWIP_TX_DPID_SHIFT 0 /* destination group ID */
#define GSWIP_TX_DPID_ELAN 0
#define GSWIP_TX_DPID_EWAN 1
#define GSWIP_TX_DPID_CPU 2
#define GSWIP_TX_DPID_APP1 3
#define GSWIP_TX_DPID_APP2 4
#define GSWIP_TX_DPID_APP3 5
#define GSWIP_TX_DPID_APP4 6
#define GSWIP_TX_DPID_APP5 7
/* Byte 2 */
#define GSWIP_TX_PORT_MAP_EN BIT(7)
#define GSWIP_TX_PORT_MAP_SEL BIT(6)
#define GSWIP_TX_LRN_DIS BIT(5)
#define GSWIP_TX_CLASS_EN BIT(4)
#define GSWIP_TX_CLASS_SHIFT 0
#define GSWIP_TX_CLASS_MASK GENMASK(3, 0)
/* Byte 3 */
#define GSWIP_TX_DPID_EN BIT(0)
#define GSWIP_TX_PORT_MAP_SHIFT 1
#define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1)
#define GSWIP_RX_HEADER_LEN 8
/* special tag in RX path header */
/* Byte 7 */
#define GSWIP_RX_SPPID_SHIFT 4
#define GSWIP_RX_SPPID_MASK GENMASK(6, 4)
static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
int err;
u8 *gswip_tag;
err = skb_cow_head(skb, GSWIP_TX_HEADER_LEN);
if (err)
return NULL;
skb_push(skb, GSWIP_TX_HEADER_LEN);
gswip_tag = skb->data;
gswip_tag[0] = GSWIP_TX_SLPID_CPU;
gswip_tag[1] = GSWIP_TX_DPID_ELAN;
gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
gswip_tag[3] |= GSWIP_TX_DPID_EN;
return skb;
}
static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
{
int port;
u8 *gswip_tag;
if (unlikely(!pskb_may_pull(skb, GSWIP_RX_HEADER_LEN)))
return NULL;
gswip_tag = skb->data - ETH_HLEN;
/* Get source port information */
port = (gswip_tag[7] & GSWIP_RX_SPPID_MASK) >> GSWIP_RX_SPPID_SHIFT;
skb->dev = dsa_master_find_slave(dev, 0, port);
if (!skb->dev)
return NULL;
/* remove GSWIP tag */
skb_pull_rcsum(skb, GSWIP_RX_HEADER_LEN);
return skb;
}
const struct dsa_device_ops gswip_netdev_ops = {
.xmit = gswip_tag_xmit,
.rcv = gswip_tag_rcv,
};
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