linux/drivers/net/dsa/realtek/rtl8366rb.c

// SPDX-License-Identifier: GPL-2.0
/* Realtek SMI subdriver for the Realtek RTL8366RB ethernet switch
 *
 * This is a sparsely documented chip, the only viable documentation seems
 * to be a patched up code drop from the vendor that appear in various
 * GPL source trees.
 *
 * Copyright (C) 2017 Linus Walleij <[email protected]>
 * Copyright (C) 2009-2010 Gabor Juhos <[email protected]>
 * Copyright (C) 2010 Antti Seppälä <[email protected]>
 * Copyright (C) 2010 Roman Yeryomin <[email protected]>
 * Copyright (C) 2011 Colin Leitner <[email protected]>
 */

#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>

#include "realtek.h"
#include "realtek-smi.h"
#include "realtek-mdio.h"
#include "rtl83xx.h"

#define RTL8366RB_PORT_NUM_CPU
#define RTL8366RB_NUM_PORTS
#define RTL8366RB_PHY_NO_MAX
#define RTL8366RB_PHY_ADDR_MAX

/* Switch Global Configuration register */
#define RTL8366RB_SGCR
#define RTL8366RB_SGCR_EN_BC_STORM_CTRL
#define RTL8366RB_SGCR_MAX_LENGTH(a)
#define RTL8366RB_SGCR_MAX_LENGTH_MASK
#define RTL8366RB_SGCR_MAX_LENGTH_1522
#define RTL8366RB_SGCR_MAX_LENGTH_1536
#define RTL8366RB_SGCR_MAX_LENGTH_1552
#define RTL8366RB_SGCR_MAX_LENGTH_16000
#define RTL8366RB_SGCR_EN_VLAN
#define RTL8366RB_SGCR_EN_VLAN_4KTB

/* Port Enable Control register */
#define RTL8366RB_PECR

/* Switch per-port learning disablement register */
#define RTL8366RB_PORT_LEARNDIS_CTRL

/* Security control, actually aging register */
#define RTL8366RB_SECURITY_CTRL

#define RTL8366RB_SSCR2
#define RTL8366RB_SSCR2_DROP_UNKNOWN_DA

/* Port Mode Control registers */
#define RTL8366RB_PMC0
#define RTL8366RB_PMC0_SPI
#define RTL8366RB_PMC0_EN_AUTOLOAD
#define RTL8366RB_PMC0_PROBE
#define RTL8366RB_PMC0_DIS_BISR
#define RTL8366RB_PMC0_ADCTEST
#define RTL8366RB_PMC0_SRAM_DIAG
#define RTL8366RB_PMC0_EN_SCAN
#define RTL8366RB_PMC0_P4_IOMODE_SHIFT
#define RTL8366RB_PMC0_P4_IOMODE_MASK
#define RTL8366RB_PMC0_P5_IOMODE_SHIFT
#define RTL8366RB_PMC0_P5_IOMODE_MASK
#define RTL8366RB_PMC0_SDSMODE_SHIFT
#define RTL8366RB_PMC0_SDSMODE_MASK
#define RTL8366RB_PMC1

/* Port Mirror Control Register */
#define RTL8366RB_PMCR
#define RTL8366RB_PMCR_SOURCE_PORT(a)
#define RTL8366RB_PMCR_SOURCE_PORT_MASK
#define RTL8366RB_PMCR_MONITOR_PORT(a)
#define RTL8366RB_PMCR_MONITOR_PORT_MASK
#define RTL8366RB_PMCR_MIRROR_RX
#define RTL8366RB_PMCR_MIRROR_TX
#define RTL8366RB_PMCR_MIRROR_SPC
#define RTL8366RB_PMCR_MIRROR_ISO

/* bits 0..7 = port 0, bits 8..15 = port 1 */
#define RTL8366RB_PAACR0
/* bits 0..7 = port 2, bits 8..15 = port 3 */
#define RTL8366RB_PAACR1
/* bits 0..7 = port 4, bits 8..15 = port 5 */
#define RTL8366RB_PAACR2
#define RTL8366RB_PAACR_SPEED_10M
#define RTL8366RB_PAACR_SPEED_100M
#define RTL8366RB_PAACR_SPEED_1000M
#define RTL8366RB_PAACR_FULL_DUPLEX
#define RTL8366RB_PAACR_LINK_UP
#define RTL8366RB_PAACR_TX_PAUSE
#define RTL8366RB_PAACR_RX_PAUSE
#define RTL8366RB_PAACR_AN

