linux/drivers/net/dsa/qca/ar9331.c

// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2019 Pengutronix, Oleksij Rempel <[email protected]>
/*
 *                   +----------------------+
 * GMAC1----RGMII----|--MAC0                |
 *      \---MDIO1----|--REGs                |----MDIO3----\
 *                   |                      |             |  +------+
 *                   |                      |             +--|      |
 *                   |                 MAC1-|----RMII--M-----| PHY0 |-o P0
 *                   |                      |          |  |  +------+
 *                   |                      |          |  +--|      |
 *                   |                 MAC2-|----RMII--------| PHY1 |-o P1
 *                   |                      |          |  |  +------+
 *                   |                      |          |  +--|      |
 *                   |                 MAC3-|----RMII--------| PHY2 |-o P2
 *                   |                      |          |  |  +------+
 *                   |                      |          |  +--|      |
 *                   |                 MAC4-|----RMII--------| PHY3 |-o P3
 *                   |                      |          |  |  +------+
 *                   |                      |          |  +--|      |
 *                   |                 MAC5-|--+-RMII--M-----|-PHY4-|-o P4
 *                   |                      |  |       |     +------+
 *                   +----------------------+  |       \--CFG_SW_PHY_SWAP
 * GMAC0---------------RMII--------------------/        \-CFG_SW_PHY_ADDR_SWAP
 *      \---MDIO0--NC
 *
 * GMAC0 and MAC5 are connected together and use same PHY. Depending on
 * configuration it can be PHY4 (default) or PHY0. Only GMAC0 or MAC5 can be
 * used at same time. If GMAC0 is used (default) then MAC5 should be disabled.
 *
 * CFG_SW_PHY_SWAP - swap connections of PHY0 and PHY4. If this bit is not set
 * PHY4 is connected to GMAC0/MAC5 bundle and PHY0 is connected to MAC1. If this
 * bit is set, PHY4 is connected to MAC1 and PHY0 is connected to GMAC0/MAC5
 * bundle.
 *
 * CFG_SW_PHY_ADDR_SWAP - swap addresses of PHY0 and PHY4
 *
 * CFG_SW_PHY_SWAP and CFG_SW_PHY_ADDR_SWAP are part of SoC specific register
 * set and not related to switch internal registers.
 */

#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <net/dsa.h>

#define AR9331_SW_NAME
#define AR9331_SW_PORTS

/* dummy reg to change page */
#define AR9331_SW_REG_PAGE

/* Global Interrupt */
#define AR9331_SW_REG_GINT
#define AR9331_SW_REG_GINT_MASK
#define AR9331_SW_GINT_PHY_INT

#define AR9331_SW_REG_FLOOD_MASK
#define AR9331_SW_FLOOD_MASK_BROAD_TO_CPU

#define AR9331_SW_REG_GLOBAL_CTRL
#define AR9331_SW_GLOBAL_CTRL_MFS_M

#define AR9331_SW_REG_MDIO_CTRL
#define AR9331_SW_MDIO_CTRL_BUSY
#define AR9331_SW_MDIO_CTRL_MASTER_EN
#define AR9331_SW_MDIO_CTRL_CMD_READ
#define AR9331_SW_MDIO_CTRL_PHY_ADDR_M
#define AR9331_SW_MDIO_CTRL_REG_ADDR_M
#define AR9331_SW_MDIO_CTRL_DATA_M

#define AR9331_SW_REG_PORT_STATUS(_port)

/* FLOW_LINK_EN - enable mac flow control config auto-neg with phy.
 * If not set, mac can be config by software.
 */
#define AR9331_SW_PORT_STATUS_FLOW_LINK_EN

/* LINK_EN - If set, MAC is configured from PHY link status.
 * If not set, MAC should be configured by software.
 */
