/* Write the desired MMD Devad */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_CTRL, MDIO_MMD_VEND2); if (ret < 0) goto err;
/* Write the desired MMD register address */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_DATA, reg); if (ret < 0) goto err;
/* Select the Function : DATA with no post increment */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); if (ret < 0) goto err;
/* Write the data into MMD's selected register */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_DATA, val);
err: if (ret < 0)
dev_err(&bus->dev, "failed to write mmd register\n");
/* Write the desired MMD Devad */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_CTRL, MDIO_MMD_VEND2); if (ret < 0) goto err;
/* Write the desired MMD register address */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_DATA, reg); if (ret < 0) goto err;
/* Select the Function : DATA with no post increment */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); if (ret < 0) goto err;
/* Read the content of the MMD's selected register */
val = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_DATA);
val &= ~mask;
val |= set; /* Write the data into MMD's selected register */
ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr),
MII_MMD_DATA, val);
err: if (ret < 0)
dev_err(&bus->dev, "failed to write mmd register\n");
/* Additional sanity for read command if the specified * entry is invalid
*/
val = mt7530_read(priv, MT7530_ATC); if ((cmd == MT7530_FDB_READ) && (val & ATC_INVALID)) return -EINVAL;
/* If port 6 is available as a CPU port, always prefer that as the default, * otherwise don't care.
*/ staticstruct dsa_port *
mt753x_preferred_default_local_cpu_port(struct dsa_switch *ds)
{ struct dsa_port *cpu_dp = dsa_to_port(ds, 6);
/* Step 1 : Disable MT7531 COREPLL */
val = mt7530_read(priv, MT7531_PLLGP_EN);
val &= ~EN_COREPLL;
mt7530_write(priv, MT7531_PLLGP_EN, val);
/* Step 2: switch to XTAL output */
val = mt7530_read(priv, MT7531_PLLGP_EN);
val |= SW_CLKSW;
mt7530_write(priv, MT7531_PLLGP_EN, val);
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val &= ~RG_COREPLL_EN;
mt7530_write(priv, MT7531_PLLGP_CR0, val);
/* Step 3: disable PLLGP and enable program PLLGP */
val = mt7530_read(priv, MT7531_PLLGP_EN);
val |= SW_PLLGP;
mt7530_write(priv, MT7531_PLLGP_EN, val);
/* Step 4: program COREPLL output frequency to 500MHz */
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val &= ~RG_COREPLL_POSDIV_M;
val |= 2 << RG_COREPLL_POSDIV_S;
mt7530_write(priv, MT7531_PLLGP_CR0, val);
usleep_range(25, 35);
switch (xtal) { case MT7531_XTAL_FSEL_25MHZ:
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val &= ~RG_COREPLL_SDM_PCW_M;
val |= 0x140000 << RG_COREPLL_SDM_PCW_S;
mt7530_write(priv, MT7531_PLLGP_CR0, val); break; case MT7531_XTAL_FSEL_40MHZ:
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val &= ~RG_COREPLL_SDM_PCW_M;
val |= 0x190000 << RG_COREPLL_SDM_PCW_S;
mt7530_write(priv, MT7531_PLLGP_CR0, val); break;
}
/* Set feedback divide ratio update signal to high */
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val |= RG_COREPLL_SDM_PCW_CHG;
mt7530_write(priv, MT7531_PLLGP_CR0, val); /* Wait for at least 16 XTAL clocks */
usleep_range(10, 20);
/* Step 5: set feedback divide ratio update signal to low */
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val &= ~RG_COREPLL_SDM_PCW_CHG;
mt7530_write(priv, MT7531_PLLGP_CR0, val);
/* Enable 325M clock for SGMII */
mt7530_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000);
/* Enable 250SSC clock for RGMII */
mt7530_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000);
/* Step 6: Enable MT7531 PLL */
val = mt7530_read(priv, MT7531_PLLGP_CR0);
val |= RG_COREPLL_EN;
mt7530_write(priv, MT7531_PLLGP_CR0, val);
val = mt7530_read(priv, MT7531_PLLGP_EN);
val |= EN_COREPLL;
mt7530_write(priv, MT7531_PLLGP_EN, val);
usleep_range(25, 35);
}
/* MIB counter doesn't provide a FramesTransmittedOK but instead * provide stats for Unicast, Broadcast and Multicast frames separately. * To simulate a global frame counter, read Unicast and addition Multicast * and Broadcast later
*/
mt7530_read_port_stats(priv, port, MT7530_PORT_MIB_TX_UNICAST, 1,
&mac_stats->FramesTransmittedOK);
/* MIB counter doesn't provide a FramesTransmittedOK but instead * provide stats for Unicast, Broadcast and Multicast frames separately. * To simulate a global frame counter, read Unicast and addition Multicast * and Broadcast later
*/
mt7530_read_port_stats(priv, port, MT7530_PORT_MIB_RX_UNICAST, 1,
&storage->rx_packets);
mt7530_read_port_stats(priv, port, MT7530_PORT_MIB_RX_MULTICAST, 1,
&storage->multicast);
storage->rx_packets += storage->multicast;
mt7530_read_port_stats(priv, port, MT7530_PORT_MIB_RX_BROADCAST, 1,
&data);
storage->rx_packets += data;
val &= ~MT7530_P5_PHY0_SEL & ~MT7530_P5_MAC_SEL & ~MT7530_P5_RGMII_MODE;
switch (priv->p5_mode) { /* MUX_PHY_P0: P0 -> P5 -> SoC MAC */ case MUX_PHY_P0:
val |= MT7530_P5_PHY0_SEL;
fallthrough;
/* MUX_PHY_P4: P4 -> P5 -> SoC MAC */ case MUX_PHY_P4: /* Setup the MAC by default for the cpu port */
mt7530_write(priv, MT753X_PMCR_P(5), 0x56300); break;
/* GMAC5: P5 -> SoC MAC or external PHY */ default:
val |= MT7530_P5_MAC_SEL; break;
}
/* Setup RGMII settings */ if (phy_interface_mode_is_rgmii(interface)) {
val |= MT7530_P5_RGMII_MODE;
/* In Clause 5 of IEEE Std 802-2014, two sublayers of the data link layer (DLL) * of the Open Systems Interconnection basic reference model (OSI/RM) are * described; the medium access control (MAC) and logical link control (LLC) * sublayers. The MAC sublayer is the one facing the physical layer. * * In 8.2 of IEEE Std 802.1Q-2022, the Bridge architecture is described. A * Bridge component comprises a MAC Relay Entity for interconnecting the Ports * of the Bridge, at least two Ports, and higher layer entities with at least a * Spanning Tree Protocol Entity included. * * Each Bridge Port also functions as an end station and shall provide the MAC * Service to an LLC Entity. Each instance of the MAC Service is provided to a * distinct LLC Entity that supports protocol identification, multiplexing, and * demultiplexing, for protocol data unit (PDU) transmission and reception by * one or more higher layer entities. * * It is described in 8.13.9 of IEEE Std 802.1Q-2022 that in a Bridge, the LLC * Entity associated with each Bridge Port is modeled as being directly * connected to the attached Local Area Network (LAN). * * On the switch with CPU port architecture, CPU port functions as Management * Port, and the Management Port functionality is provided by software which * functions as an end station. Software is connected to an IEEE 802 LAN that is * wholly contained within the system that incorporates the Bridge. Software * provides access to the LLC Entity associated with each Bridge Port by the * value of the source port field on the special tag on the frame received by * software. * * We call frames that carry control information to determine the active * topology and current extent of each Virtual Local Area Network (VLAN), i.e., * spanning tree or Shortest Path Bridging (SPB) and Multiple VLAN Registration * Protocol Data Units (MVRPDUs), and frames from other link constrained * protocols, such as Extensible Authentication Protocol over LAN (EAPOL) and * Link Layer Discovery Protocol (LLDP), link-local frames. They are not * forwarded by a Bridge. Permanently configured entries in the filtering * database (FDB) ensure that such frames are discarded by the Forwarding * Process. In 8.6.3 of IEEE Std 802.1Q-2022, this is described in detail: * * Each of the reserved MAC addresses specified in Table 8-1 * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]) shall be * permanently configured in the FDB in C-VLAN components and ERs. * * Each of the reserved MAC addresses specified in Table 8-2 * (01-80-C2-00-00-[01,02,03,04,05,06,07,08,09,0A,0E]) shall be permanently * configured in the FDB in S-VLAN components. * * Each of the reserved MAC addresses specified in Table 8-3 * (01-80-C2-00-00-[01,02,04,0E]) shall be permanently configured in the FDB in * TPMR components. * * The FDB entries for reserved MAC addresses shall specify filtering for all * Bridge Ports and all VIDs. Management shall not provide the capability to * modify or remove entries for reserved MAC addresses. * * The addresses in Table 8-1, Table 8-2, and Table 8-3 determine the scope of * propagation of PDUs within a Bridged Network, as follows: * * The Nearest Bridge group address (01-80-C2-00-00-0E) is an address that no * conformant Two-Port MAC Relay (TPMR) component, Service VLAN (S-VLAN) * component, Customer VLAN (C-VLAN) component, or MAC Bridge can forward. * PDUs transmitted using this destination address, or any other addresses * that appear in Table 8-1, Table 8-2, and Table 8-3 * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]), can * therefore travel no further than those stations that can be reached via a * single individual LAN from the originating station. * * The Nearest non-TPMR Bridge group address (01-80-C2-00-00-03), is an * address that no conformant S-VLAN component, C-VLAN component, or MAC * Bridge can forward; however, this address is relayed by a TPMR component. * PDUs using this destination address, or any of the other addresses that * appear in both Table 8-1 and Table 8-2 but not in Table 8-3 * (01-80-C2-00-00-[00,03,05,06,07,08,09,0A,0B,0C,0D,0F]), will be relayed by * any TPMRs but will propagate no further than the nearest S-VLAN component, * C-VLAN component, or MAC Bridge. * * The Nearest Customer Bridge group address (01-80-C2-00-00-00) is an address * that no conformant C-VLAN component, MAC Bridge can forward; however, it is * relayed by TPMR components and S-VLAN components. PDUs using this * destination address, or any of the other addresses that appear in Table 8-1 * but not in either Table 8-2 or Table 8-3 (01-80-C2-00-00-[00,0B,0C,0D,0F]), * will be relayed by TPMR components and S-VLAN components but will propagate * no further than the nearest C-VLAN component or MAC Bridge. * * Because the LLC Entity associated with each Bridge Port is provided via CPU * port, we must not filter these frames but forward them to CPU port. * * In a Bridge, the transmission Port is majorly decided by ingress and egress * rules, FDB, and spanning tree Port State functions of the Forwarding Process. * For link-local frames, only CPU port should be designated as destination port * in the FDB, and the other functions of the Forwarding Process must not * interfere with the decision of the transmission Port. We call this process * trapping frames to CPU port. * * Therefore, on the switch with CPU port architecture, link-local frames must * be trapped to CPU port, and certain link-local frames received by a Port of a * Bridge comprising a TPMR component or an S-VLAN component must be excluded * from it. * * A Bridge of the switch with CPU port architecture cannot comprise a Two-Port * MAC Relay (TPMR) component as a TPMR component supports only a subset of the * functionality of a MAC Bridge. A Bridge comprising two Ports (Management Port * doesn't count) of this architecture will either function as a standard MAC * Bridge or a standard VLAN Bridge. * * Therefore, a Bridge of this architecture can only comprise S-VLAN components, * C-VLAN components, or MAC Bridge components. Since there's no TPMR component, * we don't need to relay PDUs using the destination addresses specified on the * Nearest non-TPMR section, and the proportion of the Nearest Customer Bridge * section where they must be relayed by TPMR components. * * One option to trap link-local frames to CPU port is to add static FDB entries * with CPU port designated as destination port. However, because that * Independent VLAN Learning (IVL) is being used on every VID, each entry only * applies to a single VLAN Identifier (VID). For a Bridge comprising a MAC * Bridge component or a C-VLAN component, there would have to be 16 times 4096 * entries. This switch intellectual property can only hold a maximum of 2048 * entries. Using this option, there also isn't a mechanism to prevent * link-local frames from being discarded when the spanning tree Port State of * the reception Port is discarding. * * The remaining option is to utilise the BPC, RGAC1, RGAC2, RGAC3, and RGAC4 * registers. Whilst this applies to every VID, it doesn't contain all of the * reserved MAC addresses without affecting the remaining Standard Group MAC * Addresses. The REV_UN frame tag utilised using the RGAC4 register covers the * remaining 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] destination * addresses. It also includes the 01-80-C2-00-00-22 to 01-80-C2-00-00-FF * destination addresses which may be relayed by MAC Bridges or VLAN Bridges. * The latter option provides better but not complete conformance. * * This switch intellectual property also does not provide a mechanism to trap * link-local frames with specific destination addresses to CPU port by Bridge, * to conform to the filtering rules for the distinct Bridge components. * * Therefore, regardless of the type of the Bridge component, link-local frames * with these destination addresses will be trapped to CPU port: * * 01-80-C2-00-00-[00,01,02,03,0E] * * In a Bridge comprising a MAC Bridge component or a C-VLAN component: * * Link-local frames with these destination addresses won't be trapped to CPU * port which won't conform to IEEE Std 802.1Q-2022: * * 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] * * In a Bridge comprising an S-VLAN component: * * Link-local frames with these destination addresses will be trapped to CPU * port which won't conform to IEEE Std 802.1Q-2022: * * 01-80-C2-00-00-00 * * Link-local frames with these destination addresses won't be trapped to CPU * port which won't conform to IEEE Std 802.1Q-2022: * * 01-80-C2-00-00-[04,05,06,07,08,09,0A] * * To trap link-local frames to CPU port as conformant as this switch * intellectual property can allow, link-local frames are made to be regarded as * Bridge Protocol Data Units (BPDUs). This is because this switch intellectual * property only lets the frames regarded as BPDUs bypass the spanning tree Port * State function of the Forwarding Process. * * The only remaining interference is the ingress rules. When the reception Port * has no PVID assigned on software, VLAN-untagged frames won't be allowed in. * There doesn't seem to be a mechanism on the switch intellectual property to * have link-local frames bypass this function of the Forwarding Process.
*/ staticvoid
mt753x_trap_frames(struct mt7530_priv *priv)
{ /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them * VLAN-untagged.
*/
mt7530_rmw(priv, MT753X_BPC,
PAE_BPDU_FR | PAE_EG_TAG_MASK | PAE_PORT_FW_MASK |
BPDU_EG_TAG_MASK | BPDU_PORT_FW_MASK,
PAE_BPDU_FR | PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
PAE_PORT_FW(TO_CPU_FW_CPU_ONLY) |
BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
TO_CPU_FW_CPU_ONLY);
/* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress * them VLAN-untagged.
*/
mt7530_rmw(priv, MT753X_RGAC1,
R02_BPDU_FR | R02_EG_TAG_MASK | R02_PORT_FW_MASK |
R01_BPDU_FR | R01_EG_TAG_MASK | R01_PORT_FW_MASK,
R02_BPDU_FR | R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
R02_PORT_FW(TO_CPU_FW_CPU_ONLY) | R01_BPDU_FR |
R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
TO_CPU_FW_CPU_ONLY);
/* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress * them VLAN-untagged.
*/
mt7530_rmw(priv, MT753X_RGAC2,
R0E_BPDU_FR | R0E_EG_TAG_MASK | R0E_PORT_FW_MASK |
R03_BPDU_FR | R03_EG_TAG_MASK | R03_PORT_FW_MASK,
R0E_BPDU_FR | R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
R0E_PORT_FW(TO_CPU_FW_CPU_ONLY) | R03_BPDU_FR |
R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
TO_CPU_FW_CPU_ONLY);
}
/* Enable Mediatek header mode on the cpu port */
mt7530_write(priv, MT7530_PVC_P(port),
PORT_SPEC_TAG);
/* Enable flooding on the CPU port */
mt7530_set(priv, MT753X_MFC, BC_FFP(BIT(port)) | UNM_FFP(BIT(port)) |
UNU_FFP(BIT(port)));
/* Add the CPU port to the CPU port bitmap for MT7531 and the switch on * the MT7988 SoC. Trapped frames will be forwarded to the CPU port that * is affine to the inbound user port.
*/ if (priv->id == ID_MT7531 || priv->id == ID_MT7988 ||
priv->id == ID_EN7581 || priv->id == ID_AN7583)
mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port)));
/* CPU port gets connected to all user ports of * the switch.
*/
mt7530_write(priv, MT7530_PCR_P(port),
PCR_MATRIX(dsa_user_ports(priv->ds)));
/* Set to fallback mode for independent VLAN learning */
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_FALLBACK_MODE);
}
/* Allow the user port gets connected to the cpu port and also * restore the port matrix if the port is the member of a certain * bridge.
*/ if (dsa_port_is_user(dp)) { struct dsa_port *cpu_dp = dp->cpu_dp;
/* Clear up all port matrix which could be restored in the next * enablement for the port.
*/
priv->ports[port].enable = false;
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
PCR_MATRIX_CLR);
mutex_unlock(&priv->reg_mutex);
if (priv->id != ID_MT7530 && priv->id != ID_MT7621) return;
/* Do not set MT7530_P5_DIS when port 5 is being used for PHY muxing. */ if (port == 5 && priv->p5_mode == GMAC5)
mt7530_set(priv, MT753X_MTRAP, MT7530_P5_DIS); elseif (port == 6)
mt7530_set(priv, MT753X_MTRAP, MT7530_P6_DIS);
}
staticint
mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{ struct mt7530_priv *priv = ds->priv; int length;
u32 val;
/* When a new MTU is set, DSA always set the CPU port's MTU to the * largest MTU of the user ports. Because the switch only has a global * RX length register, only allowing CPU port here is enough.
*/ if (!dsa_is_cpu_port(ds, port)) return 0;
mt7530_mutex_lock(priv);
val = mt7530_mii_read(priv, MT7530_GMACCR);
val &= ~MAX_RX_PKT_LEN_MASK;
/* RX length also includes Ethernet header, MTK tag, and FCS length */
length = new_mtu + ETH_HLEN + MTK_HDR_LEN + ETH_FCS_LEN; if (length <= 1522) {
val |= MAX_RX_PKT_LEN_1522;
} elseif (length <= 1536) {
val |= MAX_RX_PKT_LEN_1536;
} elseif (length <= 1552) {
val |= MAX_RX_PKT_LEN_1552;
} else {
val &= ~MAX_RX_JUMBO_MASK;
val |= MAX_RX_JUMBO(DIV_ROUND_UP(length, 1024));
val |= MAX_RX_PKT_LEN_JUMBO;
}
mt7530_mii_write(priv, MT7530_GMACCR, val);
mt7530_mutex_unlock(priv);
return 0;
}
staticint
mt7530_port_max_mtu(struct dsa_switch *ds, int port)
{ return MT7530_MAX_MTU;
}
/* Add/remove this port to/from the port matrix of the other * ports in the same bridge. If the port is disabled, port * matrix is kept and not being setup until the port becomes * enabled.
*/ if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev)) continue;
if (other_p->enable)
mt7530_rmw(priv, MT7530_PCR_P(other_port),
PCR_MATRIX_MASK, other_p->pm);
}
/* Add/remove the all other ports to this port matrix. For !join * (leaving the bridge), only the CPU port will remain in the port matrix * of this port.
*/
p->pm = PCR_MATRIX(port_bitmap); if (priv->ports[port].enable)
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, p->pm);
}
/* Set to fallback mode for independent VLAN learning */
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_FALLBACK_MODE);
mutex_unlock(&priv->reg_mutex);
return 0;
}
staticvoid
mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
{ struct mt7530_priv *priv = ds->priv; bool all_user_ports_removed = true; int i;
/* This is called after .port_bridge_leave when leaving a VLAN-aware * bridge. Don't set standalone ports to fallback mode.
*/ if (dsa_port_bridge_dev_get(dsa_to_port(ds, port)))
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_FALLBACK_MODE);
/* Set PVID to 0 */
mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK,
G0_PORT_VID_DEF);
for (i = 0; i < priv->ds->num_ports; i++) { if (dsa_is_user_port(ds, i) &&
dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) {
all_user_ports_removed = false; break;
}
}
/* CPU port also does the same thing until all user ports belonging to * the CPU port get out of VLAN filtering mode.
*/ if (all_user_ports_removed) { struct dsa_port *dp = dsa_to_port(ds, port); struct dsa_port *cpu_dp = dp->cpu_dp;
/* Trapped into security mode allows packet forwarding through VLAN * table lookup.
*/ if (dsa_is_user_port(ds, port)) {
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_SECURITY_MODE);
mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK,
G0_PORT_VID(priv->ports[port].pvid));
/* Only accept tagged frames if PVID is not set */ if (!priv->ports[port].pvid)
mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK,
MT7530_VLAN_ACC_TAGGED);
/* Set the port as a user port which is to be able to recognize * VID from incoming packets before fetching entry within the * VLAN table.
*/
mt7530_rmw(priv, MT7530_PVC_P(port),
VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
VLAN_ATTR(MT7530_VLAN_USER) |
PVC_EG_TAG(MT7530_VLAN_EG_DISABLED));
} else { /* Also set CPU ports to the "user" VLAN port attribute, to * allow VLAN classification, but keep the EG_TAG attribute as * "consistent" (i.o.w. don't change its value) for packets * received by the switch from the CPU, so that tagged packets * are forwarded to user ports as tagged, and untagged as * untagged.
*/
mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
VLAN_ATTR(MT7530_VLAN_USER));
}
}
/* When a port is removed from the bridge, the port would be set up * back to the default as is at initial boot which is a VLAN-unaware * port.
*/
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_MATRIX_MODE);
if (vlan_filtering) { /* The port is being kept as VLAN-unaware port when bridge is * set up with vlan_filtering not being set, Otherwise, the * port and the corresponding CPU port is required the setup * for becoming a VLAN-aware port.
*/
mt7530_port_set_vlan_aware(ds, port);
mt7530_port_set_vlan_aware(ds, cpu_dp->index);
} else {
mt7530_port_set_vlan_unaware(ds, port);
}
/* Validate the entry with independent learning, create egress tag per * VLAN and joining the port as one of the port members.
*/
val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | FID(FID_BRIDGED) |
VLAN_VALID;
mt7530_write(priv, MT7530_VAWD1, val);
/* Decide whether adding tag or not for those outgoing packets from the * port inside the VLAN. * CPU port is always taken as a tagged port for serving more than one * VLANs across and also being applied with egress type stack mode for * that VLAN tags would be appended after hardware special tag used as * DSA tag.
*/ if (dsa_port_is_cpu(dp))
val = MT7530_VLAN_EGRESS_STACK; elseif (entry->untagged)
val = MT7530_VLAN_EGRESS_UNTAG; else
val = MT7530_VLAN_EGRESS_TAG;
mt7530_rmw(priv, MT7530_VAWD2,
ETAG_CTRL_P_MASK(entry->port),
ETAG_CTRL_P(entry->port, val));
}
/* Validate the entry with independent learning, keep the original * ingress tag attribute.
*/
val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
VLAN_VALID;
mt7530_write(priv, MT7530_VAWD1, val);
/* Accept all frames if PVID is set */
mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK,
MT7530_VLAN_ACC_ALL);
/* Only configure PVID if VLAN filtering is enabled */ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port)))
mt7530_rmw(priv, MT7530_PPBV1_P(port),
G0_PORT_VID_MASK,
G0_PORT_VID(vlan->vid));
} elseif (vlan->vid && priv->ports[port].pvid == vlan->vid) { /* This VLAN is overwritten without PVID, so unset it */
priv->ports[port].pvid = G0_PORT_VID_DEF;
/* Only accept tagged frames if the port is VLAN-aware */ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port)))
mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK,
MT7530_VLAN_ACC_TAGGED);
/* PVID is being restored to the default whenever the PVID port * is being removed from the VLAN.
*/ if (priv->ports[port].pvid == vlan->vid) {
priv->ports[port].pvid = G0_PORT_VID_DEF;
/* Only accept tagged frames if the port is VLAN-aware */ if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port)))
mt7530_rmw(priv, MT7530_PVC_P(port), ACC_FRM_MASK,
MT7530_VLAN_ACC_TAGGED);
/* Check for existent entry */ if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) return -EEXIST;
val = mt7530_read(priv, MT753X_MIRROR_REG(priv->id));
/* MT7530 only supports one monitor port */
monitor_port = MT753X_MIRROR_PORT_GET(priv->id, val); if (val & MT753X_MIRROR_EN(priv->id) &&
monitor_port != mirror->to_local_port) return -EEXIST;
val |= MT753X_MIRROR_EN(priv->id);
val &= ~MT753X_MIRROR_PORT_MASK(priv->id);
val |= MT753X_MIRROR_PORT_SET(priv->id, mirror->to_local_port);
mt7530_write(priv, MT753X_MIRROR_REG(priv->id), val);
val = mt7530_read(priv, MT7530_PCR_P(port)); if (ingress) {
val |= PORT_RX_MIR;
priv->mirror_rx |= BIT(port);
} else {
val |= PORT_TX_MIR;
priv->mirror_tx |= BIT(port);
}
mt7530_write(priv, MT7530_PCR_P(port), val);
#ifdef CONFIG_GPIOLIB staticinline u32
mt7530_gpio_to_bit(unsignedint offset)
{ /* Map GPIO offset to register bit * [ 2: 0] port 0 LED 0..2 as GPIO 0..2 * [ 6: 4] port 1 LED 0..2 as GPIO 3..5 * [10: 8] port 2 LED 0..2 as GPIO 6..8 * [14:12] port 3 LED 0..2 as GPIO 9..11 * [18:16] port 4 LED 0..2 as GPIO 12..14
*/ return BIT(offset + offset / 3);
}
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.