linux/drivers/net/ethernet/mediatek/mtk_star_emac.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2020 MediaTek Corporation
 * Copyright (c) 2020 BayLibre SAS
 *
 * Author: Bartosz Golaszewski <[email protected]>
 */

#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/compiler.h>
#include <linux/dma-mapping.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/mii.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>

#define MTK_STAR_DRVNAME

#define MTK_STAR_WAIT_TIMEOUT
#define MTK_STAR_MAX_FRAME_SIZE
#define MTK_STAR_SKB_ALIGNMENT
#define MTK_STAR_HASHTABLE_MC_LIMIT
#define MTK_STAR_HASHTABLE_SIZE_MAX
#define MTK_STAR_DESC_NEEDED

/* Normally we'd use NET_IP_ALIGN but on arm64 its value is 0 and it doesn't
 * work for this controller.
 */
#define MTK_STAR_IP_ALIGN

static const char *const mtk_star_clk_names[] =;
#define MTK_STAR_NCLKS

/* PHY Control Register 0 */
#define MTK_STAR_REG_PHY_CTRL0
#define MTK_STAR_BIT_PHY_CTRL0_WTCMD
#define MTK_STAR_BIT_PHY_CTRL0_RDCMD
#define MTK_STAR_BIT_PHY_CTRL0_RWOK
#define MTK_STAR_MSK_PHY_CTRL0_PREG
#define MTK_STAR_OFF_PHY_CTRL0_PREG
#define MTK_STAR_MSK_PHY_CTRL0_RWDATA
#define MTK_STAR_OFF_PHY_CTRL0_RWDATA

/* PHY Control Register 1 */
#define MTK_STAR_REG_PHY_CTRL1
#define MTK_STAR_BIT_PHY_CTRL1_LINK_ST
#define MTK_STAR_BIT_PHY_CTRL1_AN_EN
#define MTK_STAR_OFF_PHY_CTRL1_FORCE_SPD
#define MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_10M
#define MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_100M
#define MTK_STAR_VAL_PHY_CTRL1_FORCE_SPD_1000M
#define MTK_STAR_BIT_PHY_CTRL1_FORCE_DPX
#define MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_RX
#define MTK_STAR_BIT_PHY_CTRL1_FORCE_FC_TX

/* MAC Configuration Register */
#define MTK_STAR_REG_MAC_CFG
#define MTK_STAR_OFF_MAC_CFG_IPG
#define MTK_STAR_VAL_MAC_CFG_IPG_96BIT
#define MTK_STAR_BIT_MAC_CFG_MAXLEN_1522
#define MTK_STAR_BIT_MAC_CFG_AUTO_PAD
#define MTK_STAR_BIT_MAC_CFG_CRC_STRIP
#define MTK_STAR_BIT_MAC_CFG_VLAN_STRIP
#define MTK_STAR_BIT_MAC_CFG_NIC_PD

/* Flow-Control Configuration Register */
#define MTK_STAR_REG_FC_CFG
#define MTK_STAR_BIT_FC_CFG_BP_EN
#define MTK_STAR_BIT_FC_CFG_UC_PAUSE_DIR
#define MTK_STAR_OFF_FC_CFG_SEND_PAUSE_TH
#define MTK_STAR_MSK_FC_CFG_SEND_PAUSE_TH
#define MTK_STAR_VAL_FC_CFG_SEND_PAUSE_TH_2K

/* ARL Configuration Register */
#define MTK_STAR_REG_ARL_CFG
#define MTK_STAR_BIT_ARL_CFG_HASH_ALG
#define MTK_STAR_BIT_ARL_CFG_MISC_MODE

/* MAC High and Low Bytes Registers */
#define MTK_STAR_REG_MY_MAC_H
#define MTK_STAR_REG_MY_MAC_L

/* Hash Table Control Register */
#define MTK_STAR_REG_HASH_CTRL
#define MTK_STAR_MSK_HASH_CTRL_HASH_BIT_ADDR
#define MTK_STAR_BIT_HASH_CTRL_HASH_BIT_DATA
#define MTK_STAR_BIT_HASH_CTRL_ACC_CMD
#define MTK_STAR_BIT_HASH_CTRL_CMD_START
#define MTK_STAR_BIT_HASH_CTRL_BIST_OK
#define MTK_STAR_BIT_HASH_CTRL_BIST_DONE
#define MTK_STAR_BIT_HASH_CTRL_BIST_EN

/* TX DMA Control Register */
#define MTK_STAR_REG_TX_DMA_CTRL
#define MTK_STAR_BIT_TX_DMA_CTRL_START
#define MTK_STAR_BIT_TX_DMA_CTRL_STOP
#define MTK_STAR_BIT_TX_DMA_CTRL_RESUME

