linux/drivers/net/dsa/mt7530.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Mediatek MT7530 DSA Switch driver
 * Copyright (C) 2017 Sean Wang <[email protected]>
 */
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/iopoll.h>
#include <linux/mdio.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/phylink.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <net/dsa.h>

#include "mt7530.h"

static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs)
{}

/* String, offset, and register size in bytes if different from 4 bytes */
static const struct mt7530_mib_desc mt7530_mib[] =;

static void
mt7530_mutex_lock(struct mt7530_priv *priv)
{}

static void
mt7530_mutex_unlock(struct mt7530_priv *priv)
{}

static void
core_write(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static void
core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set)
{}

static void
core_set(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static void
core_clear(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static int
mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static u32
mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
{}

static void
mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static u32
_mt7530_unlocked_read(struct mt7530_dummy_poll *p)
{}

static u32
_mt7530_read(struct mt7530_dummy_poll *p)
{}

static u32
mt7530_read(struct mt7530_priv *priv, u32 reg)
{}

static void
mt7530_rmw(struct mt7530_priv *priv, u32 reg,
	   u32 mask, u32 set)
{}

static void
mt7530_set(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static void
mt7530_clear(struct mt7530_priv *priv, u32 reg, u32 val)
{}

static int
mt7530_fdb_cmd(struct mt7530_priv *priv, enum mt7530_fdb_cmd cmd, u32 *rsp)
{}

static void
mt7530_fdb_read(struct mt7530_priv *priv, struct mt7530_fdb *fdb)
{}

static void
mt7530_fdb_write(struct mt7530_priv *priv, u16 vid,
		 u8 port_mask, const u8 *mac,
		 u8 aging, u8 type)
{}

/* Set up switch core clock for MT7530 */
static void mt7530_pll_setup(struct mt7530_priv *priv)
{}

/* If port 6 is available as a CPU port, always prefer that as the default,
 * otherwise don't care.
 */
static struct dsa_port *
mt753x_preferred_default_local_cpu_port(struct dsa_switch *ds)
{}

/* Setup port 6 interface mode and TRGMII TX circuit */
static void
mt7530_setup_port6(struct dsa_switch *ds, phy_interface_t interface)
{}

static void
mt7531_pll_setup(struct mt7530_priv *priv)
{}

static void
mt7530_mib_reset(struct dsa_switch *ds)
{}

static int mt7530_phy_read_c22(struct mt7530_priv *priv, int port, int regnum)
{}

static int mt7530_phy_write_c22(struct mt7530_priv *priv, int port, int regnum,
				u16 val)
{}

static int mt7530_phy_read_c45(struct mt7530_priv *priv, int port,
			       int devad, int regnum)
{}

static int mt7530_phy_write_c45(struct mt7530_priv *priv, int port, int devad,
				int regnum, u16 val)
{}

static int
mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
			int regnum)
{}

static int
mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
			 int regnum, u16 data)
{}

static int
mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
{}

static int
mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
			 u16 data)
{}

static int
mt753x_phy_read_c22(struct mii_bus *bus, int port, int regnum)
{}

static int
mt753x_phy_read_c45(struct mii_bus *bus, int port, int devad, int regnum)
{}

static int
mt753x_phy_write_c22(struct mii_bus *bus, int port, int regnum, u16 val)
{}

static int
mt753x_phy_write_c45(struct mii_bus *bus, int port, int devad, int regnum,
		     u16 val)
{}

static void
mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
		   uint8_t *data)
{}

static void
mt7530_get_ethtool_stats(struct dsa_switch *ds, int port,
			 uint64_t *data)
{}

static int
mt7530_get_sset_count(struct dsa_switch *ds, int port, int sset)
{}

static int
mt7530_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
{}

static const char *mt7530_p5_mode_str(unsigned int mode)
{}

static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
{}

/* 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.
 */
static void
mt753x_trap_frames(struct mt7530_priv *priv)
{}

static void
mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
{}

static int
mt7530_port_enable(struct dsa_switch *ds, int port,
		   struct phy_device *phy)
{}

static void
mt7530_port_disable(struct dsa_switch *ds, int port)
{}

static int
mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{}

