linux/drivers/net/dsa/lantiq_gswip.c

// 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 <[email protected]>
 * Copyright (C) 2017 - 2019 Hauke Mehrtens <[email protected]>
 *
 * 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.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <net/dsa.h>
#include <dt-bindings/mips/lantiq_rcu_gphy.h>

#include "lantiq_pce.h"

/* GSWIP MDIO Registers */
#define GSWIP_MDIO_GLOB
#define GSWIP_MDIO_GLOB_ENABLE
#define GSWIP_MDIO_CTRL
#define GSWIP_MDIO_CTRL_BUSY
#define GSWIP_MDIO_CTRL_RD
#define GSWIP_MDIO_CTRL_WR
#define GSWIP_MDIO_CTRL_PHYAD_MASK
#define GSWIP_MDIO_CTRL_PHYAD_SHIFT
#define GSWIP_MDIO_CTRL_REGAD_MASK
#define GSWIP_MDIO_READ
#define GSWIP_MDIO_WRITE
#define GSWIP_MDIO_MDC_CFG0
#define GSWIP_MDIO_MDC_CFG1
#define GSWIP_MDIO_PHYp(p)
#define GSWIP_MDIO_PHY_LINK_MASK
#define GSWIP_MDIO_PHY_LINK_AUTO
#define GSWIP_MDIO_PHY_LINK_DOWN
#define GSWIP_MDIO_PHY_LINK_UP
#define GSWIP_MDIO_PHY_SPEED_MASK
#define GSWIP_MDIO_PHY_SPEED_AUTO
#define GSWIP_MDIO_PHY_SPEED_M10
#define GSWIP_MDIO_PHY_SPEED_M100
#define GSWIP_MDIO_PHY_SPEED_G1
#define GSWIP_MDIO_PHY_FDUP_MASK
#define GSWIP_MDIO_PHY_FDUP_AUTO
#define GSWIP_MDIO_PHY_FDUP_EN
#define GSWIP_MDIO_PHY_FDUP_DIS
#define GSWIP_MDIO_PHY_FCONTX_MASK
#define GSWIP_MDIO_PHY_FCONTX_AUTO
#define GSWIP_MDIO_PHY_FCONTX_EN
#define GSWIP_MDIO_PHY_FCONTX_DIS
#define GSWIP_MDIO_PHY_FCONRX_MASK
#define GSWIP_MDIO_PHY_FCONRX_AUTO
#define GSWIP_MDIO_PHY_FCONRX_EN
#define GSWIP_MDIO_PHY_FCONRX_DIS
#define GSWIP_MDIO_PHY_ADDR_MASK
#define GSWIP_MDIO_PHY_MASK

/* GSWIP MII Registers */
#define GSWIP_MII_CFGp(p)
#define GSWIP_MII_CFG_RESET
#define GSWIP_MII_CFG_EN
#define GSWIP_MII_CFG_ISOLATE
#define GSWIP_MII_CFG_LDCLKDIS
#define GSWIP_MII_CFG_RGMII_IBS
#define GSWIP_MII_CFG_RMII_CLK
#define GSWIP_MII_CFG_MODE_MIIP
#define GSWIP_MII_CFG_MODE_MIIM
#define GSWIP_MII_CFG_MODE_RMIIP
#define GSWIP_MII_CFG_MODE_RMIIM
#define GSWIP_MII_CFG_MODE_RGMII
#define GSWIP_MII_CFG_MODE_GMII
#define GSWIP_MII_CFG_MODE_MASK
#define GSWIP_MII_CFG_RATE_M2P5
#define GSWIP_MII_CFG_RATE_M25
#define GSWIP_MII_CFG_RATE_M125
#define GSWIP_MII_CFG_RATE_M50
#define GSWIP_MII_CFG_RATE_AUTO
#define GSWIP_MII_CFG_RATE_MASK
#define GSWIP_MII_PCDU0
#define GSWIP_MII_PCDU1
#define GSWIP_MII_PCDU5
#define GSWIP_MII_PCDU_TXDLY_MASK
#define GSWIP_MII_PCDU_RXDLY_MASK