/* RX DMA Control Register */
#define MTK_STAR_REG_RX_DMA_CTRL
#define MTK_STAR_BIT_RX_DMA_CTRL_START
#define MTK_STAR_BIT_RX_DMA_CTRL_STOP
#define MTK_STAR_BIT_RX_DMA_CTRL_RESUME

/* DMA Address Registers */
#define MTK_STAR_REG_TX_DPTR
#define MTK_STAR_REG_RX_DPTR
#define MTK_STAR_REG_TX_BASE_ADDR
#define MTK_STAR_REG_RX_BASE_ADDR

/* Interrupt Status Register */
#define MTK_STAR_REG_INT_STS
#define MTK_STAR_REG_INT_STS_PORT_STS_CHG
#define MTK_STAR_REG_INT_STS_MIB_CNT_TH
#define MTK_STAR_BIT_INT_STS_FNRC
#define MTK_STAR_BIT_INT_STS_TNTC

/* Interrupt Mask Register */
#define MTK_STAR_REG_INT_MASK
#define MTK_STAR_BIT_INT_MASK_FNRC

/* Delay-Macro Register */
#define MTK_STAR_REG_TEST0
#define MTK_STAR_BIT_INV_RX_CLK
#define MTK_STAR_BIT_INV_TX_CLK

/* Misc. Config Register */
#define MTK_STAR_REG_TEST1
#define MTK_STAR_BIT_TEST1_RST_HASH_MBIST

/* Extended Configuration Register */
#define MTK_STAR_REG_EXT_CFG
#define MTK_STAR_OFF_EXT_CFG_SND_PAUSE_RLS
#define MTK_STAR_MSK_EXT_CFG_SND_PAUSE_RLS
#define MTK_STAR_VAL_EXT_CFG_SND_PAUSE_RLS_1K

/* EthSys Configuration Register */
#define MTK_STAR_REG_SYS_CONF
#define MTK_STAR_BIT_MII_PAD_OUT_ENABLE
#define MTK_STAR_BIT_EXT_MDC_MODE
#define MTK_STAR_BIT_SWC_MII_MODE

/* MAC Clock Configuration Register */
#define MTK_STAR_REG_MAC_CLK_CONF
#define MTK_STAR_MSK_MAC_CLK_CONF
#define MTK_STAR_BIT_CLK_DIV_10
#define MTK_STAR_BIT_CLK_DIV_50

/* Counter registers. */
#define MTK_STAR_REG_C_RXOKPKT
#define MTK_STAR_REG_C_RXOKBYTE
#define MTK_STAR_REG_C_RXRUNT
#define MTK_STAR_REG_C_RXLONG
#define MTK_STAR_REG_C_RXDROP
#define MTK_STAR_REG_C_RXCRC
#define MTK_STAR_REG_C_RXARLDROP
#define MTK_STAR_REG_C_RXVLANDROP
#define MTK_STAR_REG_C_RXCSERR
#define MTK_STAR_REG_C_RXPAUSE
#define MTK_STAR_REG_C_TXOKPKT
#define MTK_STAR_REG_C_TXOKBYTE
#define MTK_STAR_REG_C_TXPAUSECOL
#define MTK_STAR_REG_C_TXRTY
#define MTK_STAR_REG_C_TXSKIP
#define MTK_STAR_REG_C_TX_ARP
#define MTK_STAR_REG_C_RX_RERR
#define MTK_STAR_REG_C_RX_UNI
#define MTK_STAR_REG_C_RX_MULTI
#define MTK_STAR_REG_C_RX_BROAD
#define MTK_STAR_REG_C_RX_ALIGNERR
#define MTK_STAR_REG_C_TX_UNI
#define MTK_STAR_REG_C_TX_MULTI
#define MTK_STAR_REG_C_TX_BROAD
#define MTK_STAR_REG_C_TX_TIMEOUT
#define MTK_STAR_REG_C_TX_LATECOL
#define MTK_STAR_REG_C_RX_LENGTHERR
#define MTK_STAR_REG_C_RX_TWIST

/* Ethernet CFG Control */
#define MTK_PERICFG_REG_NIC_CFG0_CON
#define MTK_PERICFG_REG_NIC_CFG1_CON
#define MTK_PERICFG_REG_NIC_CFG_CON_V2
#define MTK_PERICFG_REG_NIC_CFG_CON_CFG_INTF
#define MTK_PERICFG_BIT_NIC_CFG_CON_MII
#define MTK_PERICFG_BIT_NIC_CFG_CON_RMII
#define MTK_PERICFG_BIT_NIC_CFG_CON_CLK
#define MTK_PERICFG_BIT_NIC_CFG_CON_CLK_V2

