linux/drivers/net/dsa/microchip/ksz8795.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Microchip KSZ8795 switch driver
 *
 * Copyright (C) 2017 Microchip Technology Inc.
 *	Tristram Ha <[email protected]>
 */

#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/gpio.h>
#include <linux/if_vlan.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_data/microchip-ksz.h>
#include <linux/phy.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/micrel_phy.h>
#include <net/dsa.h>
#include <net/switchdev.h>
#include <linux/phylink.h>

#include "ksz_common.h"
#include "ksz8795_reg.h"
#include "ksz8.h"

static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
{}

static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
			 bool set)
{}

static int ksz8_ind_write8(struct ksz_device *dev, u8 table, u16 addr, u8 data)
{}

int ksz8_reset_switch(struct ksz_device *dev)
{}

static int ksz8863_change_mtu(struct ksz_device *dev, int frame_size)
{}

static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)
{}

int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
{}

static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues)
{}

int ksz8_all_queues_split(struct ksz_device *dev, int queues)
{}

void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
{}

static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
			      u64 *dropped, u64 *cnt)
{}

static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
			      u64 *dropped, u64 *cnt)
{}

void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
		    u64 *dropped, u64 *cnt)
{}

void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
{}

void ksz8_port_init_cnt(struct ksz_device *dev, int port)
{}

static int ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
{}

static int ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data)
{}

static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data)
{}

static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
				u8 *fid, u8 *src_port, u16 *entries)
{}

static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
				struct alu_struct *alu, bool *valid)
{}

static int ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr,
				struct alu_struct *alu)
{}

static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid,
			   u8 *member, u8 *valid)
{}

static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8 valid,
			 u16 *vlan)
{}

static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
{}

static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
{}

static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
{}

/**
 * ksz879x_get_loopback - KSZ879x specific function to get loopback
 *                        configuration status for a specific port
 * @dev: Pointer to the device structure
 * @port: Port number to query
 * @val: Pointer to store the result
 *
 * This function reads the SMI registers to determine whether loopback mode
 * is enabled for a specific port.
 *
 * Return: 0 on success, error code on failure.
 */
static int ksz879x_get_loopback(struct ksz_device *dev, u16 port,
				u16 *val)
{}

/**
 * ksz879x_set_loopback - KSZ879x specific function  to set loopback mode for
 *			  a specific port
 * @dev: Pointer to the device structure.
 * @port: Port number to modify.
 * @val: Value indicating whether to enable or disable loopback mode.
 *
 * This function translates loopback bit of the BMCR register into the
 * corresponding hardware register bit value and writes it to the SMI interface.
 *
 * Return: 0 on success, error code on failure.
 */
static int ksz879x_set_loopback(struct ksz_device *dev, u16 port, u16 val)
{}

/**
 * ksz8_r_phy_ctrl - Translates and reads from the SMI interface to a MIIM PHY
 *		     Control register (Reg. 31).
 * @dev: The KSZ device instance.
 * @port: The port number to be read.
 * @val: The value read from the SMI interface.
 *
 * This function reads the SMI interface and translates the hardware register
 * bit values into their corresponding control settings for a MIIM PHY Control
 * register.
 *
 * Return: 0 on success, error code on failure.
 */
static int ksz8_r_phy_ctrl(struct ksz_device *dev, int port, u16 *val)
{}