/* bits 0..7 = port 0, bits 8..15 = port 1 */
#define RTL8366RB_PSTAT0
/* bits 0..7 = port 2, bits 8..15 = port 3 */
#define RTL8366RB_PSTAT1
/* bits 0..7 = port 4, bits 8..15 = port 5 */
#define RTL8366RB_PSTAT2

#define RTL8366RB_POWER_SAVING_REG

/* Spanning tree status (STP) control, two bits per port per FID */
#define RTL8366RB_STP_STATE_BASE
#define RTL8366RB_STP_STATE_DISABLED
#define RTL8366RB_STP_STATE_BLOCKING
#define RTL8366RB_STP_STATE_LEARNING
#define RTL8366RB_STP_STATE_FORWARDING
#define RTL8366RB_STP_MASK
#define RTL8366RB_STP_STATE(port, state)
#define RTL8366RB_STP_STATE_MASK(port)

/* CPU port control reg */
#define RTL8366RB_CPU_CTRL_REG
#define RTL8366RB_CPU_PORTS_MSK
/* Disables inserting custom tag length/type 0x8899 */
#define RTL8366RB_CPU_NO_TAG
#define RTL8366RB_CPU_TAG_SIZE

#define RTL8366RB_SMAR0
#define RTL8366RB_SMAR1
#define RTL8366RB_SMAR2

#define RTL8366RB_RESET_CTRL_REG
#define RTL8366RB_CHIP_CTRL_RESET_HW
#define RTL8366RB_CHIP_CTRL_RESET_SW

#define RTL8366RB_CHIP_ID_REG
#define RTL8366RB_CHIP_ID_8366
#define RTL8366RB_CHIP_VERSION_CTRL_REG
#define RTL8366RB_CHIP_VERSION_MASK

/* PHY registers control */
#define RTL8366RB_PHY_ACCESS_CTRL_REG
#define RTL8366RB_PHY_CTRL_READ
#define RTL8366RB_PHY_CTRL_WRITE
#define RTL8366RB_PHY_ACCESS_BUSY_REG
#define RTL8366RB_PHY_INT_BUSY
#define RTL8366RB_PHY_EXT_BUSY
#define RTL8366RB_PHY_ACCESS_DATA_REG
#define RTL8366RB_PHY_EXT_CTRL_REG
#define RTL8366RB_PHY_EXT_WRDATA_REG
#define RTL8366RB_PHY_EXT_RDDATA_REG

#define RTL8366RB_PHY_REG_MASK
#define RTL8366RB_PHY_PAGE_OFFSET
#define RTL8366RB_PHY_PAGE_MASK
#define RTL8366RB_PHY_NO_OFFSET
#define RTL8366RB_PHY_NO_MASK

/* VLAN Ingress Control Register 1, one bit per port.
 * bit 0 .. 5 will make the switch drop ingress frames without
 * VID such as untagged or priority-tagged frames for respective
 * port.
 * bit 6 .. 11 will make the switch drop ingress frames carrying
 * a C-tag with VID != 0 for respective port.
 */
#define RTL8366RB_VLAN_INGRESS_CTRL1_REG
#define RTL8366RB_VLAN_INGRESS_CTRL1_DROP(port)

/* VLAN Ingress Control Register 2, one bit per port.
 * bit0 .. bit5 will make the switch drop all ingress frames with
 * a VLAN classification that does not include the port is in its
 * member set.
 */
#define RTL8366RB_VLAN_INGRESS_CTRL2_REG

/* LED control registers */
/* The LED blink rate is global; it is used by all triggers in all groups. */
#define RTL8366RB_LED_BLINKRATE_REG
#define RTL8366RB_LED_BLINKRATE_MASK
#define RTL8366RB_LED_BLINKRATE_28MS
#define RTL8366RB_LED_BLINKRATE_56MS
#define RTL8366RB_LED_BLINKRATE_84MS
#define RTL8366RB_LED_BLINKRATE_111MS
#define RTL8366RB_LED_BLINKRATE_222MS
#define RTL8366RB_LED_BLINKRATE_446MS

