X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/328df0407e5b3cdeb3bfbc7f51c196d244905d93..18a076fccdba90cd7bea1dd4cff1b6b0559b75f0:/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h?ds=inline diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h index cbc6f75e4..8a2913f21 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h @@ -1,7 +1,7 @@ /* * Atheros AR71xx built-in ethernet mac driver * - * Copyright (C) 2008 Gabor Juhos + * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -37,26 +38,20 @@ #define ETH_FCS_LEN 4 #define AG71XX_DRV_NAME "ag71xx" -#define AG71XX_DRV_VERSION "0.5.1" - -#define AG71XX_NAPI_TX 1 +#define AG71XX_DRV_VERSION "0.5.35" #define AG71XX_NAPI_WEIGHT 64 +#define AG71XX_OOM_REFILL (1 + HZ/10) #define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE) #define AG71XX_INT_TX (AG71XX_INT_TX_PS) #define AG71XX_INT_RX (AG71XX_INT_RX_PR | AG71XX_INT_RX_OF) -#ifdef AG71XX_NAPI_TX #define AG71XX_INT_POLL (AG71XX_INT_RX | AG71XX_INT_TX) #define AG71XX_INT_INIT (AG71XX_INT_ERR | AG71XX_INT_POLL) -#else -#define AG71XX_INT_POLL (AG71XX_INT_RX) -#define AG71XX_INT_INIT (AG71XX_INT_ERR | AG71XX_INT_POLL | AG71XX_INT_TX) -#endif #define AG71XX_TX_FIFO_LEN 2048 -#define AG71XX_TX_MTU_LEN 1536 +#define AG71XX_TX_MTU_LEN 1540 #define AG71XX_RX_PKT_RESERVE 64 #define AG71XX_RX_PKT_SIZE \ (AG71XX_RX_PKT_RESERVE + ETH_HLEN + ETH_FRAME_LEN + ETH_FCS_LEN) @@ -68,8 +63,7 @@ #define AG71XX_RX_RING_SIZE 128 -#undef AG71XX_DEBUG -#ifdef AG71XX_DEBUG +#ifdef CONFIG_AG71XX_DEBUG #define DBG(fmt, args...) printk(KERN_DEBUG fmt, ## args) #else #define DBG(fmt, args...) do {} while (0) @@ -88,32 +82,69 @@ struct ag71xx_desc { u32 ctrl; #define DESC_EMPTY BIT(31) #define DESC_MORE BIT(24) -#define DESC_PKTLEN_M 0x1fff +#define DESC_PKTLEN_M 0xfff u32 next; -}; + u32 pad; +} __attribute__((aligned(4))); struct ag71xx_buf { - struct sk_buff *skb; + struct sk_buff *skb; + struct ag71xx_desc *desc; + dma_addr_t dma_addr; + u32 pad; }; struct ag71xx_ring { struct ag71xx_buf *buf; - struct ag71xx_desc *descs; + u8 *descs_cpu; dma_addr_t descs_dma; + unsigned int desc_size; unsigned int curr; unsigned int dirty; unsigned int size; }; struct ag71xx_mdio { - struct mii_bus mii_bus; - int mii_irq[PHY_MAX_ADDR]; - void __iomem *mdio_base; + struct mii_bus *mii_bus; + int mii_irq[PHY_MAX_ADDR]; + void __iomem *mdio_base; + struct ag71xx_mdio_platform_data *pdata; +}; + +struct ag71xx_int_stats { + unsigned long rx_pr; + unsigned long rx_be; + unsigned long rx_of; + unsigned long tx_ps; + unsigned long tx_be; + unsigned long tx_ur; + unsigned long total; +}; + +struct ag71xx_napi_stats { + unsigned long napi_calls; + unsigned long rx_count; + unsigned long rx_packets; + unsigned long rx_packets_max; + unsigned long tx_count; + unsigned long tx_packets; + unsigned long tx_packets_max; + + unsigned long rx[AG71XX_NAPI_WEIGHT + 1]; + unsigned long tx[AG71XX_NAPI_WEIGHT + 1]; +}; + +struct ag71xx_debug { + struct dentry *debugfs_dir; + struct dentry *debugfs_int_stats; + struct dentry *debugfs_napi_stats; + + struct ag71xx_int_stats int_stats; + struct ag71xx_napi_stats napi_stats; }; struct ag71xx { void __iomem *mac_base; - void __iomem *mac_base2; void __iomem *mii_ctrl; spinlock_t lock; @@ -127,22 +158,30 @@ struct ag71xx { struct mii_bus *mii_bus; struct phy_device *phy_dev; + void *phy_priv; unsigned int link; unsigned int speed; - int duplex; + int duplex; + + struct work_struct restart_work; + struct timer_list oom_timer; + +#ifdef CONFIG_AG71XX_DEBUG_FS + struct ag71xx_debug debug; +#endif }; extern struct ethtool_ops ag71xx_ethtool_ops; +void ag71xx_link_adjust(struct ag71xx *ag); -extern struct ag71xx_mdio *ag71xx_mdio_bus; -extern int ag71xx_mdio_driver_init(void) __init; -extern void ag71xx_mdio_driver_exit(void); +int ag71xx_mdio_driver_init(void) __init; +void ag71xx_mdio_driver_exit(void); -extern int ag71xx_phy_connect(struct ag71xx *ag); -extern void ag71xx_phy_disconnect(struct ag71xx *ag); -extern void ag71xx_phy_start(struct ag71xx *ag); -extern void ag71xx_phy_stop(struct ag71xx *ag); +int ag71xx_phy_connect(struct ag71xx *ag); +void ag71xx_phy_disconnect(struct ag71xx *ag); +void ag71xx_phy_start(struct ag71xx *ag); +void ag71xx_phy_stop(struct ag71xx *ag); static inline struct ag71xx_platform_data *ag71xx_get_pdata(struct ag71xx *ag) { @@ -151,12 +190,12 @@ static inline struct ag71xx_platform_data *ag71xx_get_pdata(struct ag71xx *ag) static inline int ag71xx_desc_empty(struct ag71xx_desc *desc) { - return ((desc->ctrl & DESC_EMPTY) != 0); + return (desc->ctrl & DESC_EMPTY) != 0; } static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) { - return (desc->ctrl & DESC_PKTLEN_M); + return desc->ctrl & DESC_PKTLEN_M; } /* Register offsets */ @@ -229,7 +268,7 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define FIFO_CFG4_DV BIT(1) /* RX_DV Event */ #define FIFO_CFG4_FC BIT(2) /* False Carrier */ #define FIFO_CFG4_CE BIT(3) /* Code Error */ -#define FIFO_CFG4_CRC BIT(4) /* CRC error */ +#define FIFO_CFG4_CR BIT(4) /* CRC error */ #define FIFO_CFG4_LM BIT(5) /* Length Mismatch */ #define FIFO_CFG4_LO BIT(6) /* Length out of range */ #define FIFO_CFG4_OK BIT(7) /* Packet is OK */ @@ -260,6 +299,8 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define FIFO_CFG5_VT BIT(13) /* VLAN tag detected */ #define FIFO_CFG5_LE BIT(14) /* Long Event */ #define FIFO_CFG5_FT BIT(15) /* Frame Truncated */ +#define FIFO_CFG5_16 BIT(16) /* unknown */ +#define FIFO_CFG5_17 BIT(17) /* unknown */ #define FIFO_CFG5_SF BIT(18) /* Short Frame */ #define FIFO_CFG5_BM BIT(19) /* Byte Mode */ @@ -287,17 +328,17 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define MII_IND_BUSY BIT(0) #define MII_IND_INVALID BIT(2) -#define TX_CTRL_TXE BIT(0) +#define TX_CTRL_TXE BIT(0) /* Tx Enable */ -#define TX_STATUS_PS BIT(0) -#define TX_STATUS_UR BIT(1) -#define TX_STATUS_BE BIT(3) +#define TX_STATUS_PS BIT(0) /* Packet Sent */ +#define TX_STATUS_UR BIT(1) /* Tx Underrun */ +#define TX_STATUS_BE BIT(3) /* Bus Error */ -#define RX_CTRL_RXE BIT(0) +#define RX_CTRL_RXE BIT(0) /* Rx Enable */ -#define RX_STATUS_PR BIT(0) -#define RX_STATUS_OF BIT(1) -#define RX_STATUS_BE BIT(3) +#define RX_STATUS_PR BIT(0) /* Packet Received */ +#define RX_STATUS_OF BIT(2) /* Rx Overflow */ +#define RX_STATUS_BE BIT(3) /* Bus Error */ #define MII_CTRL_IF_MASK 3 #define MII_CTRL_SPEED_SHIFT 4 @@ -306,74 +347,56 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define MII_CTRL_SPEED_100 1 #define MII_CTRL_SPEED_1000 2 -static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value) +static inline void ag71xx_check_reg_offset(struct ag71xx *ag, unsigned reg) { switch (reg) { case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: - __raw_writel(value, ag->mac_base + reg); - break; case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: - reg -= AG71XX_REG_MAC_IFCTL; - __raw_writel(value, ag->mac_base2 + reg); break; + default: BUG(); } } -static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) +static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value) { - u32 ret; + ag71xx_check_reg_offset(ag, reg); - switch (reg) { - case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: - ret = __raw_readl(ag->mac_base + reg); - break; - case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: - reg -= AG71XX_REG_MAC_IFCTL; - ret = __raw_readl(ag->mac_base2 + reg); - break; - default: - BUG(); - } + __raw_writel(value, ag->mac_base + reg); + /* flush write */ + (void) __raw_readl(ag->mac_base + reg); +} + +static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) +{ + ag71xx_check_reg_offset(ag, reg); - return ret; + return __raw_readl(ag->mac_base + reg); } static inline void ag71xx_sb(struct ag71xx *ag, unsigned reg, u32 mask) { void __iomem *r; - switch (reg) { - case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: - r = ag->mac_base + reg; - __raw_writel(__raw_readl(r) | mask, r); - break; - case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: - r = ag->mac_base2 + reg - AG71XX_REG_MAC_IFCTL; - __raw_writel(__raw_readl(r) | mask, r); - break; - default: - BUG(); - } + ag71xx_check_reg_offset(ag, reg); + + r = ag->mac_base + reg; + __raw_writel(__raw_readl(r) | mask, r); + /* flush write */ + (void)__raw_readl(r); } static inline void ag71xx_cb(struct ag71xx *ag, unsigned reg, u32 mask) { void __iomem *r; - switch (reg) { - case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: - r = ag->mac_base + reg; - __raw_writel(__raw_readl(r) & ~mask, r); - break; - case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: - r = ag->mac_base2 + reg - AG71XX_REG_MAC_IFCTL; - __raw_writel(__raw_readl(r) & ~mask, r); - break; - default: - BUG(); - } + ag71xx_check_reg_offset(ag, reg); + + r = ag->mac_base + reg; + __raw_writel(__raw_readl(r) & ~mask, r); + /* flush write */ + (void) __raw_readl(r); } static inline void ag71xx_int_enable(struct ag71xx *ag, u32 ints) @@ -388,15 +411,28 @@ static inline void ag71xx_int_disable(struct ag71xx *ag, u32 ints) static inline void ag71xx_mii_ctrl_wr(struct ag71xx *ag, u32 value) { + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + + if (pdata->is_ar724x) + return; + __raw_writel(value, ag->mii_ctrl); + + /* flush write */ + __raw_readl(ag->mii_ctrl); } static inline u32 ag71xx_mii_ctrl_rr(struct ag71xx *ag) { + struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + + if (pdata->is_ar724x) + return 0xffffffff; + return __raw_readl(ag->mii_ctrl); } -static void inline ag71xx_mii_ctrl_set_if(struct ag71xx *ag, +static inline void ag71xx_mii_ctrl_set_if(struct ag71xx *ag, unsigned int mii_if) { u32 t; @@ -407,7 +443,7 @@ static void inline ag71xx_mii_ctrl_set_if(struct ag71xx *ag, ag71xx_mii_ctrl_wr(ag, t); } -static void inline ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, +static inline void ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, unsigned int speed) { u32 t; @@ -418,4 +454,53 @@ static void inline ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, ag71xx_mii_ctrl_wr(ag, t); } +#ifdef CONFIG_AG71XX_AR8216_SUPPORT +void ag71xx_add_ar8216_header(struct ag71xx *ag, struct sk_buff *skb); +int ag71xx_remove_ar8216_header(struct ag71xx *ag, struct sk_buff *skb, + int pktlen); +static inline int ag71xx_has_ar8216(struct ag71xx *ag) +{ + return ag71xx_get_pdata(ag)->has_ar8216; +} +#else +static inline void ag71xx_add_ar8216_header(struct ag71xx *ag, + struct sk_buff *skb) +{ +} + +static inline int ag71xx_remove_ar8216_header(struct ag71xx *ag, + struct sk_buff *skb, + int pktlen) +{ + return 0; +} +static inline int ag71xx_has_ar8216(struct ag71xx *ag) +{ + return 0; +} +#endif + +#ifdef CONFIG_AG71XX_DEBUG_FS +int ag71xx_debugfs_root_init(void); +void ag71xx_debugfs_root_exit(void); +int ag71xx_debugfs_init(struct ag71xx *ag); +void ag71xx_debugfs_exit(struct ag71xx *ag); +void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status); +void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx); +#else +static inline int ag71xx_debugfs_root_init(void) { return 0; } +static inline void ag71xx_debugfs_root_exit(void) {} +static inline int ag71xx_debugfs_init(struct ag71xx *ag) { return 0; } +static inline void ag71xx_debugfs_exit(struct ag71xx *ag) {} +static inline void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, + u32 status) {} +static inline void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, + int rx, int tx) {} +#endif /* CONFIG_AG71XX_DEBUG_FS */ + +void ag71xx_ar7240_start(struct ag71xx *ag); +void ag71xx_ar7240_stop(struct ag71xx *ag); +int ag71xx_ar7240_init(struct ag71xx *ag); +void ag71xx_ar7240_cleanup(struct ag71xx *ag); + #endif /* _AG71XX_H */