/* GSWIP Core Registers */
#define GSWIP_SWRES
#define GSWIP_SWRES_R1
#define GSWIP_SWRES_R0
#define GSWIP_VERSION
#define GSWIP_VERSION_REV_SHIFT
#define GSWIP_VERSION_REV_MASK
#define GSWIP_VERSION_MOD_SHIFT
#define GSWIP_VERSION_MOD_MASK
#define GSWIP_VERSION_2_0
#define GSWIP_VERSION_2_1
#define GSWIP_VERSION_2_2
#define GSWIP_VERSION_2_2_ETC

#define GSWIP_BM_RAM_VAL(x)
#define GSWIP_BM_RAM_ADDR
#define GSWIP_BM_RAM_CTRL
#define GSWIP_BM_RAM_CTRL_BAS
#define GSWIP_BM_RAM_CTRL_OPMOD
#define GSWIP_BM_RAM_CTRL_ADDR_MASK
#define GSWIP_BM_QUEUE_GCTRL
#define GSWIP_BM_QUEUE_GCTRL_GL_MOD
/* buffer management Port Configuration Register */
#define GSWIP_BM_PCFGp(p)
#define GSWIP_BM_PCFG_CNTEN
#define GSWIP_BM_PCFG_IGCNT
/* buffer management Port Control Register */
#define GSWIP_BM_RMON_CTRLp(p)
#define GSWIP_BM_CTRL_RMON_RAM1_RES
#define GSWIP_BM_CTRL_RMON_RAM2_RES

/* PCE */
#define GSWIP_PCE_TBL_KEY(x)
#define GSWIP_PCE_TBL_MASK
#define GSWIP_PCE_TBL_VAL(x)
#define GSWIP_PCE_TBL_ADDR
#define GSWIP_PCE_TBL_CTRL
#define GSWIP_PCE_TBL_CTRL_BAS
#define GSWIP_PCE_TBL_CTRL_TYPE
#define GSWIP_PCE_TBL_CTRL_VLD
#define GSWIP_PCE_TBL_CTRL_KEYFORM
#define GSWIP_PCE_TBL_CTRL_GMAP_MASK
#define GSWIP_PCE_TBL_CTRL_OPMOD_MASK
#define GSWIP_PCE_TBL_CTRL_OPMOD_ADRD
#define GSWIP_PCE_TBL_CTRL_OPMOD_ADWR
#define GSWIP_PCE_TBL_CTRL_OPMOD_KSRD
#define GSWIP_PCE_TBL_CTRL_OPMOD_KSWR
#define GSWIP_PCE_TBL_CTRL_ADDR_MASK
#define GSWIP_PCE_PMAP1
#define GSWIP_PCE_PMAP2
#define GSWIP_PCE_PMAP3
#define GSWIP_PCE_GCTRL_0
#define GSWIP_PCE_GCTRL_0_MTFL
#define GSWIP_PCE_GCTRL_0_MC_VALID
#define GSWIP_PCE_GCTRL_0_VLAN
#define GSWIP_PCE_GCTRL_1
#define GSWIP_PCE_GCTRL_1_MAC_GLOCK
#define GSWIP_PCE_GCTRL_1_MAC_GLOCK_MOD
#define GSWIP_PCE_PCTRL_0p(p)
#define GSWIP_PCE_PCTRL_0_TVM
#define GSWIP_PCE_PCTRL_0_VREP
#define GSWIP_PCE_PCTRL_0_INGRESS
#define GSWIP_PCE_PCTRL_0_PSTATE_LISTEN
#define GSWIP_PCE_PCTRL_0_PSTATE_RX
#define GSWIP_PCE_PCTRL_0_PSTATE_TX
#define GSWIP_PCE_PCTRL_0_PSTATE_LEARNING
#define GSWIP_PCE_PCTRL_0_PSTATE_FORWARDING
#define GSWIP_PCE_PCTRL_0_PSTATE_MASK
#define GSWIP_PCE_VCTRL(p)
#define GSWIP_PCE_VCTRL_UVR
#define GSWIP_PCE_VCTRL_VIMR
#define GSWIP_PCE_VCTRL_VEMR
#define GSWIP_PCE_VCTRL_VSR
#define GSWIP_PCE_VCTRL_VID0
#define GSWIP_PCE_DEFPVID(p)