/**
 * ksz8_r_phy_bmcr - Translates and reads from the SMI interface to a MIIM PHY
 *		     Basic mode control register (Reg. 0).
 * @dev: The KSZ device instance.
 * @port: The port number to be read.
 * @val: The value read from the SMI interface.
 *
 * This function reads the SMI interface and translates the hardware register
 * bit values into their corresponding control settings for a MIIM PHY Basic
 * mode control register.
 *
 * MIIM Bit Mapping Comparison between KSZ8794 and KSZ8873
 * -------------------------------------------------------------------
 * MIIM Bit                    | KSZ8794 Reg/Bit             | KSZ8873 Reg/Bit
 * ----------------------------+-----------------------------+----------------
 * Bit 15 - Soft Reset         | 0xF/4                       | Not supported
 * Bit 14 - Loopback           | 0xD/0 (MAC), 0xF/7 (PHY)    ~ 0xD/0 (PHY)
 * Bit 13 - Force 100          | 0xC/6                       = 0xC/6
 * Bit 12 - AN Enable          | 0xC/7 (reverse logic)       ~ 0xC/7
 * Bit 11 - Power Down         | 0xD/3                       = 0xD/3
 * Bit 10 - PHY Isolate        | 0xF/5                       | Not supported
 * Bit 9 - Restart AN          | 0xD/5                       = 0xD/5
 * Bit 8 - Force Full-Duplex   | 0xC/5                       = 0xC/5
 * Bit 7 - Collision Test/Res. | Not supported               | Not supported
 * Bit 6 - Reserved            | Not supported               | Not supported
 * Bit 5 - Hp_mdix             | 0x9/7                       ~ 0xF/7
 * Bit 4 - Force MDI           | 0xD/1                       = 0xD/1
 * Bit 3 - Disable MDIX        | 0xD/2                       = 0xD/2
 * Bit 2 - Disable Far-End F.  | ????                        | 0xD/4
 * Bit 1 - Disable Transmit    | 0xD/6                       = 0xD/6
 * Bit 0 - Disable LED         | 0xD/7                       = 0xD/7
 * -------------------------------------------------------------------
 *
 * Return: 0 on success, error code on failure.
 */
static int ksz8_r_phy_bmcr(struct ksz_device *dev, u16 port, u16 *val)
{}

int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
{}

/**
 * ksz8_w_phy_ctrl - Translates and writes to the SMI interface from a MIIM PHY
 *		     Control register (Reg. 31).
 * @dev: The KSZ device instance.
 * @port: The port number to be configured.
 * @val: The register value to be written.
 *
 * This function translates control settings from a MIIM PHY Control register
 * into their corresponding hardware register bit values for the SMI
 * interface.
 *
 * Return: 0 on success, error code on failure.
 */
static int ksz8_w_phy_ctrl(struct ksz_device *dev, int port, u16 val)
{}

/**
 * ksz8_w_phy_bmcr - Translates and writes to the SMI interface from a MIIM PHY
 *		     Basic mode control register (Reg. 0).
 * @dev: The KSZ device instance.
 * @port: The port number to be configured.
 * @val: The register value to be written.
 *
 * This function translates control settings from a MIIM PHY Basic mode control
 * register into their corresponding hardware register bit values for the SMI
 * interface.
 *
 * MIIM Bit Mapping Comparison between KSZ8794 and KSZ8873
 * -------------------------------------------------------------------
 * MIIM Bit                    | KSZ8794 Reg/Bit             | KSZ8873 Reg/Bit
 * ----------------------------+-----------------------------+----------------
 * Bit 15 - Soft Reset         | 0xF/4                       | Not supported
 * Bit 14 - Loopback           | 0xD/0 (MAC), 0xF/7 (PHY)    ~ 0xD/0 (PHY)
 * Bit 13 - Force 100          | 0xC/6                       = 0xC/6
 * Bit 12 - AN Enable          | 0xC/7 (reverse logic)       ~ 0xC/7
 * Bit 11 - Power Down         | 0xD/3                       = 0xD/3
 * Bit 10 - PHY Isolate        | 0xF/5                       | Not supported
 * Bit 9 - Restart AN          | 0xD/5                       = 0xD/5
 * Bit 8 - Force Full-Duplex   | 0xC/5                       = 0xC/5
 * Bit 7 - Collision Test/Res. | Not supported               | Not supported
 * Bit 6 - Reserved            | Not supported               | Not supported
 * Bit 5 - Hp_mdix             | 0x9/7                       ~ 0xF/7
 * Bit 4 - Force MDI           | 0xD/1                       = 0xD/1
 * Bit 3 - Disable MDIX        | 0xD/2                       = 0xD/2
 * Bit 2 - Disable Far-End F.  | ????                        | 0xD/4
 * Bit 1 - Disable Transmit    | 0xD/6                       = 0xD/6
 * Bit 0 - Disable LED         | 0xD/7                       = 0xD/7
 * -------------------------------------------------------------------
 *
 * Return: 0 on success, error code on failure.
 */
static int ksz8_w_phy_bmcr(struct ksz_device *dev, u16 port, u16 val)
{}

int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
{}

void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
{}

void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
{}

int ksz8_fdb_dump(struct ksz_device *dev, int port,
		  dsa_fdb_dump_cb_t *cb, void *data)
{}

static int ksz8_add_sta_mac(struct ksz_device *dev, int port,
			    const unsigned char *addr, u16 vid)
{}