/* LED trigger event for each group */
#define RTL8366RB_LED_CTRL_REG
#define RTL8366RB_LED_CTRL_OFFSET(led_group)
#define RTL8366RB_LED_CTRL_MASK(led_group)

/* The RTL8366RB_LED_X_X registers are used to manually set the LED state only
 * when the corresponding LED group in RTL8366RB_LED_CTRL_REG is
 * RTL8366RB_LEDGROUP_FORCE. Otherwise, it is ignored.
 */
#define RTL8366RB_LED_0_1_CTRL_REG
#define RTL8366RB_LED_2_3_CTRL_REG
#define RTL8366RB_LED_X_X_CTRL_REG(led_group)
#define RTL8366RB_LED_0_X_CTRL_MASK
#define RTL8366RB_LED_X_1_CTRL_MASK
#define RTL8366RB_LED_2_X_CTRL_MASK
#define RTL8366RB_LED_X_3_CTRL_MASK

#define RTL8366RB_MIB_COUNT
#define RTL8366RB_GLOBAL_MIB_COUNT
#define RTL8366RB_MIB_COUNTER_PORT_OFFSET
#define RTL8366RB_MIB_COUNTER_BASE
#define RTL8366RB_MIB_CTRL_REG
#define RTL8366RB_MIB_CTRL_USER_MASK
#define RTL8366RB_MIB_CTRL_BUSY_MASK
#define RTL8366RB_MIB_CTRL_RESET_MASK
#define RTL8366RB_MIB_CTRL_PORT_RESET(_p)
#define RTL8366RB_MIB_CTRL_GLOBAL_RESET

#define RTL8366RB_PORT_VLAN_CTRL_BASE
#define RTL8366RB_PORT_VLAN_CTRL_REG(_p)
#define RTL8366RB_PORT_VLAN_CTRL_MASK
#define RTL8366RB_PORT_VLAN_CTRL_SHIFT(_p)

#define RTL8366RB_VLAN_TABLE_READ_BASE
#define RTL8366RB_VLAN_TABLE_WRITE_BASE

#define RTL8366RB_TABLE_ACCESS_CTRL_REG
#define RTL8366RB_TABLE_VLAN_READ_CTRL
#define RTL8366RB_TABLE_VLAN_WRITE_CTRL

#define RTL8366RB_VLAN_MC_BASE(_x)

#define RTL8366RB_PORT_LINK_STATUS_BASE
#define RTL8366RB_PORT_STATUS_SPEED_MASK
#define RTL8366RB_PORT_STATUS_DUPLEX_MASK
#define RTL8366RB_PORT_STATUS_LINK_MASK
#define RTL8366RB_PORT_STATUS_TXPAUSE_MASK
#define RTL8366RB_PORT_STATUS_RXPAUSE_MASK
#define RTL8366RB_PORT_STATUS_AN_MASK

#define RTL8366RB_NUM_VLANS
#define RTL8366RB_NUM_LEDGROUPS
#define RTL8366RB_NUM_VIDS
#define RTL8366RB_PRIORITYMAX
#define RTL8366RB_NUM_FIDS
#define RTL8366RB_FIDMAX

#define RTL8366RB_PORT_1
#define RTL8366RB_PORT_2
#define RTL8366RB_PORT_3
#define RTL8366RB_PORT_4
#define RTL8366RB_PORT_5

#define RTL8366RB_PORT_CPU

#define RTL8366RB_PORT_ALL

#define RTL8366RB_PORT_ALL_BUT_CPU

#define RTL8366RB_PORT_ALL_EXTERNAL

#define RTL8366RB_PORT_ALL_INTERNAL

/* First configuration word per member config, VID and prio */
#define RTL8366RB_VLAN_VID_MASK
#define RTL8366RB_VLAN_PRIORITY_SHIFT
#define RTL8366RB_VLAN_PRIORITY_MASK
/* Second configuration word per member config, member and untagged */
#define RTL8366RB_VLAN_UNTAG_SHIFT
#define RTL8366RB_VLAN_UNTAG_MASK
#define RTL8366RB_VLAN_MEMBER_MASK
/* Third config word per member config, STAG currently unused */
#define RTL8366RB_VLAN_STAG_MBR_MASK
#define RTL8366RB_VLAN_STAG_MBR_SHIFT
#define RTL8366RB_VLAN_STAG_IDX_MASK
#define RTL8366RB_VLAN_STAG_IDX_SHIFT
#define RTL8366RB_VLAN_FID_MASK