#define GSWIP_MAC_FLEN
#define GSWIP_MAC_CTRL_0p(p)
#define GSWIP_MAC_CTRL_0_PADEN
#define GSWIP_MAC_CTRL_0_FCS_EN
#define GSWIP_MAC_CTRL_0_FCON_MASK
#define GSWIP_MAC_CTRL_0_FCON_AUTO
#define GSWIP_MAC_CTRL_0_FCON_RX
#define GSWIP_MAC_CTRL_0_FCON_TX
#define GSWIP_MAC_CTRL_0_FCON_RXTX
#define GSWIP_MAC_CTRL_0_FCON_NONE
#define GSWIP_MAC_CTRL_0_FDUP_MASK
#define GSWIP_MAC_CTRL_0_FDUP_AUTO
#define GSWIP_MAC_CTRL_0_FDUP_EN
#define GSWIP_MAC_CTRL_0_FDUP_DIS
#define GSWIP_MAC_CTRL_0_GMII_MASK
#define GSWIP_MAC_CTRL_0_GMII_AUTO
#define GSWIP_MAC_CTRL_0_GMII_MII
#define GSWIP_MAC_CTRL_0_GMII_RGMII
#define GSWIP_MAC_CTRL_2p(p)
#define GSWIP_MAC_CTRL_2_LCHKL
#define GSWIP_MAC_CTRL_2_MLEN

/* Ethernet Switch Fetch DMA Port Control Register */
#define GSWIP_FDMA_PCTRLp(p)
#define GSWIP_FDMA_PCTRL_EN
#define GSWIP_FDMA_PCTRL_STEN
#define GSWIP_FDMA_PCTRL_VLANMOD_MASK
#define GSWIP_FDMA_PCTRL_VLANMOD_SHIFT
#define GSWIP_FDMA_PCTRL_VLANMOD_DIS
#define GSWIP_FDMA_PCTRL_VLANMOD_PRIO
#define GSWIP_FDMA_PCTRL_VLANMOD_ID
#define GSWIP_FDMA_PCTRL_VLANMOD_BOTH

/* Ethernet Switch Store DMA Port Control Register */
#define GSWIP_SDMA_PCTRLp(p)
#define GSWIP_SDMA_PCTRL_EN
#define GSWIP_SDMA_PCTRL_FCEN
#define GSWIP_SDMA_PCTRL_PAUFWD

#define GSWIP_TABLE_ACTIVE_VLAN
#define GSWIP_TABLE_VLAN_MAPPING
#define GSWIP_TABLE_MAC_BRIDGE
#define GSWIP_TABLE_MAC_BRIDGE_KEY3_FID
#define GSWIP_TABLE_MAC_BRIDGE_VAL0_PORT
#define GSWIP_TABLE_MAC_BRIDGE_VAL1_STATIC

#define XRX200_GPHY_FW_ALIGN

/* 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

struct gswip_hw_info {};

struct xway_gphy_match_data {};

struct gswip_gphy_fw {};

struct gswip_vlan {};

struct gswip_priv {};

struct gswip_pce_table_entry {};

struct gswip_rmon_cnt_desc {};

#define MIB_DESC(_size, _offset, _name)

static const struct gswip_rmon_cnt_desc gswip_rmon_cnt[] =;

static u32 gswip_switch_r(struct gswip_priv *priv, u32 offset)
{}

static void gswip_switch_w(struct gswip_priv *priv, u32 val, u32 offset)
{}

static void gswip_switch_mask(struct gswip_priv *priv, u32 clear, u32 set,
			      u32 offset)
{}

static u32 gswip_switch_r_timeout(struct gswip_priv *priv, u32 offset,
				  u32 cleared)
{}

static u32 gswip_mdio_r(struct gswip_priv *priv, u32 offset)
{}

static void gswip_mdio_w(struct gswip_priv *priv, u32 val, u32 offset)
{}

static void gswip_mdio_mask(struct gswip_priv *priv, u32 clear, u32 set,
			    u32 offset)
{}

static u32 gswip_mii_r(struct gswip_priv *priv, u32 offset)
{}

static void gswip_mii_w(struct gswip_priv *priv, u32 val, u32 offset)
{}

static void gswip_mii_mask(struct gswip_priv *priv, u32 clear, u32 set,
			   u32 offset)
{}

static void gswip_mii_mask_cfg(struct gswip_priv *priv, u32 clear, u32 set,
			       int port)
{}

static void gswip_mii_mask_pcdu(struct gswip_priv *priv, u32 clear, u32 set,
				int port)
{}

static int gswip_mdio_poll(struct gswip_priv *priv)
{}

static int gswip_mdio_wr(struct mii_bus *bus, int addr, int reg, u16 val)
{}

static int gswip_mdio_rd(struct mii_bus *bus, int addr, int reg)
{}

static int gswip_mdio(struct gswip_priv *priv)
{}

static int gswip_pce_table_entry_read(struct gswip_priv *priv,
				      struct gswip_pce_table_entry *tbl)
{}

static int gswip_pce_table_entry_write(struct gswip_priv *priv,
				       struct gswip_pce_table_entry *tbl)
{}

/* 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.
 */