#define AR9331_SW_PORT_STATUS_LINK_EN
#define AR9331_SW_PORT_STATUS_DUPLEX_MODE
#define AR9331_SW_PORT_STATUS_RX_FLOW_EN
#define AR9331_SW_PORT_STATUS_TX_FLOW_EN
#define AR9331_SW_PORT_STATUS_RXMAC
#define AR9331_SW_PORT_STATUS_TXMAC
#define AR9331_SW_PORT_STATUS_SPEED_M
#define AR9331_SW_PORT_STATUS_SPEED_1000
#define AR9331_SW_PORT_STATUS_SPEED_100
#define AR9331_SW_PORT_STATUS_SPEED_10

#define AR9331_SW_PORT_STATUS_MAC_MASK

#define AR9331_SW_PORT_STATUS_LINK_MASK

#define AR9331_SW_REG_PORT_CTRL(_port)
#define AR9331_SW_PORT_CTRL_HEAD_EN
#define AR9331_SW_PORT_CTRL_PORT_STATE
#define AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED
#define AR9331_SW_PORT_CTRL_PORT_STATE_BLOCKING
#define AR9331_SW_PORT_CTRL_PORT_STATE_LISTENING
#define AR9331_SW_PORT_CTRL_PORT_STATE_LEARNING
#define AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD

#define AR9331_SW_REG_PORT_VLAN(_port)
#define AR9331_SW_PORT_VLAN_8021Q_MODE
#define AR9331_SW_8021Q_MODE_SECURE
#define AR9331_SW_8021Q_MODE_CHECK
#define AR9331_SW_8021Q_MODE_FALLBACK
#define AR9331_SW_8021Q_MODE_NONE
#define AR9331_SW_PORT_VLAN_PORT_VID_MEMBER

/* MIB registers */
#define AR9331_MIB_COUNTER(x)

/* Phy bypass mode
 * ------------------------------------------------------------------------
 * Bit:   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |
 *
 * real   | start |   OP  | PhyAddr           |  Reg Addr         |  TA   |
 * atheros| start |   OP  | 2'b00 |PhyAdd[2:0]|  Reg Addr[4:0]    |  TA   |
 *
 *
 * Bit:   |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |
 * real   |  Data                                                         |
 * atheros|  Data                                                         |
 *
 * ------------------------------------------------------------------------
 * Page address mode
 * ------------------------------------------------------------------------
 * Bit:   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |
 * real   | start |   OP  | PhyAddr           |  Reg Addr         |  TA   |
 * atheros| start |   OP  | 2'b11 |                          8'b0 |  TA   |
 *
 * Bit:   |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |
 * real   |  Data                                                         |
 * atheros|                       | Page [9:0]                            |
 */
/* In case of Page Address mode, Bit[18:9] of 32 bit register address should be
 * written to bits[9:0] of mdio data register.
 */
#define AR9331_SW_ADDR_PAGE

/* ------------------------------------------------------------------------
 * Normal register access mode
 * ------------------------------------------------------------------------
 * Bit:   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |
 * real   | start |   OP  | PhyAddr           |  Reg Addr         |  TA   |
 * atheros| start |   OP  | 2'b10 |  low_addr[7:0]                |  TA   |
 *
 * Bit:   |16 |17 |18 |19 |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 |30 |31 |
 * real   |  Data                                                         |
 * atheros|  Data                                                         |
 * ------------------------------------------------------------------------
 */
#define AR9331_SW_LOW_ADDR_PHY
#define AR9331_SW_LOW_ADDR_REG

#define AR9331_SW_MDIO_PHY_MODE_M
#define AR9331_SW_MDIO_PHY_MODE_PAGE
#define AR9331_SW_MDIO_PHY_MODE_REG
#define AR9331_SW_MDIO_PHY_MODE_BYPASS
#define AR9331_SW_MDIO_PHY_ADDR_M

/* Empirical determined values */
#define AR9331_SW_MDIO_POLL_SLEEP_US
#define AR9331_SW_MDIO_POLL_TIMEOUT_US