/* Port ingress bandwidth control */
#define RTL8366RB_IB_BASE
#define RTL8366RB_IB_REG(pnum)
#define RTL8366RB_IB_BDTH_MASK
#define RTL8366RB_IB_PREIFG

/* Port egress bandwidth control */
#define RTL8366RB_EB_BASE
#define RTL8366RB_EB_REG(pnum)
#define RTL8366RB_EB_BDTH_MASK
#define RTL8366RB_EB_PREIFG_REG
#define RTL8366RB_EB_PREIFG

#define RTL8366RB_BDTH_SW_MAX
#define RTL8366RB_BDTH_UNIT
#define RTL8366RB_BDTH_REG_DEFAULT

/* QOS */
#define RTL8366RB_QOS
/* Include/Exclude Preamble and IFG (20 bytes). 0:Exclude, 1:Include. */
#define RTL8366RB_QOS_DEFAULT_PREIFG

/* Interrupt handling */
#define RTL8366RB_INTERRUPT_CONTROL_REG
#define RTL8366RB_INTERRUPT_POLARITY
#define RTL8366RB_P4_RGMII_LED
#define RTL8366RB_INTERRUPT_MASK_REG
#define RTL8366RB_INTERRUPT_LINK_CHGALL
#define RTL8366RB_INTERRUPT_ACLEXCEED
#define RTL8366RB_INTERRUPT_STORMEXCEED
#define RTL8366RB_INTERRUPT_P4_FIBER
#define RTL8366RB_INTERRUPT_P4_UTP
#define RTL8366RB_INTERRUPT_VALID
#define RTL8366RB_INTERRUPT_STATUS_REG
#define RTL8366RB_NUM_INTERRUPT

/* Port isolation registers */
#define RTL8366RB_PORT_ISO_BASE
#define RTL8366RB_PORT_ISO(pnum)
#define RTL8366RB_PORT_ISO_EN
#define RTL8366RB_PORT_ISO_PORTS_MASK
#define RTL8366RB_PORT_ISO_PORTS(pmask)

/* bits 0..5 enable force when cleared */
#define RTL8366RB_MAC_FORCE_CTRL_REG

#define RTL8366RB_OAM_PARSER_REG
#define RTL8366RB_OAM_MULTIPLEXER_REG

#define RTL8366RB_GREEN_FEATURE_REG
#define RTL8366RB_GREEN_FEATURE_MSK
#define RTL8366RB_GREEN_FEATURE_TX
#define RTL8366RB_GREEN_FEATURE_RX

enum rtl8366_ledgroup_mode {};

struct rtl8366rb_led {};

/**
 * struct rtl8366rb - RTL8366RB-specific data
 * @max_mtu: per-port max MTU setting
 * @pvid_enabled: if PVID is set for respective port
 * @leds: per-port and per-ledgroup led info
 */
struct rtl8366rb {};

static struct rtl8366_mib_counter rtl8366rb_mib_counters[] =;

static int rtl8366rb_get_mib_counter(struct realtek_priv *priv,
				     int port,
				     struct rtl8366_mib_counter *mib,
				     u64 *mibvalue)
{}

static u32 rtl8366rb_get_irqmask(struct irq_data *d)
{}

static void rtl8366rb_mask_irq(struct irq_data *d)
{}

static void rtl8366rb_unmask_irq(struct irq_data *d)
{}

static irqreturn_t rtl8366rb_irq(int irq, void *data)
{}

static struct irq_chip rtl8366rb_irq_chip =;

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

static void rtl8366rb_irq_unmap(struct irq_domain *d, unsigned int irq)
{}

static const struct irq_domain_ops rtl8366rb_irqdomain_ops =;

static int rtl8366rb_setup_cascaded_irq(struct realtek_priv *priv)
{}

static int rtl8366rb_set_addr(struct realtek_priv *priv)
{}

/* Found in a vendor driver */

/* Struct for handling the jam tables' entries */
struct rtl8366rb_jam_tbl_entry {};