static int gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add)
{}

static int gswip_port_enable(struct dsa_switch *ds, int port,
			     struct phy_device *phydev)
{}

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

static int gswip_pce_load_microcode(struct gswip_priv *priv)
{}

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

static int gswip_setup(struct dsa_switch *ds)
{}

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

static int gswip_vlan_active_create(struct gswip_priv *priv,
				    struct net_device *bridge,
				    int fid, u16 vid)
{}

static int gswip_vlan_active_remove(struct gswip_priv *priv, int idx)
{}

static int gswip_vlan_add_unaware(struct gswip_priv *priv,
				  struct net_device *bridge, int port)
{}

static int gswip_vlan_add_aware(struct gswip_priv *priv,
				struct net_device *bridge, int port,
				u16 vid, bool untagged,
				bool pvid)
{}

static int gswip_vlan_remove(struct gswip_priv *priv,
			     struct net_device *bridge, int port,
			     u16 vid, bool pvid, bool vlan_aware)
{}

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

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

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

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

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

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

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

static int gswip_port_fdb(struct dsa_switch *ds, int port,
			  const unsigned char *addr, u16 vid, bool add)
{}

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

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

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

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

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

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

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

static void gswip_port_set_link(struct gswip_priv *priv, int port, bool link)
{}

static void gswip_port_set_speed(struct gswip_priv *priv, int port, int speed,
				 phy_interface_t interface)
{}

static void gswip_port_set_duplex(struct gswip_priv *priv, int port, int duplex)
{}

static void gswip_port_set_pause(struct gswip_priv *priv, int port,
				 bool tx_pause, bool rx_pause)
{}

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

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

static void gswip_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 gswip_get_strings(struct dsa_switch *ds, int port, u32 stringset,
			      uint8_t *data)
{}

static u32 gswip_bcm_ram_entry_read(struct gswip_priv *priv, u32 table,
				    u32 index)
{}

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

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

static const struct phylink_mac_ops gswip_phylink_mac_ops =;

static const struct dsa_switch_ops gswip_xrx200_switch_ops =;

static const struct dsa_switch_ops gswip_xrx300_switch_ops =;

static const struct xway_gphy_match_data xrx200a1x_gphy_data =;

static const struct xway_gphy_match_data xrx200a2x_gphy_data =;

static const struct xway_gphy_match_data xrx300_gphy_data =;

static const struct of_device_id xway_gphy_match[] __maybe_unused =;

static int gswip_gphy_fw_load(struct gswip_priv *priv, struct gswip_gphy_fw *gphy_fw)
{}

static int gswip_gphy_fw_probe(struct gswip_priv *priv,
			       struct gswip_gphy_fw *gphy_fw,
			       struct device_node *gphy_fw_np, int i)
{}

static void gswip_gphy_fw_remove(struct gswip_priv *priv,
				 struct gswip_gphy_fw *gphy_fw)
{}

static int gswip_gphy_fw_list(struct gswip_priv *priv,
			      struct device_node *gphy_fw_list_np, u32 version)
{}

static int gswip_probe(struct platform_device *pdev)
{}

static void gswip_remove(struct platform_device *pdev)
{}

static void gswip_shutdown(struct platform_device *pdev)
{}

static const struct gswip_hw_info gswip_xrx200 =;

static const struct gswip_hw_info gswip_xrx300 =;

static const struct of_device_id gswip_of_match[] =;
MODULE_DEVICE_TABLE(of, gswip_of_match);

static struct platform_driver gswip_driver =;

module_platform_driver();

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