X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/546b5ed544503182a9b3e981bc11feebd6042b21..b2f236b82b51018434550c9434e43f9b923afa7c:/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h index e22a7e6d3..77962fec8 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-2009 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver @@ -15,9 +15,11 @@ #define __AG71XX_H #include +#include #include #include #include +#include #include #include #include @@ -26,6 +28,7 @@ #include #include #include +#include #include @@ -35,23 +38,17 @@ #define ETH_FCS_LEN 4 #define AG71XX_DRV_NAME "ag71xx" -#define AG71XX_DRV_VERSION "0.3.9" - -#define AG71XX_NAPI_TX 1 +#define AG71XX_DRV_VERSION "0.5.25" #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 @@ -66,8 +63,7 @@ #define AG71XX_RX_RING_SIZE 128 -#undef DEBUG -#ifdef DEBUG +#ifdef CONFIG_AG71XX_DEBUG #define DBG(fmt, args...) printk(KERN_DEBUG fmt, ## args) #else #define DBG(fmt, args...) do {} while (0) @@ -86,23 +82,33 @@ 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 ag71xx_desc *desc; }; 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 ag71xx_mdio_platform_data *pdata; +}; + struct ag71xx { void __iomem *mac_base; void __iomem *mii_ctrl; @@ -111,56 +117,38 @@ struct ag71xx { struct platform_device *pdev; struct net_device *dev; struct napi_struct napi; + u32 msg_enable; struct ag71xx_ring rx_ring; struct ag71xx_ring tx_ring; + struct mii_bus *mii_bus; struct phy_device *phy_dev; - struct mii_bus mii_bus; unsigned int link; unsigned int speed; int duplex; + + struct work_struct restart_work; + struct timer_list oom_timer; }; extern struct ethtool_ops ag71xx_ethtool_ops; -extern int ag71xx_mdio_init(struct ag71xx *ag, int id); -extern void ag71xx_mdio_cleanup(struct ag71xx *ag); -extern int ag71xx_mii_peek(struct ag71xx *ag); -extern void ag71xx_mii_ctrl_set_if(struct ag71xx *ag, unsigned int mii_if); -extern void ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, unsigned int speed); -extern void ag71xx_link_update(struct ag71xx *ag); +extern struct ag71xx_mdio *ag71xx_mdio_bus; +int ag71xx_mdio_driver_init(void) __init; +void ag71xx_mdio_driver_exit(void); + +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) { return ag->pdev->dev.platform_data; } -static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value) -{ - __raw_writel(value, ag->mac_base + reg); -} - -static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) -{ - return __raw_readl(ag->mac_base + reg); -} - -static inline void ag71xx_sb(struct ag71xx *ag, unsigned reg, u32 mask) -{ - void __iomem *r = ag->mac_base + reg; - - __raw_writel(__raw_readl(r) | mask, r); -} - -static inline void ag71xx_cb(struct ag71xx *ag, unsigned reg, u32 mask) -{ - void __iomem *r = ag->mac_base + reg; - - __raw_writel(__raw_readl(r) & ~mask, r); -} - static inline int ag71xx_desc_empty(struct ag71xx_desc *desc) { return ((desc->ctrl & DESC_EMPTY) != 0); @@ -210,12 +198,14 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define AG71XX_REG_INT_ENABLE 0x0198 #define AG71XX_REG_INT_STATUS 0x019c -#define MAC_CFG1_TXE BIT(0) -#define MAC_CFG1_STX BIT(1) -#define MAC_CFG1_RXE BIT(2) -#define MAC_CFG1_SRX BIT(3) -#define MAC_CFG1_LB BIT(8) -#define MAC_CFG1_SR BIT(31) +#define MAC_CFG1_TXE BIT(0) /* Tx Enable */ +#define MAC_CFG1_STX BIT(1) /* Synchronize Tx Enable */ +#define MAC_CFG1_RXE BIT(2) /* Rx Enable */ +#define MAC_CFG1_SRX BIT(3) /* Synchronize Rx Enable */ +#define MAC_CFG1_TFC BIT(4) /* Tx Flow Control Enable */ +#define MAC_CFG1_RFC BIT(5) /* Rx Flow Control Enable */ +#define MAC_CFG1_LB BIT(8) /* Loopback mode */ +#define MAC_CFG1_SR BIT(31) /* Soft Reset */ #define MAC_CFG2_FDX BIT(0) #define MAC_CFG2_CRC_EN BIT(1) @@ -225,6 +215,56 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define MAC_CFG2_IF_1000 BIT(9) #define MAC_CFG2_IF_10_100 BIT(8) +#define FIFO_CFG0_WTM BIT(0) /* Watermark Module */ +#define FIFO_CFG0_RXS BIT(1) /* Rx System Module */ +#define FIFO_CFG0_RXF BIT(2) /* Rx Fabric Module */ +#define FIFO_CFG0_TXS BIT(3) /* Tx System Module */ +#define FIFO_CFG0_TXF BIT(4) /* Tx Fabric Module */ +#define FIFO_CFG0_ALL (FIFO_CFG0_WTM | FIFO_CFG0_RXS | FIFO_CFG0_RXF \ + | FIFO_CFG0_TXS | FIFO_CFG0_TXF) + +#define FIFO_CFG0_ENABLE_SHIFT 8 + +#define FIFO_CFG4_DE BIT(0) /* Drop Event */ +#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_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 */ +#define FIFO_CFG4_MC BIT(8) /* Multicast Packet */ +#define FIFO_CFG4_BC BIT(9) /* Broadcast Packet */ +#define FIFO_CFG4_DR BIT(10) /* Dribble */ +#define FIFO_CFG4_LE BIT(11) /* Long Event */ +#define FIFO_CFG4_CF BIT(12) /* Control Frame */ +#define FIFO_CFG4_PF BIT(13) /* Pause Frame */ +#define FIFO_CFG4_UO BIT(14) /* Unsupported Opcode */ +#define FIFO_CFG4_VT BIT(15) /* VLAN tag detected */ +#define FIFO_CFG4_FT BIT(16) /* Frame Truncated */ +#define FIFO_CFG4_UC BIT(17) /* Unicast Packet */ + +#define FIFO_CFG5_DE BIT(0) /* Drop Event */ +#define FIFO_CFG5_DV BIT(1) /* RX_DV Event */ +#define FIFO_CFG5_FC BIT(2) /* False Carrier */ +#define FIFO_CFG5_CE BIT(3) /* Code Error */ +#define FIFO_CFG5_LM BIT(4) /* Length Mismatch */ +#define FIFO_CFG5_LO BIT(5) /* Length Out of Range */ +#define FIFO_CFG5_OK BIT(6) /* Packet is OK */ +#define FIFO_CFG5_MC BIT(7) /* Multicast Packet */ +#define FIFO_CFG5_BC BIT(8) /* Broadcast Packet */ +#define FIFO_CFG5_DR BIT(9) /* Dribble */ +#define FIFO_CFG5_CF BIT(10) /* Control Frame */ +#define FIFO_CFG5_PF BIT(11) /* Pause Frame */ +#define FIFO_CFG5_UO BIT(12) /* Unsupported Opcode */ +#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 */ + #define AG71XX_INT_TX_PS BIT(0) #define AG71XX_INT_TX_UR BIT(1) #define AG71XX_INT_TX_BE BIT(3) @@ -241,33 +281,105 @@ static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) #define MII_CFG_CLK_DIV_14 5 #define MII_CFG_CLK_DIV_20 6 #define MII_CFG_CLK_DIV_28 7 +#define MII_CFG_RESET BIT(31) #define MII_CMD_WRITE 0x0 #define MII_CMD_READ 0x1 -#define MII_ADDR_S 8 +#define MII_ADDR_SHIFT 8 #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 FIFO_CFG5_BYTE_PER_CLK BIT(19) - -#define MII_CTRL_SPEED_S 4 -#define MII_CTRL_SPEED_M 3 +#define MII_CTRL_IF_MASK 3 +#define MII_CTRL_SPEED_SHIFT 4 +#define MII_CTRL_SPEED_MASK 3 #define MII_CTRL_SPEED_10 0 #define MII_CTRL_SPEED_100 1 #define MII_CTRL_SPEED_1000 2 +static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value) +{ + void __iomem *r; + + switch (reg) { + case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: + case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: + r = ag->mac_base + reg; + __raw_writel(value, r); + + /* flush write */ + (void) __raw_readl(r); + break; + default: + BUG(); + } +} + +static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) +{ + void __iomem *r; + u32 ret; + + switch (reg) { + case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: + case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: + r = ag->mac_base + reg; + ret = __raw_readl(r); + break; + default: + BUG(); + } + + return ret; +} + +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: + case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: + r = ag->mac_base + reg; + __raw_writel(__raw_readl(r) | mask, r); + + /* flush write */ + (void)__raw_readl(r); + break; + default: + BUG(); + } +} + +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: + case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: + r = ag->mac_base + reg; + __raw_writel(__raw_readl(r) & ~mask, r); + + /* flush write */ + (void) __raw_readl(r); + break; + default: + BUG(); + } +} + static inline void ag71xx_int_enable(struct ag71xx *ag, u32 ints) { ag71xx_sb(ag, AG71XX_REG_INT_ENABLE, ints); @@ -278,4 +390,65 @@ static inline void ag71xx_int_disable(struct ag71xx *ag, u32 ints) ag71xx_cb(ag, AG71XX_REG_INT_ENABLE, 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, + unsigned int mii_if) +{ + u32 t; + + t = ag71xx_mii_ctrl_rr(ag); + t &= ~(MII_CTRL_IF_MASK); + t |= (mii_if & MII_CTRL_IF_MASK); + ag71xx_mii_ctrl_wr(ag, t); +} + +static void inline ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, + unsigned int speed) +{ + u32 t; + + t = ag71xx_mii_ctrl_rr(ag); + t &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT); + t |= (speed & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT; + 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); +#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) +{ + return 0; +} +#endif + #endif /* _AG71XX_H */