/* For the "version 0" early silicon, appear in most source releases */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_init_jam_ver_0[] =;

/* This v1 init sequence is from Belkin F5D8235 U-Boot release */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_init_jam_ver_1[] =;

/* This v2 init sequence is from Belkin F5D8235 U-Boot release */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_init_jam_ver_2[] =;

/* Appears in a DDWRT code dump */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_init_jam_ver_3[] =;

/* Belkin F5D8235 v1, "belkin,f5d8235-v1" */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_init_jam_f5d8235[] =;

/* DGN3500, "netgear,dgn3500", "netgear,dgn3500b" */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_init_jam_dgn3500[] =;

/* This jam table activates "green ethernet", which means low power mode
 * and is claimed to detect the cable length and not use more power than
 * necessary, and the ports should enter power saving mode 10 seconds after
 * a cable is disconnected. Seems to always be the same.
 */
static const struct rtl8366rb_jam_tbl_entry rtl8366rb_green_jam[] =;

/* Function that jams the tables in the proper registers */
static int rtl8366rb_jam_table(const struct rtl8366rb_jam_tbl_entry *jam_table,
			       int jam_size, struct realtek_priv *priv,
			       bool write_dbg)
{}

static int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
				      u8 led_group,
				      enum rtl8366_ledgroup_mode mode)
{}

static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
{}

static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
{}

static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
{}

static int
rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
				       enum led_brightness brightness)
{}

static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
			       struct fwnode_handle *led_fwnode)
{}

static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv)
{}

static int rtl8366rb_setup_leds(struct realtek_priv *priv)
{}

static int rtl8366rb_setup(struct dsa_switch *ds)
{}

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

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

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

static void
rtl8366rb_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
rtl8366rb_mac_link_down(struct phylink_config *config, unsigned int mode,
			phy_interface_t interface)
{}

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

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

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

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

/**
 * rtl8366rb_drop_untagged() - make the switch drop untagged and C-tagged frames
 * @priv: SMI state container
 * @port: the port to drop untagged and C-tagged frames on
 * @drop: whether to drop or pass untagged and C-tagged frames
 *
 * Return: zero for success, a negative number on error.
 */
static int rtl8366rb_drop_untagged(struct realtek_priv *priv, int port, bool drop)
{}

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

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

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

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

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

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

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

static int rtl8366rb_get_vlan_4k(struct realtek_priv *priv, u32 vid,
				 struct rtl8366_vlan_4k *vlan4k)
{}

static int rtl8366rb_set_vlan_4k(struct realtek_priv *priv,
				 const struct rtl8366_vlan_4k *vlan4k)
{}

static int rtl8366rb_get_vlan_mc(struct realtek_priv *priv, u32 index,
				 struct rtl8366_vlan_mc *vlanmc)
{}

static int rtl8366rb_set_vlan_mc(struct realtek_priv *priv, u32 index,
				 const struct rtl8366_vlan_mc *vlanmc)
{}

static int rtl8366rb_get_mc_index(struct realtek_priv *priv, int port, int *val)
{}

static int rtl8366rb_set_mc_index(struct realtek_priv *priv, int port, int index)
{}

static bool rtl8366rb_is_vlan_valid(struct realtek_priv *priv, unsigned int vlan)
{}

static int rtl8366rb_enable_vlan(struct realtek_priv *priv, bool enable)
{}

static int rtl8366rb_enable_vlan4k(struct realtek_priv *priv, bool enable)
{}

static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
{}

static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
			       u16 val)
{}

static int rtl8366rb_reset_chip(struct realtek_priv *priv)
{}

static int rtl8366rb_detect(struct realtek_priv *priv)
{}

static const struct phylink_mac_ops rtl8366rb_phylink_mac_ops =;

static const struct dsa_switch_ops rtl8366rb_switch_ops =;

static const struct realtek_ops rtl8366rb_ops =;

const struct realtek_variant rtl8366rb_variant =;

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

static struct platform_driver rtl8366rb_smi_driver =;

static struct mdio_driver rtl8366rb_mdio_driver =;

static int rtl8366rb_init(void)
{}
module_init();

static void __exit rtl8366rb_exit(void)
{}
module_exit(rtl8366rb_exit);

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