static int ksz8_del_sta_mac(struct ksz_device *dev, int port,
			    const unsigned char *addr, u16 vid)
{}

int ksz8_mdb_add(struct ksz_device *dev, int port,
		 const struct switchdev_obj_port_mdb *mdb, struct dsa_db db)
{}

int ksz8_mdb_del(struct ksz_device *dev, int port,
		 const struct switchdev_obj_port_mdb *mdb, struct dsa_db db)
{}

int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr,
		 u16 vid, struct dsa_db db)
{}

int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr,
		 u16 vid, struct dsa_db db)
{}

int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag,
			     struct netlink_ext_ack *extack)
{}

static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
{}

int ksz8_port_vlan_add(struct ksz_device *dev, int port,
		       const struct switchdev_obj_port_vlan *vlan,
		       struct netlink_ext_ack *extack)
{}

int ksz8_port_vlan_del(struct ksz_device *dev, int port,
		       const struct switchdev_obj_port_vlan *vlan)
{}

int ksz8_port_mirror_add(struct ksz_device *dev, int port,
			 struct dsa_mall_mirror_tc_entry *mirror,
			 bool ingress, struct netlink_ext_ack *extack)
{}

void ksz8_port_mirror_del(struct ksz_device *dev, int port,
			  struct dsa_mall_mirror_tc_entry *mirror)
{}

static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port)
{}

void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port)
{}

static void ksz88x3_config_rmii_clk(struct ksz_device *dev)
{}

void ksz8_config_cpu_port(struct dsa_switch *ds)
{}

/**
 * ksz8_phy_port_link_up - Configures ports with integrated PHYs
 * @dev: The KSZ device instance.
 * @port: The port number to configure.
 * @duplex: The desired duplex mode.
 * @tx_pause: If true, enables transmit pause.
 * @rx_pause: If true, enables receive pause.
 *
 * Description:
 * The function configures flow control settings for a given port based on the
 * desired settings and current duplex mode.
 *
 * According to the KSZ8873 datasheet, the PORT_FORCE_FLOW_CTRL bit in the
 * Port Control 2 register (0x1A for Port 1, 0x22 for Port 2, 0x32 for Port 3)
 * determines how flow control is handled on the port:
 *    "1 = will always enable full-duplex flow control on the port, regardless
 *         of AN result.
 *     0 = full-duplex flow control is enabled based on AN result."
 *
 * This means that the flow control behavior depends on the state of this bit:
 * - If PORT_FORCE_FLOW_CTRL is set to 1, the switch will ignore AN results and
 *   force flow control on the port.
 * - If PORT_FORCE_FLOW_CTRL is set to 0, the switch will enable or disable
 *   flow control based on the AN results.
 *
 * However, there is a potential limitation in this configuration. It is
 * currently not possible to force disable flow control on a port if we still
 * advertise pause support. While such a configuration is not currently
 * supported by Linux, and may not make practical sense, it's important to be
 * aware of this limitation when working with the KSZ8873 and similar devices.
 */
static void ksz8_phy_port_link_up(struct ksz_device *dev, int port, int duplex,
				  bool tx_pause, bool rx_pause)
{}

/**
 * ksz8_cpu_port_link_up - Configures the CPU port of the switch.
 * @dev: The KSZ device instance.
 * @speed: The desired link speed.
 * @duplex: The desired duplex mode.
 * @tx_pause: If true, enables transmit pause.
 * @rx_pause: If true, enables receive pause.
 *
 * Description:
 * The function configures flow control and speed settings for the CPU
 * port of the switch based on the desired settings, current duplex mode, and
 * speed.
 */
static void ksz8_cpu_port_link_up(struct ksz_device *dev, int speed, int duplex,
				  bool tx_pause, bool rx_pause)
{}

void ksz8_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 int ksz8_handle_global_errata(struct dsa_switch *ds)
{}

int ksz8_enable_stp_addr(struct ksz_device *dev)
{}

int ksz8_setup(struct dsa_switch *ds)
{}

void ksz8_get_caps(struct ksz_device *dev, int port,
		   struct phylink_config *config)
{}

u32 ksz8_get_port_addr(int port, int offset)
{}

int ksz8_switch_init(struct ksz_device *dev)
{}

void ksz8_switch_exit(struct ksz_device *dev)
{}

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