static int
mt7530_port_max_mtu(struct dsa_switch *ds, int port)
{}

static void
mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state)
{}

static void mt7530_update_port_member(struct mt7530_priv *priv, int port,
				      const struct net_device *bridge_dev,
				      bool join) __must_hold(&priv->reg_mutex)
{}

static int
mt7530_port_pre_bridge_flags(struct dsa_switch *ds, int port,
			     struct switchdev_brport_flags flags,
			     struct netlink_ext_ack *extack)
{}

static int
mt7530_port_bridge_flags(struct dsa_switch *ds, int port,
			 struct switchdev_brport_flags flags,
			 struct netlink_ext_ack *extack)
{}

static int
mt7530_port_bridge_join(struct dsa_switch *ds, int port,
			struct dsa_bridge bridge, bool *tx_fwd_offload,
			struct netlink_ext_ack *extack)
{}

static void
mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
{}

static void
mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port)
{}

static void
mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
			 struct dsa_bridge bridge)
{}

static int
mt7530_port_fdb_add(struct dsa_switch *ds, int port,
		    const unsigned char *addr, u16 vid,
		    struct dsa_db db)
{}

static int
mt7530_port_fdb_del(struct dsa_switch *ds, int port,
		    const unsigned char *addr, u16 vid,
		    struct dsa_db db)
{}

static int
mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
		     dsa_fdb_dump_cb_t *cb, void *data)
{}

static int
mt7530_port_mdb_add(struct dsa_switch *ds, int port,
		    const struct switchdev_obj_port_mdb *mdb,
		    struct dsa_db db)
{}

static int
mt7530_port_mdb_del(struct dsa_switch *ds, int port,
		    const struct switchdev_obj_port_mdb *mdb,
		    struct dsa_db db)
{}

static int
mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
{}

static int
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
			   struct netlink_ext_ack *extack)
{}

static void
mt7530_hw_vlan_add(struct mt7530_priv *priv,
		   struct mt7530_hw_vlan_entry *entry)
{}

static void
mt7530_hw_vlan_del(struct mt7530_priv *priv,
		   struct mt7530_hw_vlan_entry *entry)
{}

static void
mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
		      struct mt7530_hw_vlan_entry *entry,
		      mt7530_vlan_op vlan_op)
{}

static int
mt7530_setup_vlan0(struct mt7530_priv *priv)
{}

static int
mt7530_port_vlan_add(struct dsa_switch *ds, int port,
		     const struct switchdev_obj_port_vlan *vlan,
		     struct netlink_ext_ack *extack)
{}

static int
mt7530_port_vlan_del(struct dsa_switch *ds, int port,
		     const struct switchdev_obj_port_vlan *vlan)
{}

static int mt753x_port_mirror_add(struct dsa_switch *ds, int port,
				  struct dsa_mall_mirror_tc_entry *mirror,
				  bool ingress, struct netlink_ext_ack *extack)
{}

static void mt753x_port_mirror_del(struct dsa_switch *ds, int port,
				   struct dsa_mall_mirror_tc_entry *mirror)
{}

static enum dsa_tag_protocol
mtk_get_tag_protocol(struct dsa_switch *ds, int port,
		     enum dsa_tag_protocol mp)
{}

#ifdef CONFIG_GPIOLIB
static inline u32
mt7530_gpio_to_bit(unsigned int offset)
{}

static int
mt7530_gpio_get(struct gpio_chip *gc, unsigned int offset)
{}

static void
mt7530_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{}

static int
mt7530_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{}

static int
mt7530_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
{}

static int
mt7530_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, int value)
{}

static int
mt7530_setup_gpio(struct mt7530_priv *priv)
{}
#endif /* CONFIG_GPIOLIB */

static irqreturn_t
mt7530_irq_thread_fn(int irq, void *dev_id)
{}

static void
mt7530_irq_mask(struct irq_data *d)
{}

static void
mt7530_irq_unmask(struct irq_data *d)
{}

static void
mt7530_irq_bus_lock(struct irq_data *d)
{}

static void
mt7530_irq_bus_sync_unlock(struct irq_data *d)
{}

static struct irq_chip mt7530_irq_chip =;

