You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
13 KiB

#ifndef __HLETH_H
#define __HLETH_H
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/list.h>
#include <linux/phy.h>
#include <linux/io.h>
#define HLETH_SKB_MEMORY_STATS
#define HLETH_MIIBUS_NAME "hlmii"
#define HLETH_DRIVER_NAME "hleth"
/* hleth max port */
#define HLETH_MAX_PORT 2
/* invalid phy addr */
#define HLETH_INVALID_PHY_ADDR 0xff
/* hleth monitor timer, 10ms */
#define HLETH_MONITOR_TIMER 10
/* hleth hardware queue send fifo depth, increase to optimize TX performance. */
#define HLETH_HWQ_XMIT_DEPTH 12
/* set irq affinity to cpu1 when multi-processor */
#define HLETH_IRQ_AFFINITY_CPU 1
#define HLETH_MAX_QUEUE_DEPTH 64
#define HLETH_MAX_RX_HEAD_LEN (10000) /* max skbs for rx */
#define HLETH_MAX_RCV_LEN 1535 /* max receive length */
#define TXQ_NUM 64
#define RXQ_NUM 128
#define HLETH_NAPI_WEIGHT 32
/* mmu should be less than 1600 Bytes
*/
#define HLETH_MAX_FRAME_SIZE (1600)
#define SKB_SIZE (HLETH_MAX_FRAME_SIZE)
#define hleth_invalid_rxpkg_len(len) (!((len) >= 42 && \
(len) <= HLETH_MAX_FRAME_SIZE))
#define HLETH_MAX_MAC_FILTER_NUM 8
#define HLETH_MAX_UNICAST_ADDRESSES 2
#define HLETH_MAX_MULTICAST_ADDRESSES (HLETH_MAX_MAC_FILTER_NUM - \
HLETH_MAX_UNICAST_ADDRESSES)
/* Register Definition
*/
/*------------------------- port register -----------------------------------*/
/* Mac port sel */
#define HLETH_P_MAC_PORTSEL 0x0200
#define HLETH_P_MAC_PORTSEL_STAT 0
#define HLETH_P_MAC_PORTSEL_STAT_MDIO 0
#define HLETH_P_MAC_PORTSEL_STAT_CPU 1
#define HLETH_P_MAC_PORTSEL_MII_MODE 1
#define HLETH_P_MAC_PORTSEL_MII ~BIT(1)
#define HLETH_P_MAC_PORTSEL_RMII BIT(1)
/* Mac ro status */
#define HLETH_P_MAC_RO_STAT 0x0204
/* Mac port status set */
#define HLETH_P_MAC_PORTSET 0x0208
#define HLETH_P_MAC_PORTSET_SPD_100M BIT(2)
#define HLETH_P_MAC_PORTSET_LINKED BIT(1)
#define HLETH_P_MAC_PORTSET_DUP_FULL BIT(0)
/* Mac status change */
#define HLETH_P_MAC_STAT_CHANGE 0x020C
/* Mac set */
#define HLETH_P_MAC_SET 0x0210
#define hleth_p_mac_set_len_max(n) ((n) & 0x7FF)
#define HLETH_P_MAC_SET_LEN_MAX_MSK GENMASK(10, 0)
#define HLETH_P_MAC_RX_IPGCTRL 0x0214
#define HLETH_P_MAC_TX_IPGCTRL 0x0218
#define HLETH_P_MAC_TX_IPGCTRL_PRE_CNT_LMT_SHIFT 23
#define HLETH_P_MAC_TX_IPGCTRL_PRE_CNT_LMT_MSK GENMASK(25, 23)
/* queue length set */
#define HLETH_P_GLB_QLEN_SET 0x0344
#define HLETH_P_GLB_QLEN_SET_TXQ_DEP_MSK GENMASK(5, 0)
#define hleth_p_glb_qlen_set_txq_dep(n) ((n) << 0)
#define HLETH_P_GLB_QLEN_SET_RXQ_DEP_MSK GENMASK(13, 8)
#define hleth_p_glb_qlen_set_rxq_dep(n) ((n) << 8)
/* Rx frame start addr */
#define HLETH_P_GLB_RXFRM_SADDR 0x0350
/* Rx (read only) Queue-ID and LEN */
#define HLETH_P_GLB_RO_IQFRM_DES 0x0354
#define HLETH_P_GLB_RO_IQFRM_DES_FDIN_LEN_MSK GENMASK(11, 0)
/* Rx ADDR */
#define HLETH_P_GLB_IQ_ADDR 0x0358
/* Tx ADDR and LEN */
#define HLETH_P_GLB_EQ_ADDR 0x0360
#define HLETH_P_GLB_EQFRM_LEN 0x0364
#define HLETH_P_GLB_EQFRM_TXINQ_LEN_MSK GENMASK(10, 0)
/* Rx/Tx Queue ID */
#define HLETH_P_GLB_RO_QUEUE_ID 0x0368
/* Rx/Tx Queue staus */
#define HLETH_P_GLB_RO_QUEUE_STAT 0x036C
/* check this bit to see if we can add a Tx package */
#define HLETH_P_GLB_RO_QUEUE_STAT_XMITQ_RDY_MSK BIT(24)
/* check this bit to see if we can add a Rx addr */
#define HLETH_P_GLB_RO_QUEUE_STAT_RECVQ_RDY_MSK BIT(25)
/* counts in queue, include currently sending */
#define HLETH_P_GLB_RO_QUEUE_STAT_XMITQ_CNT_INUSE_MSK GENMASK(5, 0)
/* Rx Checksum Offload Control */
#define HLETH_P_RX_COE_CTRL 0x0380
#define BIT_COE_PAYLOAD_DROP BIT(14)
#define HLETH_P_RF_OVERCNT 0x634
/*------------------------- global register --------------------------------*/
/* host mac address */
#define HLETH_GLB_HOSTMAC_L32 0x1300
#define HLETH_GLB_HOSTMAC_H16 0x1304
/* soft reset */
#define HLETH_GLB_SOFT_RESET 0x1308
#define HLETH_GLB_SOFT_RESET_ALL BIT(0)
#define HLETH_GLB_SOFT_RESET_P0 BIT(2)
#define HLETH_GLB_SOFT_RESET_P1 BIT(3)
/* forward contrl */
#define HLETH_GLB_FWCTRL 0x1310
#define HLETH_GLB_FWCTRL_VLAN_ENABLE BIT(0)
#define HLETH_GLB_FWCTRL_FW2CPU_ENA_U BIT(5)
#define HLETH_GLB_FWCTRL_FW2CPU_ENA_D BIT(9)
#define HLETH_GLB_FWCTRL_FWALL2CPU_U BIT(7)
#define HLETH_GLB_FWCTRL_FWALL2CPU_D BIT(11)
#define HLETH_GLB_FWCTRL_FW2OTHPORT_ENA_U BIT(4)
#define HLETH_GLB_FWCTRL_FW2OTHPORT_ENA_D BIT(8)
#define HLETH_GLB_FWCTRL_FW2OTHPORT_FORCE_U BIT(6)
#define HLETH_GLB_FWCTRL_FW2OTHPORT_FORCE_D BIT(10)
/* Mac filter table control */
#define HLETH_GLB_MACTCTRL 0x1314
#define HLETH_GLB_MACTCTRL_MACT_ENA_U BIT(7)
#define HLETH_GLB_MACTCTRL_MACT_ENA_D BIT(15)
#define HLETH_GLB_MACTCTRL_BROAD2CPU_U BIT(5)
#define HLETH_GLB_MACTCTRL_BROAD2CPU_D BIT(13)
#define HLETH_GLB_MACTCTRL_BROAD2OTHPORT_U BIT(4)
#define HLETH_GLB_MACTCTRL_BROAD2OTHPORT_D BIT(12)
#define HLETH_GLB_MACTCTRL_MULTI2CPU_U BIT(3)
#define HLETH_GLB_MACTCTRL_MULTI2CPU_D BIT(11)
#define HLETH_GLB_MACTCTRL_MULTI2OTHPORT_U BIT(2)
#define HLETH_GLB_MACTCTRL_MULTI2OTHPORT_D BIT(10)
#define HLETH_GLB_MACTCTRL_UNI2CPU_U BIT(1)
#define HLETH_GLB_MACTCTRL_UNI2CPU_D BIT(9)
#define HLETH_GLB_MACTCTRL_UNI2OTHPORT_U BIT(0)
#define HLETH_GLB_MACTCTRL_UNI2OTHPORT_D BIT(8)
/* Host mac address */
#define HLETH_GLB_DN_HOSTMAC_L32 0x1340
#define HLETH_GLB_DN_HOSTMAC_H16 0x1344
#define HLETH_GLB_DN_HOSTMAC_ENA 0x1348
#define HLETH_GLB_DN_HOSTMAC_ENA_BIT BIT(0)
/* Mac filter */
#define HLETH_GLB_MAC_L32_BASE 0x1400
#define HLETH_GLB_MAC_H16_BASE 0x1404
#define HLETH_GLB_MAC_L32_BASE_D (0x1400 + 16 * 0x8)
#define HLETH_GLB_MAC_H16_BASE_D (0x1404 + 16 * 0x8)
#define HLETH_GLB_MACFLT_H16 GENMASK(15, 0)
#define HLETH_GLB_MACFLT_FW2CPU_U BIT(21)
#define HLETH_GLB_MACFLT_FW2CPU_D BIT(19)
#define HLETH_GLB_MACFLT_FW2PORT_U BIT(20)
#define HLETH_GLB_MACFLT_FW2PORT_D BIT(18)
#define HLETH_GLB_MACFLT_ENA_U BIT(17)
#define HLETH_GLB_MACFLT_ENA_D BIT(16)
/* ENDIAN */
#define HLETH_GLB_ENDIAN_MOD 0x1318
#define HLETH_GLB_ENDIAN_MOD_IN BIT(1)
#define HLETH_GLB_ENDIAN_MOD_OUT BIT(0)
/* IRQs */
#define HLETH_GLB_IRQ_STAT 0x1330
#define HLETH_GLB_IRQ_ENA 0x1334
#define HLETH_GLB_IRQ_ENA_IEN_A BIT(19)
#define HLETH_GLB_IRQ_ENA_IEN_U BIT(18)
#define HLETH_GLB_IRQ_ENA_IEN_D BIT(17)
#define HLETH_GLB_IRQ_ENA_BIT_U GENMASK(7, 0)
#define HLETH_GLB_IRQ_ENA_BIT_D GENMASK(27, 20)
#define HLETH_GLB_IRQ_RAW 0x1338
#define HLETH_GLB_IRQ_INT_MULTI_RXRDY_U BIT(7)
#define HLETH_GLB_IRQ_INT_MULTI_RXRDY_D BIT(27)
#define HLETH_GLB_IRQ_INT_TXQUE_RDY_U BIT(6)
#define HLETH_GLB_IRQ_INT_TXQUE_RDY_D BIT(26)
#define HLETH_GLB_IRQ_INT_RX_RDY_U BIT(0)
#define HLETH_GLB_IRQ_INT_RX_RDY_D BIT(20)
/* ***********************************************************
*
* Only for internal used!
*
* ***********************************************************
*/
/* read/write IO */
#define hleth_readl(base, ofs) \
readl(base + (ofs))
#define hleth_writel(base, v, ofs) \
writel(v, base + (ofs))
#define HLETH_TRACE_LEVEL 8
#define hlreg_trace(level, msg...) do { \
if ((level) >= HLETH_TRACE_LEVEL) { \
pr_info("hlreg_trace:%s:%d: ", __func__, __LINE__); \
pr_info(msg); \
pr_info("\n"); \
} \
} while (0)
#define hlreg_readl(base, ofs) ({ unsigned long reg = readl((base) + (ofs)); \
hlreg_trace(2, "_readl(0x%04X) = 0x%08lX", (ofs), reg); \
reg; })
#define hlreg_writel(base, v, ofs) do { writel((v), (base) + (ofs)); \
hlreg_trace(2, "_writel(0x%04X) = 0x%08lX", \
(ofs), (unsigned long)(v)); \
} while (0)
#define hleth_dump_buf(buf, len) do { \
int i; \
char *p = (void *)(buf); \
pr_info("%s->%d, buf=0x%.8x, len=%d\n", \
__func__, __LINE__, \
(int)(buf), (int)(len)); \
for (i = 0; i < (len); i++) { \
pr_info("0x%.2x ", *(p+i)); \
if (!((i+1) & 0x07)) \
pr_info("\n"); \
} \
pr_info("\n"); \
} while (0)
/* port */
enum hleth_port_e {
HLETH_PORT_0 = 0,
HLETH_PORT_1,
HLETH_PORT_NUM,
};
struct hleth_queue {
struct sk_buff **skb;
dma_addr_t *dma_phys;
int num;
unsigned int head;
unsigned int tail;
};
struct hleth_netdev_priv {
void __iomem *glb_base; /* virtual io global addr */
void __iomem *port_base; /* virtual to port addr:
* port0-0; port1-0x2000
*/
int port; /* 0 => up port, 1 => down port */
int irq;
struct device *dev;
struct net_device *ndev;
struct net_device_stats stats;
struct phy_device *phy;
struct device_node *phy_node;
struct platform_device *pdev;
phy_interface_t phy_mode;
struct mii_bus *mii_bus;
struct sk_buff_head rx_head; /* received pkgs */
struct hleth_queue rxq;
struct hleth_queue txq;
u32 tx_fifo_used_cnt;
struct timer_list monitor;
struct {
int hw_xmitq;
} depth;
#ifdef CONFIG_HLETH_MAX_RX_POOLS
struct {
unsigned long rx_pool_dry_times;
} stat;
struct rx_skb_pool {
struct sk_buff *sk_pool[CONFIG_HLETH_MAX_RX_POOLS];/* skb pool */
int next_free_skb; /* next free skb */
} rx_pool;
#endif
struct napi_struct napi;
int link_stat;
int (*eee_init)(struct phy_device *phy_dev);
struct work_struct tx_timeout_task;
spinlock_t lock; /* lock for reg rw */
unsigned long lockflags;
spinlock_t mdio_lock; /* lock for mdio reg */
unsigned long mdio_lockflags;
struct clk *clk;
bool mac_wol_enabled;
bool pm_state_set;
bool autoeee_enabled;
#ifdef HLETH_SKB_MEMORY_STATS
atomic_t tx_skb_occupied;
atomic_t tx_skb_mem_occupied;
atomic_t rx_skb_occupied;
atomic_t rx_skb_mem_occupied;
#endif
unsigned int rx_fifo_overcnt;
};
/* phy parameter */
struct hleth_phy_param_s {
bool isvalid; /* valid or not */
bool isinternal; /* internal phy or external phy */
int phy_addr;
u32 trim_params;
phy_interface_t phy_mode;
const char *macaddr;
/* gpio reset pin if has */
void __iomem *gpio_base;
u32 gpio_bit;
};
#define MAX_MULTICAST_FILTER 8
#define MAX_MAC_LIMIT ETH_ALEN*MAX_MULTICAST_FILTER
struct ethstats {
void __iomem *base;
void __iomem *macbase[2];
char prbuf[SZ_4K];
u32 sz_prbuf;
struct dentry *dentry;
};
struct mcdump {
void __iomem *base;
u32 net_flags;
u32 mc_rcv;
u32 mc_drop;
u32 mac_nr;
spinlock_t lock;
char mac[MAX_MAC_LIMIT];
char prbuf[SZ_1K];
u32 sz_prbuf;
struct dentry *dentry;
};
#ifdef HLETH_SKB_MEMORY_STATS
struct eth_mem_stats {
char prbuf[SZ_1K];
u32 sz_prbuf;
struct dentry *dentry;
};
#endif
struct hleth_platdrv_data {
struct hleth_phy_param_s hleth_phy_param[HLETH_MAX_PORT];
struct net_device *hleth_devs_save[HLETH_MAX_PORT];
struct hleth_netdev_priv hleth_priv;
int hleth_real_port_cnt;
/* debugfs info */
struct dentry *root;
struct ethstats ethstats;
struct mcdump mcdump;
#ifdef HLETH_SKB_MEMORY_STATS
struct eth_mem_stats eth_mem_stats;
#endif
};
#undef local_lock_init
#undef local_lock
#undef local_unlock
#define local_lock_init(priv) spin_lock_init(&(priv)->lock)
#define local_lock_exit(priv)
#define local_lock(priv) spin_lock_irqsave(&(priv)->lock, \
(priv)->lockflags)
#define local_unlock(priv) spin_unlock_irqrestore(&(priv)->lock, \
(priv)->lockflags)
#define hleth_mdio_lock_init(priv) spin_lock_init(&(priv)->mdio_lock)
#define hleth_mdio_lock_exit(priv)
#define hleth_mdio_lock(priv) spin_lock_irqsave(&(priv)->mdio_lock, \
(priv)->mdio_lockflags)
#define hleth_mdio_unlock(priv) spin_unlock_irqrestore(&(priv)->mdio_lock, \
(priv)->mdio_lockflags)
#define ud_bit_name(name) ((priv->port == HLETH_PORT_0) ? \
name##_U : name##_D)
#define glb_mac_h16(port, reg) ((((port) == HLETH_PORT_0) ? \
HLETH_GLB_MAC_H16_BASE : \
HLETH_GLB_MAC_H16_BASE_D) + (reg * 0x8))
#define glb_mac_l32(port, reg) ((((port) == HLETH_PORT_0) ? \
HLETH_GLB_MAC_L32_BASE : \
HLETH_GLB_MAC_L32_BASE_D) + (reg * 0x8))
#define SIOCGETMODE (SIOCDEVPRIVATE) /* get work mode */
#define SIOCSETMODE (SIOCDEVPRIVATE + 1) /* set work mode */
#define SIOCGETFWD (SIOCDEVPRIVATE + 2) /* get forcing forward config */
#define SIOCSETFWD (SIOCDEVPRIVATE + 3) /* set forcing forward config */
#define SIOCSETPM (SIOCDEVPRIVATE + 4) /* set pmt wake up config */
#define SIOCSETSUSPEND (SIOCDEVPRIVATE + 5) /* call dev->suspend */
#define SIOCSETRESUME (SIOCDEVPRIVATE + 6) /* call dev->resume */
#define SIOCGETPM (SIOCDEVPRIVATE + 7) /* call dev->resume */
extern bool hleth_fephy_opt;
void hleth_autoeee_init(struct hleth_netdev_priv *priv, int link_stat);
void hleth_phy_register_fixups(void);
void hleth_phy_unregister_fixups(void);
void hleth_phy_reset(struct hleth_platdrv_data *pdata);
void hleth_phy_clk_disable(struct hleth_platdrv_data *pdata);
void hleth_fix_festa_phy_trim(struct mii_bus *bus, struct hleth_platdrv_data *pdata);
#endif
/* vim: set ts=8 sw=8 tw=78: */