// SPDX-License-Identifier: GPL-2.0 /* * Lantiq / Intel GSWIP switch driver for VRX200, xRX300 and xRX330 SoCs * * Copyright (C) 2010 Lantiq Deutschland * Copyright (C) 2012 John Crispin <john@phrozen.org> * Copyright (C) 2017 - 2019 Hauke Mehrtens <hauke@hauke-m.de> * * The VLAN and bridge model the GSWIP hardware uses does not directly * matches the model DSA uses. * * The hardware has 64 possible table entries for bridges with one VLAN * ID, one flow id and a list of ports for each bridge. All entries which * match the same flow ID are combined in the mac learning table, they * act as one global bridge. * The hardware does not support VLAN filter on the port, but on the * bridge, this driver converts the DSA model to the hardware. * * The CPU gets all the exception frames which do not match any forwarding * rule and the CPU port is also added to all bridges. This makes it possible * to handle all the special cases easily in software. * At the initialization the driver allocates one bridge table entry for * each switch port which is used when the port is used without an * explicit bridge. This prevents the frames from being forwarded * between all LAN ports by default.
*/
/* Maximum packet size supported by the switch. In theory this should be 10240, * but long packets currently cause lock-ups with an MTU of over 2526. Medium * packets are sometimes dropped (e.g. TCP over 2477, UDP over 2516-2519, ICMP * over 2526), hence an MTU value of 2400 seems safe. This issue only affects * packet reception. This is probably caused by the PPA engine, which is on the * RX part of the device. Packet transmission works properly up to 10240.
*/ #define GSWIP_MAX_PACKET_LENGTH 2400
struct gswip_hw_info { int max_ports; int cpu_port; conststruct dsa_switch_ops *ops;
};
val &= ~(clear);
val |= set;
gswip_mii_w(priv, val, offset);
}
staticvoid gswip_mii_mask_cfg(struct gswip_priv *priv, u32 clear, u32 set, int port)
{ /* There's no MII_CFG register for the CPU port */ if (!dsa_is_cpu_port(priv->ds, port))
gswip_mii_mask(priv, clear, set, GSWIP_MII_CFGp(port));
}
staticvoid gswip_mii_mask_pcdu(struct gswip_priv *priv, u32 clear, u32 set, int port)
{ switch (port) { case 0:
gswip_mii_mask(priv, clear, set, GSWIP_MII_PCDU0); break; case 1:
gswip_mii_mask(priv, clear, set, GSWIP_MII_PCDU1); break; case 5:
gswip_mii_mask(priv, clear, set, GSWIP_MII_PCDU5); break;
}
}
staticint gswip_mdio_poll(struct gswip_priv *priv)
{ int cnt = 100;
while (likely(cnt--)) {
u32 ctrl = gswip_mdio_r(priv, GSWIP_MDIO_CTRL);
/* Add the LAN port into a bridge with the CPU port by * default. This prevents automatic forwarding of * packages between the LAN ports when no explicit * bridge is configured.
*/ staticint gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add)
{ struct gswip_pce_table_entry vlan_active = {0,}; struct gswip_pce_table_entry vlan_mapping = {0,}; unsignedint cpu_port = priv->hw_info->cpu_port; int err;
vlan_active.index = port + 1;
vlan_active.table = GSWIP_TABLE_ACTIVE_VLAN;
vlan_active.key[0] = 0; /* vid */
vlan_active.val[0] = port + 1 /* fid */;
vlan_active.valid = add;
err = gswip_pce_table_entry_write(priv, &vlan_active); if (err) {
dev_err(priv->dev, "failed to write active VLAN: %d\n", err); return err;
}
if (!add) return 0;
vlan_mapping.index = port + 1;
vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
vlan_mapping.val[0] = 0 /* vid */;
vlan_mapping.val[1] = BIT(port) | BIT(cpu_port);
vlan_mapping.val[2] = 0;
err = gswip_pce_table_entry_write(priv, &vlan_mapping); if (err) {
dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err); return err;
}
return 0;
}
staticint gswip_port_setup(struct dsa_switch *ds, int port)
{ struct gswip_priv *priv = ds->priv; int err;
if (!dsa_is_cpu_port(ds, port)) {
err = gswip_add_single_port_br(priv, port, true); if (err) return err;
}
/* Do not allow changing the VLAN filtering options while in bridge */ if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) {
NL_SET_ERR_MSG_MOD(extack, "Dynamic toggling of vlan_filtering not supported"); return -EIO;
}
if (vlan_filtering) { /* Use tag based VLAN */
gswip_switch_mask(priv,
GSWIP_PCE_VCTRL_VSR,
GSWIP_PCE_VCTRL_UVR | GSWIP_PCE_VCTRL_VIMR |
GSWIP_PCE_VCTRL_VEMR,
GSWIP_PCE_VCTRL(port));
gswip_switch_mask(priv, GSWIP_PCE_PCTRL_0_TVM, 0,
GSWIP_PCE_PCTRL_0p(port));
} else { /* Use port based VLAN */
gswip_switch_mask(priv,
GSWIP_PCE_VCTRL_UVR | GSWIP_PCE_VCTRL_VIMR |
GSWIP_PCE_VCTRL_VEMR,
GSWIP_PCE_VCTRL_VSR,
GSWIP_PCE_VCTRL(port));
gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_TVM,
GSWIP_PCE_PCTRL_0p(port));
}
return 0;
}
staticint gswip_setup(struct dsa_switch *ds)
{ struct gswip_priv *priv = ds->priv; unsignedint cpu_port = priv->hw_info->cpu_port; int i; int err;
/* disable port fetch/store dma on all ports */ for (i = 0; i < priv->hw_info->max_ports; i++) {
gswip_port_disable(ds, i);
gswip_port_vlan_filtering(ds, i, false, NULL);
}
/* Deactivate MDIO PHY auto polling. Some PHYs as the AR8030 have an * interoperability problem with this auto polling mechanism because * their status registers think that the link is in a different state * than it actually is. For the AR8030 it has the BMSR_ESTATEN bit set * as well as ESTATUS_1000_TFULL and ESTATUS_1000_XFULL. This makes the * auto polling state machine consider the link being negotiated with * 1Gbit/s. Since the PHY itself is a Fast Ethernet RMII PHY this leads * to the switch port being completely dead (RX and TX are both not * working). * Also with various other PHY / port combinations (PHY11G GPHY, PHY22F * GPHY, external RGMII PEF7071/7072) any traffic would stop. Sometimes * it would work fine for a few minutes to hours and then stop, on * other device it would no traffic could be sent or received at all. * Testing shows that when PHY auto polling is disabled these problems * go away.
*/
gswip_mdio_w(priv, 0x0, GSWIP_MDIO_MDC_CFG0);
/* Disable the xMII interface and clear it's isolation bit */ for (i = 0; i < priv->hw_info->max_ports; i++)
gswip_mii_mask_cfg(priv,
GSWIP_MII_CFG_EN | GSWIP_MII_CFG_ISOLATE,
0, i);
/* enable special tag insertion on cpu port */
gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN,
GSWIP_FDMA_PCTRLp(cpu_port));
/* accept special tag in ingress direction */
gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
GSWIP_PCE_PCTRL_0p(cpu_port));
staticint gswip_vlan_active_remove(struct gswip_priv *priv, int idx)
{ struct gswip_pce_table_entry vlan_active = {0,}; int err;
vlan_active.index = idx;
vlan_active.table = GSWIP_TABLE_ACTIVE_VLAN;
vlan_active.valid = false;
err = gswip_pce_table_entry_write(priv, &vlan_active); if (err)
dev_err(priv->dev, "failed to delete active VLAN: %d\n", err);
priv->vlans[idx].bridge = NULL;
return err;
}
staticint gswip_vlan_add_unaware(struct gswip_priv *priv, struct net_device *bridge, int port)
{ struct gswip_pce_table_entry vlan_mapping = {0,}; unsignedint max_ports = priv->hw_info->max_ports; unsignedint cpu_port = priv->hw_info->cpu_port; bool active_vlan_created = false; int idx = -1; int i; int err;
/* Check if there is already a page for this bridge */ for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { if (priv->vlans[i].bridge == bridge) {
idx = i; break;
}
}
/* If this bridge is not programmed yet, add a Active VLAN table * entry in a free slot and prepare the VLAN mapping table entry.
*/ if (idx == -1) {
idx = gswip_vlan_active_create(priv, bridge, -1, 0); if (idx < 0) return idx;
active_vlan_created = true;
vlan_mapping.index = idx;
vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING; /* VLAN ID byte, maps to the VLAN ID of vlan active table */
vlan_mapping.val[0] = 0;
} else { /* Read the existing VLAN mapping entry from the switch */
vlan_mapping.index = idx;
vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
err = gswip_pce_table_entry_read(priv, &vlan_mapping); if (err) {
dev_err(priv->dev, "failed to read VLAN mapping: %d\n",
err); return err;
}
}
/* Update the VLAN mapping entry and write it to the switch */
vlan_mapping.val[1] |= BIT(cpu_port);
vlan_mapping.val[1] |= BIT(port);
err = gswip_pce_table_entry_write(priv, &vlan_mapping); if (err) {
dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err); /* In case an Active VLAN was creaetd delete it again */ if (active_vlan_created)
gswip_vlan_active_remove(priv, idx); return err;
}
staticint gswip_vlan_add_aware(struct gswip_priv *priv, struct net_device *bridge, int port,
u16 vid, bool untagged, bool pvid)
{ struct gswip_pce_table_entry vlan_mapping = {0,}; unsignedint max_ports = priv->hw_info->max_ports; unsignedint cpu_port = priv->hw_info->cpu_port; bool active_vlan_created = false; int idx = -1; int fid = -1; int i; int err;
/* Check if there is already a page for this bridge */ for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { if (priv->vlans[i].bridge == bridge) { if (fid != -1 && fid != priv->vlans[i].fid)
dev_err(priv->dev, "one bridge with multiple flow ids\n");
fid = priv->vlans[i].fid; if (priv->vlans[i].vid == vid) {
idx = i; break;
}
}
}
/* If this bridge is not programmed yet, add a Active VLAN table * entry in a free slot and prepare the VLAN mapping table entry.
*/ if (idx == -1) {
idx = gswip_vlan_active_create(priv, bridge, fid, vid); if (idx < 0) return idx;
active_vlan_created = true;
vlan_mapping.index = idx;
vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING; /* VLAN ID byte, maps to the VLAN ID of vlan active table */
vlan_mapping.val[0] = vid;
} else { /* Read the existing VLAN mapping entry from the switch */
vlan_mapping.index = idx;
vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
err = gswip_pce_table_entry_read(priv, &vlan_mapping); if (err) {
dev_err(priv->dev, "failed to read VLAN mapping: %d\n",
err); return err;
}
}
vlan_mapping.val[0] = vid; /* Update the VLAN mapping entry and write it to the switch */
vlan_mapping.val[1] |= BIT(cpu_port);
vlan_mapping.val[2] |= BIT(cpu_port);
vlan_mapping.val[1] |= BIT(port); if (untagged)
vlan_mapping.val[2] &= ~BIT(port); else
vlan_mapping.val[2] |= BIT(port);
err = gswip_pce_table_entry_write(priv, &vlan_mapping); if (err) {
dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err); /* In case an Active VLAN was creaetd delete it again */ if (active_vlan_created)
gswip_vlan_active_remove(priv, idx); return err;
}
if (pvid)
gswip_switch_w(priv, idx, GSWIP_PCE_DEFPVID(port));
return 0;
}
staticint gswip_vlan_remove(struct gswip_priv *priv, struct net_device *bridge, int port,
u16 vid, bool pvid, bool vlan_aware)
{ struct gswip_pce_table_entry vlan_mapping = {0,}; unsignedint max_ports = priv->hw_info->max_ports; unsignedint cpu_port = priv->hw_info->cpu_port; int idx = -1; int i; int err;
/* Check if there is already a page for this bridge */ for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { if (priv->vlans[i].bridge == bridge &&
(!vlan_aware || priv->vlans[i].vid == vid)) {
idx = i; break;
}
}
if (idx == -1) {
dev_err(priv->dev, "bridge to leave does not exists\n"); return -ENOENT;
}
/* In case all ports are removed from the bridge, remove the VLAN */ if ((vlan_mapping.val[1] & ~BIT(cpu_port)) == 0) {
err = gswip_vlan_active_remove(priv, idx); if (err) {
dev_err(priv->dev, "failed to write active VLAN: %d\n",
err); return err;
}
}
/* GSWIP 2.2 (GRX300) and later program here the VID directly. */ if (pvid)
gswip_switch_w(priv, 0, GSWIP_PCE_DEFPVID(port));
/* When the bridge uses VLAN filtering we have to configure VLAN * specific bridges. No bridge is configured here.
*/ if (!br_vlan_enabled(br)) {
err = gswip_vlan_add_unaware(priv, br, port); if (err) return err;
priv->port_vlan_filter &= ~BIT(port);
} else {
priv->port_vlan_filter |= BIT(port);
} return gswip_add_single_port_br(priv, port, false);
}
/* When the bridge uses VLAN filtering we have to configure VLAN * specific bridges. No bridge is configured here.
*/ if (!br_vlan_enabled(br))
gswip_vlan_remove(priv, br, port, 0, true, false);
}
staticint gswip_port_vlan_prepare(struct dsa_switch *ds, int port, conststruct switchdev_obj_port_vlan *vlan, struct netlink_ext_ack *extack)
{ struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port)); struct gswip_priv *priv = ds->priv; unsignedint max_ports = priv->hw_info->max_ports; int pos = max_ports; int i, idx = -1;
/* We only support VLAN filtering on bridges */ if (!dsa_is_cpu_port(ds, port) && !bridge) return -EOPNOTSUPP;
/* Check if there is already a page for this VLAN */ for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { if (priv->vlans[i].bridge == bridge &&
priv->vlans[i].vid == vlan->vid) {
idx = i; break;
}
}
/* If this VLAN is not programmed yet, we have to reserve * one entry in the VLAN table. Make sure we start at the * next position round.
*/ if (idx == -1) { /* Look for a free slot */ for (; pos < ARRAY_SIZE(priv->vlans); pos++) { if (!priv->vlans[pos].bridge) {
idx = pos;
pos++; break;
}
}
if (idx == -1) {
NL_SET_ERR_MSG_MOD(extack, "No slot in VLAN table"); return -ENOSPC;
}
}
err = gswip_port_vlan_prepare(ds, port, vlan, extack); if (err) return err;
/* We have to receive all packets on the CPU port and should not * do any VLAN filtering here. This is also called with bridge * NULL and then we do not know for which bridge to configure * this.
*/ if (dsa_is_cpu_port(ds, port)) return 0;
/* We have to receive all packets on the CPU port and should not * do any VLAN filtering here. This is also called with bridge * NULL and then we do not know for which bridge to configure * this.
*/ if (dsa_is_cpu_port(ds, port)) return 0;
staticint gswip_port_max_mtu(struct dsa_switch *ds, int port)
{ /* Includes 8 bytes for special header. */ return GSWIP_MAX_PACKET_LENGTH - VLAN_ETH_HLEN - ETH_FCS_LEN;
}
staticint gswip_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{ struct gswip_priv *priv = ds->priv;
/* CPU port always has maximum mtu of user ports, so use it to set * switch frame size, including 8 byte special header.
*/ if (dsa_is_cpu_port(ds, port)) {
new_mtu += 8;
gswip_switch_w(priv, VLAN_ETH_HLEN + new_mtu + ETH_FCS_LEN,
GSWIP_MAC_FLEN);
}
/* Enable MLEN for ports with non-standard MTUs, including the special * header on the CPU port added above.
*/ if (new_mtu != ETH_DATA_LEN)
gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
GSWIP_MAC_CTRL_2p(port)); else
gswip_switch_mask(priv, GSWIP_MAC_CTRL_2_MLEN, 0,
GSWIP_MAC_CTRL_2p(port));
return 0;
}
staticvoid gswip_xrx200_phylink_get_caps(struct dsa_switch *ds, int port, struct phylink_config *config)
{ switch (port) { case 0: case 1:
phy_interface_set_rgmii(config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_MII,
config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_REVMII,
config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_RMII,
config->supported_interfaces); break;
case 2: case 3: case 4: case 6:
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
config->supported_interfaces); break;
case 5:
phy_interface_set_rgmii(config->supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
config->supported_interfaces); break;
}
ret = clk_prepare_enable(gphy_fw->clk_gate); if (ret) return ret;
reset_control_assert(gphy_fw->reset);
/* The vendor BSP uses a 200ms delay after asserting the reset line. * Without this some users are observing that the PHY is not coming up * on the MDIO bus.
*/
msleep(200);
ret = request_firmware(&fw, gphy_fw->fw_name, dev); if (ret) return dev_err_probe(dev, ret, "failed to load firmware: %s\n",
gphy_fw->fw_name);
/* GPHY cores need the firmware code in a persistent and contiguous * memory area with a 16 kB boundary aligned start address.
*/
size = fw->size + XRX200_GPHY_FW_ALIGN;
gphy_fw->reset = of_reset_control_array_get_exclusive(gphy_fw_np); if (IS_ERR(gphy_fw->reset)) return dev_err_probe(dev, PTR_ERR(gphy_fw->reset), "Failed to lookup gphy reset\n");
return gswip_gphy_fw_load(priv, gphy_fw);
}
staticvoid gswip_gphy_fw_remove(struct gswip_priv *priv, struct gswip_gphy_fw *gphy_fw)
{ int ret;
/* check if the device was fully probed */ if (!gphy_fw->fw_name) return;
ret = regmap_write(priv->rcu_regmap, gphy_fw->fw_addr_offset, 0); if (ret)
dev_err(priv->dev, "can not reset GPHY FW pointer\n");
clk_disable_unprepare(gphy_fw->clk_gate);
reset_control_put(gphy_fw->reset);
}
staticint gswip_gphy_fw_list(struct gswip_priv *priv, struct device_node *gphy_fw_list_np, u32 version)
{ struct device *dev = priv->dev; struct device_node *gphy_fw_np; conststruct of_device_id *match; int err; int i = 0;
/* The VRX200 rev 1.1 uses the GSWIP 2.0 and needs the older * GPHY firmware. The VRX200 rev 1.2 uses the GSWIP 2.1 and also * needs a different GPHY firmware.
*/ if (of_device_is_compatible(gphy_fw_list_np, "lantiq,xrx200-gphy-fw")) { switch (version) { case GSWIP_VERSION_2_0:
priv->gphy_fw_name_cfg = &xrx200a1x_gphy_data; break; case GSWIP_VERSION_2_1:
priv->gphy_fw_name_cfg = &xrx200a2x_gphy_data; break; default: return dev_err_probe(dev, -ENOENT, "unknown GSWIP version: 0x%x\n",
version);
}
}
match = of_match_node(xway_gphy_match, gphy_fw_list_np); if (match && match->data)
priv->gphy_fw_name_cfg = match->data;
if (!priv->gphy_fw_name_cfg) return dev_err_probe(dev, -ENOENT, "GPHY compatible type not supported\n");
priv->num_gphy_fw = of_get_available_child_count(gphy_fw_list_np); if (!priv->num_gphy_fw) return -ENOENT;
priv->rcu_regmap = syscon_regmap_lookup_by_phandle(gphy_fw_list_np, "lantiq,rcu"); if (IS_ERR(priv->rcu_regmap)) return PTR_ERR(priv->rcu_regmap);
/* The standalone PHY11G requires 300ms to be fully * initialized and ready for any MDIO communication after being * taken out of reset. For the SoC-internal GPHY variant there * is no (known) documentation for the minimum time after a * reset. Use the same value as for the standalone variant as * some users have reported internal PHYs not being detected * without any delay.
*/
msleep(300);
return 0;
remove_gphy: for (i = 0; i < priv->num_gphy_fw; i++)
gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); return err;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.