/* Represents the actual structure of descriptors used by the MAC. We can
 * reuse the same structure for both TX and RX - the layout is the same, only
 * the flags differ slightly.
 */
struct mtk_star_ring_desc {};

#define MTK_STAR_DESC_MSK_LEN
#define MTK_STAR_DESC_BIT_RX_CRCE
#define MTK_STAR_DESC_BIT_RX_OSIZE
#define MTK_STAR_DESC_BIT_INT
#define MTK_STAR_DESC_BIT_LS
#define MTK_STAR_DESC_BIT_FS
#define MTK_STAR_DESC_BIT_EOR
#define MTK_STAR_DESC_BIT_COWN

/* Helper structure for storing data read from/written to descriptors in order
 * to limit reads from/writes to DMA memory.
 */
struct mtk_star_ring_desc_data {};

#define MTK_STAR_RING_NUM_DESCS
#define MTK_STAR_TX_THRESH
#define MTK_STAR_NUM_TX_DESCS
#define MTK_STAR_NUM_RX_DESCS
#define MTK_STAR_NUM_DESCS_TOTAL
#define MTK_STAR_DMA_SIZE

struct mtk_star_ring {};

struct mtk_star_compat {};

struct mtk_star_priv {};

static struct device *mtk_star_get_dev(struct mtk_star_priv *priv)
{}

static const struct regmap_config mtk_star_regmap_config =;

static void mtk_star_ring_init(struct mtk_star_ring *ring,
			       struct mtk_star_ring_desc *descs)
{}

static int mtk_star_ring_pop_tail(struct mtk_star_ring *ring,
				  struct mtk_star_ring_desc_data *desc_data)
{}

static void mtk_star_ring_push_head(struct mtk_star_ring *ring,
				    struct mtk_star_ring_desc_data *desc_data,
				    unsigned int flags)
{}

static void
mtk_star_ring_push_head_rx(struct mtk_star_ring *ring,
			   struct mtk_star_ring_desc_data *desc_data)
{}

static void
mtk_star_ring_push_head_tx(struct mtk_star_ring *ring,
			   struct mtk_star_ring_desc_data *desc_data)
{}

static unsigned int mtk_star_tx_ring_avail(struct mtk_star_ring *ring)
{}

static dma_addr_t mtk_star_dma_map_rx(struct mtk_star_priv *priv,
				      struct sk_buff *skb)
{}

static void mtk_star_dma_unmap_rx(struct mtk_star_priv *priv,
				  struct mtk_star_ring_desc_data *desc_data)
{}

static dma_addr_t mtk_star_dma_map_tx(struct mtk_star_priv *priv,
				      struct sk_buff *skb)
{}

static void mtk_star_dma_unmap_tx(struct mtk_star_priv *priv,
				  struct mtk_star_ring_desc_data *desc_data)
{}

static void mtk_star_nic_disable_pd(struct mtk_star_priv *priv)
{}

static void mtk_star_enable_dma_irq(struct mtk_star_priv *priv,
				    bool rx, bool tx)
{}

static void mtk_star_disable_dma_irq(struct mtk_star_priv *priv,
				     bool rx, bool tx)
{}

/* Unmask the three interrupts we care about, mask all others. */
static void mtk_star_intr_enable(struct mtk_star_priv *priv)
{}

static void mtk_star_intr_disable(struct mtk_star_priv *priv)
{}

static unsigned int mtk_star_intr_ack_all(struct mtk_star_priv *priv)
{}

static void mtk_star_dma_init(struct mtk_star_priv *priv)
{}

static void mtk_star_dma_start(struct mtk_star_priv *priv)
{}

static void mtk_star_dma_stop(struct mtk_star_priv *priv)
{}

static void mtk_star_dma_disable(struct mtk_star_priv *priv)
{}

static void mtk_star_dma_resume_rx(struct mtk_star_priv *priv)
{}

static void mtk_star_dma_resume_tx(struct mtk_star_priv *priv)
{}

static void mtk_star_set_mac_addr(struct net_device *ndev)
{}

static void mtk_star_reset_counters(struct mtk_star_priv *priv)
{}

static void mtk_star_update_stat(struct mtk_star_priv *priv,
				 unsigned int reg, u64 *stat)
{}

/* Try to get as many stats as possible from the internal registers instead
 * of tracking them ourselves.
 */
static void mtk_star_update_stats(struct mtk_star_priv *priv)
{}

static struct sk_buff *mtk_star_alloc_skb(struct net_device *ndev)
{}

static int mtk_star_prepare_rx_skbs(struct net_device *ndev)
{}