static int
mt7530_irq_map(struct irq_domain *domain, unsigned int irq,
	       irq_hw_number_t hwirq)
{}

static const struct irq_domain_ops mt7530_irq_domain_ops =;

static void
mt7988_irq_mask(struct irq_data *d)
{}

static void
mt7988_irq_unmask(struct irq_data *d)
{}

static struct irq_chip mt7988_irq_chip =;

static int
mt7988_irq_map(struct irq_domain *domain, unsigned int irq,
	       irq_hw_number_t hwirq)
{}

static const struct irq_domain_ops mt7988_irq_domain_ops =;

static void
mt7530_setup_mdio_irq(struct mt7530_priv *priv)
{}

static int
mt7530_setup_irq(struct mt7530_priv *priv)
{}

static void
mt7530_free_mdio_irq(struct mt7530_priv *priv)
{}

static void
mt7530_free_irq_common(struct mt7530_priv *priv)
{}

static void
mt7530_free_irq(struct mt7530_priv *priv)
{}

static int
mt7530_setup_mdio(struct mt7530_priv *priv)
{}

static int
mt7530_setup(struct dsa_switch *ds)
{}

static int
mt7531_setup_common(struct dsa_switch *ds)
{}

static int
mt7531_setup(struct dsa_switch *ds)
{}

static void mt7530_mac_port_get_caps(struct dsa_switch *ds, int port,
				     struct phylink_config *config)
{}

static void mt7531_mac_port_get_caps(struct dsa_switch *ds, int port,
				     struct phylink_config *config)
{}

static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port,
				     struct phylink_config *config)
{}

static void en7581_mac_port_get_caps(struct dsa_switch *ds, int port,
				     struct phylink_config *config)
{}

static void
mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
		  phy_interface_t interface)
{}

static void mt7531_rgmii_setup(struct mt7530_priv *priv,
			       phy_interface_t interface,
			       struct phy_device *phydev)
{}

static void
mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
		  phy_interface_t interface)
{}

static struct phylink_pcs *
mt753x_phylink_mac_select_pcs(struct phylink_config *config,
			      phy_interface_t interface)
{}

static void
mt753x_phylink_mac_config(struct phylink_config *config, unsigned int mode,
			  const struct phylink_link_state *state)
{}

static void mt753x_phylink_mac_link_down(struct phylink_config *config,
					 unsigned int mode,
					 phy_interface_t interface)
{}

static void mt753x_phylink_mac_link_up(struct phylink_config *config,
				       struct phy_device *phydev,
				       unsigned int mode,
				       phy_interface_t interface,
				       int speed, int duplex,
				       bool tx_pause, bool rx_pause)
{}

static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
				    struct phylink_config *config)
{}

static int mt753x_pcs_validate(struct phylink_pcs *pcs,
			       unsigned long *supported,
			       const struct phylink_link_state *state)
{}

static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
				 struct phylink_link_state *state)
{}

static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
			     phy_interface_t interface,
			     const unsigned long *advertising,
			     bool permit_pause_to_mac)
{}

static void mt7530_pcs_an_restart(struct phylink_pcs *pcs)
{}

static const struct phylink_pcs_ops mt7530_pcs_ops =;

static int
mt753x_setup(struct dsa_switch *ds)
{}

static int mt753x_get_mac_eee(struct dsa_switch *ds, int port,
			      struct ethtool_keee *e)
{}

static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
			      struct ethtool_keee *e)
{}

static void
mt753x_conduit_state_change(struct dsa_switch *ds,
			    const struct net_device *conduit,
			    bool operational)
{}

static int mt7988_setup(struct dsa_switch *ds)
{}

const struct dsa_switch_ops mt7530_switch_ops =;
EXPORT_SYMBOL_GPL();

static const struct phylink_mac_ops mt753x_phylink_mac_ops =;

const struct mt753x_info mt753x_table[] =;
EXPORT_SYMBOL_GPL();

int
mt7530_probe_common(struct mt7530_priv *priv)
{}
EXPORT_SYMBOL_GPL();

void
mt7530_remove_common(struct mt7530_priv *priv)
{}
EXPORT_SYMBOL_GPL();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();