/* The interval should be small enough to avoid overflow of 32bit MIBs */
/*
 * FIXME: until we can read MIBs from stats64 call directly (i.e. sleep
 * there), we have to poll stats more frequently then it is actually needed.
 * For overflow protection, normally, 100 sec interval should have been OK.
 */
#define STATS_INTERVAL_JIFFIES

struct ar9331_sw_stats_raw {};

struct ar9331_sw_port {};

struct ar9331_sw_priv {};

static struct ar9331_sw_priv *ar9331_sw_port_to_priv(struct ar9331_sw_port *port)
{}

/* Warning: switch reset will reset last AR9331_SW_MDIO_PHY_MODE_PAGE request
 * If some kind of optimization is used, the request should be repeated.
 */
static int ar9331_sw_reset(struct ar9331_sw_priv *priv)
{}

static int ar9331_sw_mbus_write(struct mii_bus *mbus, int port, int regnum,
				u16 data)
{}

static int ar9331_sw_mbus_read(struct mii_bus *mbus, int port, int regnum)
{}

static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)
{}

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

static int ar9331_sw_setup(struct dsa_switch *ds)
{}

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

static enum dsa_tag_protocol ar9331_sw_get_tag_protocol(struct dsa_switch *ds,
							int port,
							enum dsa_tag_protocol m)
{}

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

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

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

static void ar9331_sw_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 ar9331_read_stats(struct ar9331_sw_port *port)
{}

static void ar9331_do_stats_poll(struct work_struct *work)
{}

static void ar9331_get_stats64(struct dsa_switch *ds, int port,
			       struct rtnl_link_stats64 *s)
{}

static void ar9331_get_pause_stats(struct dsa_switch *ds, int port,
				   struct ethtool_pause_stats *pause_stats)
{}

static const struct phylink_mac_ops ar9331_phylink_mac_ops =;

static const struct dsa_switch_ops ar9331_sw_ops =;

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

static void ar9331_sw_mask_irq(struct irq_data *d)
{}

static void ar9331_sw_unmask_irq(struct irq_data *d)
{}

static void ar9331_sw_irq_bus_lock(struct irq_data *d)
{}

static void ar9331_sw_irq_bus_sync_unlock(struct irq_data *d)
{}

static struct irq_chip ar9331_sw_irq_chip =;

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

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

static const struct irq_domain_ops ar9331_sw_irqdomain_ops =;

static int ar9331_sw_irq_init(struct ar9331_sw_priv *priv)
{}

static int __ar9331_mdio_write(struct mii_bus *sbus, u8 mode, u16 reg, u16 val)
{}

static int __ar9331_mdio_read(struct mii_bus *sbus, u16 reg)
{}

static int ar9331_mdio_read(void *ctx, const void *reg_buf, size_t reg_len,
			    void *val_buf, size_t val_len)
{}

static int ar9331_mdio_write(void *ctx, u32 reg, u32 val)
{}

static int ar9331_sw_bus_write(void *context, const void *data, size_t count)
{}

static const struct regmap_range ar9331_valid_regs[] =;

static const struct regmap_range ar9331_nonvolatile_regs[] =;

static const struct regmap_range_cfg ar9331_regmap_range[] =;

static const struct regmap_access_table ar9331_register_set =;

static const struct regmap_access_table ar9331_volatile_set =;

static const struct regmap_config ar9331_mdio_regmap_config =;

static const struct regmap_bus ar9331_sw_bus =;

static int ar9331_sw_probe(struct mdio_device *mdiodev)
{}

static void ar9331_sw_remove(struct mdio_device *mdiodev)
{}

static void ar9331_sw_shutdown(struct mdio_device *mdiodev)
{}

static const struct of_device_id ar9331_sw_of_match[] =;

static struct mdio_driver ar9331_sw_mdio_driver =;

mdio_module_driver(ar9331_sw_mdio_driver);

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