static void
mtk_star_ring_free_skbs(struct mtk_star_priv *priv, struct mtk_star_ring *ring,
			void (*unmap_func)(struct mtk_star_priv *,
					   struct mtk_star_ring_desc_data *))
{}

static void mtk_star_free_rx_skbs(struct mtk_star_priv *priv)
{}

static void mtk_star_free_tx_skbs(struct mtk_star_priv *priv)
{}

/**
 * mtk_star_handle_irq - Interrupt Handler.
 * @irq: interrupt number.
 * @data: pointer to a network interface device structure.
 * Description : this is the driver interrupt service routine.
 * it mainly handles:
 *  1. tx complete interrupt for frame transmission.
 *  2. rx complete interrupt for frame reception.
 *  3. MAC Management Counter interrupt to avoid counter overflow.
 **/
static irqreturn_t mtk_star_handle_irq(int irq, void *data)
{}

/* Wait for the completion of any previous command - CMD_START bit must be
 * cleared by hardware.
 */
static int mtk_star_hash_wait_cmd_start(struct mtk_star_priv *priv)
{}

static int mtk_star_hash_wait_ok(struct mtk_star_priv *priv)
{}

static int mtk_star_set_hashbit(struct mtk_star_priv *priv,
				unsigned int hash_addr)
{}

static int mtk_star_reset_hash_table(struct mtk_star_priv *priv)
{}

static void mtk_star_phy_config(struct mtk_star_priv *priv)
{}

static void mtk_star_adjust_link(struct net_device *ndev)
{}

static void mtk_star_init_config(struct mtk_star_priv *priv)
{}

static int mtk_star_enable(struct net_device *ndev)
{}

static void mtk_star_disable(struct net_device *ndev)
{}

static int mtk_star_netdev_open(struct net_device *ndev)
{}

static int mtk_star_netdev_stop(struct net_device *ndev)
{}

static int mtk_star_netdev_ioctl(struct net_device *ndev,
				 struct ifreq *req, int cmd)
{}

static int __mtk_star_maybe_stop_tx(struct mtk_star_priv *priv, u16 size)
{}

static inline int mtk_star_maybe_stop_tx(struct mtk_star_priv *priv, u16 size)
{}

static netdev_tx_t mtk_star_netdev_start_xmit(struct sk_buff *skb,
					      struct net_device *ndev)
{}

/* Returns the number of bytes sent or a negative number on the first
 * descriptor owned by DMA.
 */
static int mtk_star_tx_complete_one(struct mtk_star_priv *priv)
{}

static int mtk_star_tx_poll(struct napi_struct *napi, int budget)
{}

static void mtk_star_netdev_get_stats64(struct net_device *ndev,
					struct rtnl_link_stats64 *stats)
{}

static void mtk_star_set_rx_mode(struct net_device *ndev)
{}

static const struct net_device_ops mtk_star_netdev_ops =;

static void mtk_star_get_drvinfo(struct net_device *dev,
				 struct ethtool_drvinfo *info)
{}

/* TODO Add ethtool stats. */
static const struct ethtool_ops mtk_star_ethtool_ops =;

static int mtk_star_rx(struct mtk_star_priv *priv, int budget)
{}

static int mtk_star_rx_poll(struct napi_struct *napi, int budget)
{}

static void mtk_star_mdio_rwok_clear(struct mtk_star_priv *priv)
{}

static int mtk_star_mdio_rwok_wait(struct mtk_star_priv *priv)
{}

static int mtk_star_mdio_read(struct mii_bus *mii, int phy_id, int regnum)
{}

static int mtk_star_mdio_write(struct mii_bus *mii, int phy_id,
			       int regnum, u16 data)
{}

static int mtk_star_mdio_init(struct net_device *ndev)
{}

static __maybe_unused int mtk_star_suspend(struct device *dev)
{}

static __maybe_unused int mtk_star_resume(struct device *dev)
{}

static void mtk_star_clk_disable_unprepare(void *data)
{}

static int mtk_star_set_timing(struct mtk_star_priv *priv)
{}

static int mtk_star_probe(struct platform_device *pdev)
{}

#ifdef CONFIG_OF
static int mt8516_set_interface_mode(struct net_device *ndev)
{}

static int mt8365_set_interface_mode(struct net_device *ndev)
{}

static const struct mtk_star_compat mtk_star_mt8516_compat =;

static const struct mtk_star_compat mtk_star_mt8365_compat =;

static const struct of_device_id mtk_star_of_match[] =;
MODULE_DEVICE_TABLE(of, mtk_star_of_match);
#endif

static SIMPLE_DEV_PM_OPS(mtk_star_pm_ops,
			 mtk_star_suspend, mtk_star_resume);

static struct platform_driver mtk_star_driver =;
module_platform_driver();

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