Skip to content

Instantly share code, notes, and snippets.

@ysc3839
Created April 28, 2018 15:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ysc3839/d88242927c48f792fe2ac6dd8f1023a4 to your computer and use it in GitHub Desktop.
Save ysc3839/d88242927c48f792fe2ac6dd8f1023a4 to your computer and use it in GitHub Desktop.
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/if_ether.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/rt2880/surfboardint.h>
#if defined (CONFIG_RAETH_TSO)
#include <linux/tcp.h>
#include <net/ipv6.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <linux/in.h>
#include <linux/ppp_defs.h>
#include <linux/if_pppox.h>
#endif
#if defined (CONFIG_RAETH_LRO)
#include <linux/inet_lro.h>
#endif
#include <linux/delay.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
#include <linux/sched.h>
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
#include <asm/rt2880/rt_mmap.h>
#else
#include <linux/libata-compat.h>
#endif
#include "ra2882ethreg.h"
#include "raether.h"
#include "ra_mac.h"
#include "ra_ioctl.h"
#include "ra_rfrw.h"
#ifdef CONFIG_RAETH_NETLINK
#include "ra_netlink.h"
#endif
#if defined (CONFIG_RAETH_QOS)
#include "ra_qos.h"
#endif
#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
#include "../../../net/nat/hw_nat/ra_nat.h"
#endif
#if defined (TASKLET_WORKQUEUE_SW)
int init_schedule;
int working_schedule;
#endif
#ifdef CONFIG_RAETH_NAPI
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static int raeth_clean(struct napi_struct *napi, int budget);
#else
static int raeth_clean(struct net_device *dev, int *budget);
#endif
static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do);
#else
static int rt2880_eth_recv(struct net_device* dev);
#endif
#if !defined(CONFIG_RA_NAT_NONE)
/* bruce+
*/
extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
#endif
#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
/* Qwert+
*/
#include <asm/mipsregs.h>
extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
#endif /* CONFIG_RA_CLASSIFIER */
#if defined (CONFIG_RALINK_RT3052_MP2)
int32_t mcast_rx(struct sk_buff * skb);
int32_t mcast_tx(struct sk_buff * skb);
#endif
#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf)
{
/* TODO */
return 0;
}
#else
#ifdef RA_MTD_RW_BY_NUM
int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
#else
int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
#endif
#endif
#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
void setup_internal_gsw(void);
#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
void apll_xtal_enable(void);
#define REGBIT(x, n) (x << n)
#endif
#endif
/* gmac driver feature set config */
#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
#undef DELAY_INT
#else
#define DELAY_INT 1
#endif
//#define CONFIG_UNH_TEST
/* end of config */
#if defined (CONFIG_RAETH_JUMBOFRAME)
#define MAX_RX_LENGTH 4096
#else
#define MAX_RX_LENGTH 1536
#endif
struct net_device *dev_raether;
static int rx_dma_owner_idx;
static int rx_dma_owner_idx0;
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
static int rx_dma_owner_idx1;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
int rx_calc_idx1;
#endif
#endif
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
int rx_calc_idx0;
#endif
static int pending_recv;
static struct PDMA_rxdesc *rx_ring;
unsigned long tx_ring_full=0;
#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
unsigned short p0_rx_good_cnt = 0;
unsigned short p1_rx_good_cnt = 0;
unsigned short p2_rx_good_cnt = 0;
unsigned short p3_rx_good_cnt = 0;
unsigned short p4_rx_good_cnt = 0;
unsigned short p5_rx_good_cnt = 0;
unsigned short p6_rx_good_cnt = 0;
unsigned short p0_tx_good_cnt = 0;
unsigned short p1_tx_good_cnt = 0;
unsigned short p2_tx_good_cnt = 0;
unsigned short p3_tx_good_cnt = 0;
unsigned short p4_tx_good_cnt = 0;
unsigned short p5_tx_good_cnt = 0;
unsigned short p6_tx_good_cnt = 0;
unsigned short p0_rx_byte_cnt = 0;
unsigned short p1_rx_byte_cnt = 0;
unsigned short p2_rx_byte_cnt = 0;
unsigned short p3_rx_byte_cnt = 0;
unsigned short p4_rx_byte_cnt = 0;
unsigned short p5_rx_byte_cnt = 0;
unsigned short p6_rx_byte_cnt = 0;
unsigned short p0_tx_byte_cnt = 0;
unsigned short p1_tx_byte_cnt = 0;
unsigned short p2_tx_byte_cnt = 0;
unsigned short p3_tx_byte_cnt = 0;
unsigned short p4_tx_byte_cnt = 0;
unsigned short p5_tx_byte_cnt = 0;
unsigned short p6_tx_byte_cnt = 0;
#if defined(CONFIG_RALINK_MT7620)
unsigned short p7_rx_good_cnt = 0;
unsigned short p7_tx_good_cnt = 0;
unsigned short p7_rx_byte_cnt = 0;
unsigned short p7_tx_byte_cnt = 0;
#endif
#endif
#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
#include "ra_ethtool.h"
extern struct ethtool_ops ra_ethtool_ops;
#ifdef CONFIG_PSEUDO_SUPPORT
extern struct ethtool_ops ra_virt_ethtool_ops;
#endif // CONFIG_PSEUDO_SUPPORT //
#endif // (CONFIG_ETHTOOL //
#ifdef CONFIG_RALINK_VISTA_BASIC
int is_switch_175c = 1;
#endif
unsigned int M2Q_table[64] = {0};
EXPORT_SYMBOL(M2Q_table);
#if defined (CONFIG_RAETH_LRO)
unsigned int lan_ip;
struct lro_para_struct lro_para;
int lro_flush_needed;
extern char const *nvram_get(int index, char *name);
#endif
#define KSEG1 0xa0000000
#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
extern int fe_dma_init(struct net_device *dev);
extern int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no);
extern void ei_xmit_housekeeping(unsigned long unused);
extern inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no);
#if 0
void skb_dump(struct sk_buff* sk) {
unsigned int i;
printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n",
sk->dev?sk->dev->name:"ip stack",sk->len,sk->truesize,
skb_headroom(sk),skb_tailroom(sk));
//for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) {
for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) {
if((i % 20) == 0)
printk("\n");
if(i==(unsigned int)sk->data) printk("{");
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
if(i==(unsigned int)sk->transport_header) printk("#");
if(i==(unsigned int)sk->network_header) printk("|");
if(i==(unsigned int)sk->mac_header) printk("*");
#else
if(i==(unsigned int)sk->h.raw) printk("#");
if(i==(unsigned int)sk->nh.raw) printk("|");
if(i==(unsigned int)sk->mac.raw) printk("*");
#endif
printk("%02X-",*((unsigned char*)i));
if(i==(unsigned int)sk->tail) printk("}");
}
printk("\n");
}
#endif
#if defined (CONFIG_GIGAPHY) || defined (CONFIG_P5_MAC_TO_PHY_MODE) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
int isICPlusGigaPHY(int ge)
{
u32 phy_id0 = 0, phy_id1 = 0;
#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
if (ge == 2) {
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id1 = 0;
}
}
else
#endif
#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
{
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id1 = 0;
}
}
#endif
if ((phy_id0 == EV_ICPLUS_PHY_ID0) && ((phy_id1 & 0xfff0) == EV_ICPLUS_PHY_ID1))
return 1;
return 0;
}
int isMarvellGigaPHY(int ge)
{
u32 phy_id0 = 0, phy_id1 = 0;
#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
if (ge == 2) {
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id1 = 0;
}
}
else
#endif
#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
{
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id1 = 0;
}
}
#endif
;
if ((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1))
return 1;
return 0;
}
int isVtssGigaPHY(int ge)
{
u32 phy_id0 = 0, phy_id1 = 0;
#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
if (ge == 2) {
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id1 = 0;
}
}
else
#endif
#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
{
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id1 = 0;
}
}
#endif
;
if ((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1))
return 1;
return 0;
}
#endif
/*
* Set the hardware MAC address.
*/
static int ei_set_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if(netif_running(dev))
return -EBUSY;
ra2880MacAddressSet(addr->sa_data);
return 0;
}
#ifdef CONFIG_PSEUDO_SUPPORT
static int ei_set_mac2_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if(netif_running(dev))
return -EBUSY;
ra2880Mac2AddressSet(addr->sa_data);
return 0;
}
#endif
void set_fe_dma_glo_cfg(void)
{
int dma_glo_cfg=0;
#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
int fe_glo_cfg=0;
#endif
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_32DWORDS);
#elif defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS);
#else
dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_4DWORDS);
#endif
#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
dma_glo_cfg |= (RX_2B_OFFSET);
#endif
#if defined (CONFIG_32B_DESC)
dma_glo_cfg |= (DESC_32B_EN);
#endif
sysRegWrite(DMA_GLO_CFG, dma_glo_cfg);
#ifdef CONFIG_RAETH_QDMA
sysRegWrite(QDMA_GLO_CFG, dma_glo_cfg);
#endif
/* only the following chipset need to set it */
#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
//set 1us timer count in unit of clock cycle
fe_glo_cfg = sysRegRead(FE_GLO_CFG);
fe_glo_cfg &= ~(0xff << 8); //clear bit8-bit15
fe_glo_cfg |= (((get_surfboard_sysclk()/1000000)) << 8);
sysRegWrite(FE_GLO_CFG, fe_glo_cfg);
#endif
}
int forward_config(struct net_device *dev)
{
#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
/* RT5350: No GDMA, PSE, CDMA, PPE */
unsigned int sdmVal;
sdmVal = sysRegRead(SDM_CON);
#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
sdmVal |= 0x7<<16; // UDPCS, TCPCS, IPCS=1
#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
#if defined (CONFIG_RAETH_SPECIAL_TAG)
sdmVal |= 0x1<<20; // TCI_81XX
#endif // CONFIG_RAETH_SPECIAL_TAG //
sysRegWrite(SDM_CON, sdmVal);
#else //Non RT5350 chipset
unsigned int regVal, regCsg;
#ifdef CONFIG_PSEUDO_SUPPORT
unsigned int regVal2;
#endif
#ifdef CONFIG_RAETH_HW_VLAN_TX
#if defined(CONFIG_RALINK_MT7620)
/* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x430) = 0x00010000;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x434) = 0x00030002;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x438) = 0x00050004;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x43C) = 0x00070006;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x440) = 0x00090008;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x444) = 0x000b000a;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x448) = 0x000d000c;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x44C) = 0x000f000e;
#else
/*
* VLAN_IDX 0 = VLAN_ID 0
* .........
* VLAN_IDX 15 = VLAN ID 15
*
*/
/* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xa8) = 0x00010000;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xac) = 0x00030002;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb0) = 0x00050004;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb4) = 0x00070006;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb8) = 0x00090008;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xbc) = 0x000b000a;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc0) = 0x000d000c;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc4) = 0x000f000e;
#endif
#endif
regVal = sysRegRead(GDMA1_FWD_CFG);
regCsg = sysRegRead(CDMA_CSG_CFG);
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 = sysRegRead(GDMA2_FWD_CFG);
#endif
//set unicast/multicast/broadcast frame to cpu
#if defined (CONFIG_RALINK_MT7620)
/* GDMA1 frames destination port is port0 CPU*/
regVal &= ~0x7;
#else
regVal &= ~0xFFFF;
regVal |= GDMA1_FWD_PORT;
#endif
regCsg &= ~0x7;
#if defined (CONFIG_RAETH_SPECIAL_TAG)
regVal |= (1 << 24); //GDM1_TCI_81xx
#endif
#ifdef CONFIG_RAETH_HW_VLAN_TX
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
dev->features |= NETIF_F_HW_VLAN_TX;
#else
dev->features |= NETIF_F_HW_VLAN_CTAG_TX;
#endif
#endif
#ifdef CONFIG_RAETH_HW_VLAN_RX
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
dev->features |= NETIF_F_HW_VLAN_RX;
#else
dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
#endif
#endif
#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
//enable ipv4 header checksum check
regVal |= GDM1_ICS_EN;
regCsg |= ICS_GEN_EN;
//enable tcp checksum check
regVal |= GDM1_TCS_EN;
regCsg |= TCS_GEN_EN;
//enable udp checksum check
regVal |= GDM1_UCS_EN;
regCsg |= UCS_GEN_EN;
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 &= ~0xFFFF;
regVal2 |= GDMA2_FWD_PORT;
regVal2 |= GDM1_ICS_EN;
regVal2 |= GDM1_TCS_EN;
regVal2 |= GDM1_UCS_EN;
#endif
dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
//#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
// dev->vlan_features |= NETIF_F_IP_CSUM;
//#endif
#if defined(CONFIG_RALINK_MT7620)
#if defined (CONFIG_RAETH_TSO)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
}
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
}
#endif // CONFIG_RAETH_TSOV6 //
#else
#if defined (CONFIG_RAETH_TSO)
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
#endif // CONFIG_RAETH_TSOV6 //
#endif // CONFIG_RALINK_MT7620 //
#else // Checksum offload disabled
//disable ipv4 header checksum check
regVal &= ~GDM1_ICS_EN;
regCsg &= ~ICS_GEN_EN;
//disable tcp checksum check
regVal &= ~GDM1_TCS_EN;
regCsg &= ~TCS_GEN_EN;
//disable udp checksum check
regVal &= ~GDM1_UCS_EN;
regCsg &= ~UCS_GEN_EN;
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 &= ~GDM1_ICS_EN;
regVal2 &= ~GDM1_TCS_EN;
regVal2 &= ~GDM1_UCS_EN;
#endif
dev->features &= ~NETIF_F_IP_CSUM; /* disable checksum TCP/UDP over IPv4 */
#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
#ifdef CONFIG_RAETH_JUMBOFRAME
regVal |= GDM1_JMB_EN;
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 |= GDM1_JMB_EN;
#endif
#endif
sysRegWrite(GDMA1_FWD_CFG, regVal);
sysRegWrite(CDMA_CSG_CFG, regCsg);
#ifdef CONFIG_PSEUDO_SUPPORT
sysRegWrite(GDMA2_FWD_CFG, regVal2);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
dev->vlan_features = dev->features;
#endif
/*
* PSE_FQ_CFG register definition -
*
* Define max free queue page count in PSE. (31:24)
* RT2883/RT3883 - 0xff908000 (255 pages)
* RT3052 - 0x80504000 (128 pages)
* RT2880 - 0x80504000 (128 pages)
*
* In each page, there are 128 bytes in each page.
*
* 23:16 - free queue flow control release threshold
* 15:8 - free queue flow control assertion threshold
* 7:0 - free queue empty threshold
*
* The register affects QOS correctness in frame engine!
*/
#if defined(CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883)
sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_RT2883_PSE_FQ_CFG));
#elif defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
defined (CONFIG_RALINK_MT7628)
/*use default value*/
#else
sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_PSE_FQFC_CFG));
#endif
/*
*FE_RST_GLO register definition -
*Bit 0: PSE Rest
*Reset PSE after re-programming PSE_FQ_CFG.
*/
regVal = 0x1;
sysRegWrite(FE_RST_GL, regVal);
sysRegWrite(FE_RST_GL, 0); // update for RSTCTL issue
regCsg = sysRegRead(CDMA_CSG_CFG);
printk("CDMA_CSG_CFG = %0X\n",regCsg);
regVal = sysRegRead(GDMA1_FWD_CFG);
printk("GDMA1_FWD_CFG = %0X\n",regVal);
#ifdef CONFIG_PSEUDO_SUPPORT
regVal = sysRegRead(GDMA2_FWD_CFG);
printk("GDMA2_FWD_CFG = %0X\n",regVal);
#endif
#endif
return 1;
}
#ifdef CONFIG_RAETH_LRO
static int
rt_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph,
u64 *hdr_flags, void *priv)
{
struct iphdr *iph = NULL;
int vhdr_len = 0;
/*
* Make sure that this packet is Ethernet II, is not VLAN
* tagged, is IPv4, has a valid IP header, and is TCP.
*/
if (skb->protocol == 0x0081) {
vhdr_len = VLAN_HLEN;
}
iph = (struct iphdr *)(skb->data + vhdr_len);
if (iph->daddr != lro_para.lan_ip1) {
return -1;
}
if(iph->protocol != IPPROTO_TCP) {
return -1;
} else {
*iphdr = iph;
*tcph = skb->data + (iph->ihl << 2) + vhdr_len;
*hdr_flags = LRO_IPV4 | LRO_TCP;
lro_flush_needed = 1;
return 0;
}
}
#endif // CONFIG_RAETH_LRO //
#ifdef CONFIG_RAETH_NAPI
static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do)
#else
static int rt2880_eth_recv(struct net_device* dev)
#endif
{
struct sk_buff *skb, *rx_skb;
unsigned int length = 0;
unsigned long RxProcessed;
int bReschedule = 0;
END_DEVICE* ei_local = netdev_priv(dev);
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
int rx_ring_no=0;
#endif
#if defined (CONFIG_RAETH_SPECIAL_TAG)
struct vlan_ethhdr *veth=NULL;
#endif
#ifdef CONFIG_PSEUDO_SUPPORT
PSEUDO_ADAPTER *pAd;
#endif
RxProcessed = 0;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx0 = (rx_calc_idx0 + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
#endif
#if defined (CONFIG_32B_DESC)
#if defined (CONFIG_MIPS)
dma_cache_sync(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#else
dma_sync_single_for_cpu(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#endif
#endif
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx1 = (rx_calc_idx1 + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_RX_DESC;
#endif
#if defined (CONFIG_32B_DESC)
#if defined (CONFIG_MIPS)
dma_cache_sync(NULL, &ei_local->rx_ring1[rx_dma_owner_idx1], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#else
dma_sync_single_for_cpu(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#endif
#endif
#endif
for ( ; ; ) {
#ifdef CONFIG_RAETH_NAPI
if(*work_done >= work_to_do)
break;
(*work_done)++;
#else
if (RxProcessed++ > NUM_RX_MAX_PROCESS)
{
// need to reschedule rx handle
bReschedule = 1;
break;
}
#endif
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if (ei_local->rx_ring1[rx_dma_owner_idx1].rxd_info2.DDONE_bit == 1) {
rx_ring = ei_local->rx_ring1;
rx_dma_owner_idx = rx_dma_owner_idx1;
// printk("rx_dma_owner_idx1=%x\n",rx_dma_owner_idx1);
rx_ring_no=1;
} else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
rx_ring = ei_local->rx_ring0;
rx_dma_owner_idx = rx_dma_owner_idx0;
// printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0);
rx_ring_no=0;
} else {
break;
}
#else
if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
rx_ring = ei_local->rx_ring0;
rx_dma_owner_idx = rx_dma_owner_idx0;
} else {
break;
}
#endif
#if defined (CONFIG_32B_DESC)
prefetch(&rx_ring[(rx_dma_owner_idx + 1) % NUM_RX_DESC]);
#endif
/* skb processing */
length = rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0;
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if(rx_ring_no==1) {
rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx];
rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data;
} else {
rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
}
#else
rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
#endif
rx_skb->len = length;
#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
rx_skb->data += NET_IP_ALIGN;
#endif
rx_skb->tail = rx_skb->data + length;
#ifdef CONFIG_PSEUDO_SUPPORT
if(rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
if(ei_local->PseudoDev!=NULL) {
rx_skb->dev = ei_local->PseudoDev;
rx_skb->protocol = eth_type_trans(rx_skb,ei_local->PseudoDev);
}else {
printk("ERROR: PseudoDev is still not initialize but receive packet from GMAC2\n");
}
}else{
rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb,dev);
}
#else
rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb,dev);
#endif
#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
#if defined (CONFIG_PDMA_NEW)
if(rx_ring[rx_dma_owner_idx].rxd_info4.L4VLD) {
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
}else {
rx_skb->ip_summed = CHECKSUM_NONE;
}
#else
if(rx_ring[rx_dma_owner_idx].rxd_info4.IPFVLD_bit) {
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
}else {
rx_skb->ip_summed = CHECKSUM_NONE;
}
#endif
#else
rx_skb->ip_summed = CHECKSUM_NONE;
#endif
#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
/* Qwert+
*/
if(ra_classifier_hook_rx!= NULL)
{
#if defined(CONFIG_RALINK_EXTERNAL_TIMER)
ra_classifier_hook_rx(rx_skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF));
#else
ra_classifier_hook_rx(rx_skb, read_c0_count());
#endif
}
#endif /* CONFIG_RA_CLASSIFIER */
#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
if(ra_sw_nat_hook_rx != NULL) {
FOE_MAGIC_TAG(rx_skb)= FOE_MAGIC_GE;
*(uint32_t *)(FOE_INFO_START_ADDR(rx_skb)+2) = *(uint32_t *)&rx_ring[rx_dma_owner_idx].rxd_info4;
FOE_ALG(rx_skb) = 0;
}
#endif
/* We have to check the free memory size is big enough
* before pass the packet to cpu*/
#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
skb = skbmgr_dev_alloc_skb2k();
#else
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
skb = alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
#else
skb = __dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
#endif
#endif
if (unlikely(skb == NULL))
{
printk(KERN_ERR "skb not available...\n");
#ifdef CONFIG_PSEUDO_SUPPORT
if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
if (ei_local->PseudoDev != NULL) {
pAd = netdev_priv(ei_local->PseudoDev);
pAd->stat.rx_dropped++;
}
} else
#endif
ei_local->stat.rx_dropped++;
bReschedule = 1;
break;
}
#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
skb_reserve(skb, NET_IP_ALIGN);
#endif
#if defined (CONFIG_RAETH_SPECIAL_TAG)
// port0: 0x8100 => 0x8100 0001
// port1: 0x8101 => 0x8100 0002
// port2: 0x8102 => 0x8100 0003
// port3: 0x8103 => 0x8100 0004
// port4: 0x8104 => 0x8100 0005
// port5: 0x8105 => 0x8100 0006
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
veth = (struct vlan_ethhdr *)(rx_skb->mac_header);
#else
veth = (struct vlan_ethhdr *)(rx_skb->mac.raw);
#endif
/*donot check 0x81 due to MT7530 SPEC*/
//if((veth->h_vlan_proto & 0xFF) == 0x81)
{
veth->h_vlan_TCI = htons( (((veth->h_vlan_proto >> 8) & 0xF) + 1) );
rx_skb->protocol = veth->h_vlan_proto = htons(ETH_P_8021Q);
}
#endif
/* ra_sw_nat_hook_rx return 1 --> continue
* ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx
*/
#if !defined(CONFIG_RA_NAT_NONE)
if((ra_sw_nat_hook_rx == NULL) ||
(ra_sw_nat_hook_rx!= NULL && ra_sw_nat_hook_rx(rx_skb)))
#endif
{
#if defined (CONFIG_RALINK_RT3052_MP2)
if(mcast_rx(rx_skb)==0) {
kfree_skb(rx_skb);
}else
#endif
#if defined (CONFIG_RAETH_LRO)
if (rx_skb->ip_summed == CHECKSUM_UNNECESSARY) {
lro_receive_skb(&ei_local->lro_mgr, rx_skb, NULL);
//LroStatsUpdate(&ei_local->lro_mgr,0);
} else
#endif
#ifdef CONFIG_RAETH_NAPI
netif_receive_skb(rx_skb);
#else
#ifdef CONFIG_RAETH_HW_VLAN_RX
if(ei_local->vlgrp && rx_ring[rx_dma_owner_idx].rxd_info2.TAG) {
vlan_hwaccel_rx(rx_skb, ei_local->vlgrp, rx_ring[rx_dma_owner_idx].rxd_info3.VID);
} else {
netif_rx(rx_skb);
}
#else
#ifdef CONFIG_RAETH_CPU_LOOPBACK
skb_push(rx_skb,ETH_HLEN);
ei_start_xmit(rx_skb, dev, 1);
#else
netif_rx(rx_skb);
#endif
#endif
#endif
}
#ifdef CONFIG_PSEUDO_SUPPORT
if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
if (ei_local->PseudoDev != NULL) {
pAd = netdev_priv(ei_local->PseudoDev);
pAd->stat.rx_packets++;
pAd->stat.rx_bytes += length;
}
} else
#endif
{
ei_local->stat.rx_packets++;
ei_local->stat.rx_bytes += length;
}
#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = MAX_RX_LENGTH;
rx_ring[rx_dma_owner_idx].rxd_info2.LS0 = 0;
#endif
rx_ring[rx_dma_owner_idx].rxd_info2.DDONE_bit = 0;
rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
#ifdef CONFIG_32B_DESC
dma_cache_sync(NULL, &rx_ring[rx_dma_owner_idx], sizeof(struct PDMA_rxdesc), DMA_TO_DEVICE);
#endif
/* Move point to next RXD which wants to alloc*/
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if(rx_ring_no==0) {
sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_calc_idx0 = rx_dma_owner_idx;
#endif
}else {
sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx);
ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_calc_idx1 = rx_dma_owner_idx;
#endif
}
#else
sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_calc_idx0 = rx_dma_owner_idx;
#endif
#endif
/* Update to Next packet point that was received.
*/
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if(rx_ring_no==0) {
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
#endif
}else {
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx1 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_RX_DESC;
#endif
}
#else
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
#endif
#endif
} /* for */
#if defined (CONFIG_RAETH_LRO)
if (lro_flush_needed) {
//LroStatsUpdate(&ei_local->lro_mgr,1);
lro_flush_all(&ei_local->lro_mgr);
lro_flush_needed = 0;
}
#endif
return bReschedule;
}
///////////////////////////////////////////////////////////////////
/////
///// ra_get_stats - gather packet information for management plane
/////
///// Pass net_device_stats to the upper layer.
/////
/////
///// RETURNS: pointer to net_device_stats
///////////////////////////////////////////////////////////////////
struct net_device_stats *ra_get_stats(struct net_device *dev)
{
END_DEVICE *ei_local = netdev_priv(dev);
return &ei_local->stat;
}
#if defined (CONFIG_RT_3052_ESW)
void kill_sig_workq(struct work_struct *work)
{
struct file *fp;
char pid[8];
struct task_struct *p = NULL;
//read udhcpc pid from file, and send signal USR2,USR1 to get a new IP
fp = filp_open("/var/run/udhcpc.pid", O_RDONLY, 0);
if (IS_ERR(fp))
return;
if (fp->f_op && fp->f_op->read) {
if (fp->f_op->read(fp, pid, 8, &fp->f_pos) > 0) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
p = pid_task(find_get_pid(simple_strtoul(pid, NULL, 10)), PIDTYPE_PID);
#else
p = find_task_by_pid(simple_strtoul(pid, NULL, 10));
#endif
if (NULL != p) {
send_sig(SIGUSR2, p, 0);
send_sig(SIGUSR1, p, 0);
}
}
}
filp_close(fp, NULL);
}
#endif
///////////////////////////////////////////////////////////////////
/////
///// ra2880Recv - process the next incoming packet
/////
///// Handle one incoming packet. The packet is checked for errors and sent
///// to the upper layer.
/////
///// RETURNS: OK on success or ERROR.
///////////////////////////////////////////////////////////////////
#ifndef CONFIG_RAETH_NAPI
#if defined WORKQUEUE_BH || defined (TASKLET_WORKQUEUE_SW)
void ei_receive_workq(struct work_struct *work)
#else
void ei_receive(unsigned long unused) // device structure
#endif // WORKQUEUE_BH //
{
struct net_device *dev = dev_raether;
END_DEVICE *ei_local = netdev_priv(dev);
unsigned long reg_int_mask=0;
int bReschedule=0;
if(tx_ring_full==0){
bReschedule = rt2880_eth_recv(dev);
if(bReschedule)
{
#ifdef WORKQUEUE_BH
schedule_work(&ei_local->rx_wq);
#else
#if defined (TASKLET_WORKQUEUE_SW)
if (working_schedule == 1)
schedule_work(&ei_local->rx_wq);
else
#endif
tasklet_hi_schedule(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
}else{
reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
#if defined(DELAY_INT)
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
#else
sysRegWrite(RAETH_FE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1));
#endif
#ifdef CONFIG_RAETH_QDMA
reg_int_mask=sysRegRead(QFE_INT_ENABLE);
#if defined(DELAY_INT)
sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
#else
sysRegWrite(QFE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1));
#endif
#endif
}
}else{
#ifdef WORKQUEUE_BH
schedule_work(&ei_local->rx_wq);
#else
#if defined (TASKLET_WORKQUEUE_SW)
if (working_schedule == 1)
schedule_work(&ei_local->rx_wq);
else
#endif
tasklet_schedule(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
}
}
#endif
#ifdef CONFIG_RAETH_NAPI
static int
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
raeth_clean(struct napi_struct *napi, int budget)
#else
raeth_clean(struct net_device *netdev, int *budget)
#endif
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
struct net_device *netdev=dev_raether;
int work_to_do = budget;
#else
int work_to_do = min(*budget, netdev->quota);
#endif
END_DEVICE *ei_local =netdev_priv(netdev);
int work_done = 0;
unsigned long reg_int_mask=0;
ei_xmit_housekeeping(0);
rt2880_eth_recv(netdev, &work_done, work_to_do);
/* this could control when to re-enable interrupt, 0-> mean never enable interrupt*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
*budget -= work_done;
netdev->quota -= work_done;
#endif
/* if no Tx and not enough Rx work done, exit the polling mode */
if(( (work_done < work_to_do)) || !netif_running(netdev)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
napi_complete(&ei_local->napi);
#else
netif_rx_complete(netdev);
#endif
atomic_dec_and_test(&ei_local->irq_sem);
sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL); // ack all fe interrupts
reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
#ifdef DELAY_INT
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask |RAETH_FE_INT_DLY_INIT); // init delay interrupt only
#else
sysRegWrite(RAETH_FE_INT_ENABLE,reg_int_mask | RAETH_FE_INT_SETTING);
#endif
#ifdef CONFIG_RAETH_QDMA
sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
reg_int_mask=sysRegRead(QFE_INT_ENABLE);
#ifdef DELAY_INT
sysRegWrite(QFE_INT_ENABLE, reg_int_mask |QFE_INT_DLY_INIT); // init delay interrupt only
#else
sysRegWrite(QFE_INT_ENABLE,reg_int_mask | (RX_DONE_INT0 | RX_DONE_INT1 | RLS_DONE_INT));
#endif
#endif // CONFIG_RAETH_QDMA //
return 0;
}
return 1;
}
#endif
void gsw_delay_setting(void)
{
#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
END_DEVICE *ei_local = netdev_priv(dev_raether);
int reg_int_val = 0;
int link_speed = 0;
reg_int_val = sysRegRead(FE_INT_STATUS2);
if( reg_int_val & BIT(25))
{
if(sysRegRead(RALINK_ETH_SW_BASE+0x0208) & 0x1) // link up
{
link_speed = (sysRegRead(RALINK_ETH_SW_BASE+0x0208)>>2 & 0x3);
if(link_speed == 1)
{
// delay setting for 100M
if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
mii_mgr_write(31, 0x7b00, 8);
printk("MT7621 GE2 link rate to 100M\n");
} else
{
//delay setting for 10/1000M
if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
mii_mgr_write(31, 0x7b00, 0x102);
printk("MT7621 GE2 link rate to 10M/1G\n");
}
schedule_work(&ei_local->kill_sig_wq);
}
}
sysRegWrite(FE_INT_STATUS2, reg_int_val);
#endif
}
/**
* ei_interrupt - handle controler interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
static irqreturn_t ei_interrupt(int irq, void *dev_id)
#else
static irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
#endif
{
#if !defined(CONFIG_RAETH_NAPI)
unsigned long reg_int_val;
unsigned long reg_int_mask=0;
unsigned int recv = 0;
unsigned int transmit __maybe_unused = 0;
unsigned long flags;
#endif
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
//Qwert
/*
unsigned long old,cur,dcycle;
static int cnt = 0;
static unsigned long max_dcycle = 0,tcycle = 0;
old = read_c0_count();
*/
if (dev == NULL)
{
printk (KERN_ERR "net_interrupt(): irq %x for unknown device.\n", IRQ_ENET0);
return IRQ_NONE;
}
#ifdef CONFIG_RAETH_NAPI
gsw_delay_setting();
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
if(napi_schedule_prep(&ei_local->napi)) {
#else
if(netif_rx_schedule_prep(dev)) {
#endif
atomic_inc(&ei_local->irq_sem);
sysRegWrite(RAETH_FE_INT_ENABLE, 0);
#ifdef CONFIG_RAETH_QDMA
sysRegWrite(QFE_INT_ENABLE, 0);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
__napi_schedule(&ei_local->napi);
#else
__netif_rx_schedule(dev);
#endif
}
#else
spin_lock_irqsave(&(ei_local->page_lock), flags);
reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
#ifdef CONFIG_RAETH_QDMA
reg_int_val |= sysRegRead(QFE_INT_STATUS);
#endif
#if defined (DELAY_INT)
if((reg_int_val & RX_DLY_INT))
recv = 1;
if (reg_int_val & RAETH_TX_DLY_INT)
transmit = 1;
#else
if((reg_int_val & RX_DONE_INT0))
recv = 1;
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if((reg_int_val & RX_DONE_INT1))
recv = 1;
#endif
if (reg_int_val & RAETH_TX_DONE_INT0)
transmit |= RAETH_TX_DONE_INT0;
#if defined (CONFIG_RAETH_QOS)
if (reg_int_val & TX_DONE_INT1)
transmit |= TX_DONE_INT1;
if (reg_int_val & TX_DONE_INT2)
transmit |= TX_DONE_INT2;
if (reg_int_val & TX_DONE_INT3)
transmit |= TX_DONE_INT3;
#endif //CONFIG_RAETH_QOS
#endif //DELAY_INT
#if defined (DELAY_INT)
sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_DLY_INIT);
#else
sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL);
#endif
#ifdef CONFIG_RAETH_QDMA
#if defined (DELAY_INT)
sysRegWrite(QFE_INT_STATUS, QFE_INT_DLY_INIT);
#else
sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
#endif
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
if(transmit)
ei_xmit_housekeeping(0);
#else
ei_xmit_housekeeping(0);
#endif
if (((recv == 1) || (pending_recv ==1)) && (tx_ring_full==0))
{
reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
#if defined (DELAY_INT)
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
#else
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1));
#endif //DELAY_INT
#ifdef CONFIG_RAETH_QDMA
reg_int_mask = sysRegRead(QFE_INT_ENABLE);
#if defined (DELAY_INT)
sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
#else
sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1));
#endif //DELAY_INT
#endif
pending_recv=0;
#ifdef WORKQUEUE_BH
schedule_work(&ei_local->rx_wq);
#else
#if defined (TASKLET_WORKQUEUE_SW)
if (working_schedule == 1)
schedule_work(&ei_local->rx_wq);
else
#endif
tasklet_hi_schedule(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
}
else if (recv == 1 && tx_ring_full==1)
{
pending_recv=1;
}
else if((recv == 0) && (transmit == 0))
{
gsw_delay_setting();
}
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
#endif
return IRQ_HANDLED;
}
#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \
defined (CONFIG_RALINK_MT7620)|| defined (CONFIG_RALINK_MT7621)
static void esw_link_status_changed(int port_no, void *dev_id)
{
unsigned int reg_val;
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined (CONFIG_RALINK_MT7620)
reg_val = *((volatile u32 *)(RALINK_ETH_SW_BASE+ 0x3008 + (port_no*0x100)));
#elif defined (CONFIG_RALINK_MT7621)
mii_mgr_read(31, (0x3008 + (port_no*0x100)), &reg_val);
#endif
if(reg_val & 0x1) {
printk("ESW: Link Status Changed - Port%d Link UP\n", port_no);
#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(port_no, 31, 0x52b5);
mii_mgr_write(port_no, 16, 0xb780);
mii_mgr_write(port_no, 17, 0x00e0);
mii_mgr_write(port_no, 16, 0x9780);
#endif
#if defined (CONFIG_WAN_AT_P0)
if(port_no==0) {
schedule_work(&ei_local->kill_sig_wq);
}
#elif defined (CONFIG_WAN_AT_P4)
if(port_no==4) {
schedule_work(&ei_local->kill_sig_wq);
}
#endif
} else {
printk("ESW: Link Status Changed - Port%d Link Down\n", port_no);
#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(port_no, 31, 0x52b5);
mii_mgr_write(port_no, 16, 0xb780);
mii_mgr_write(port_no, 17, 0x0000);
mii_mgr_write(port_no, 16, 0x9780);
#endif
}
}
#endif
#if defined (CONFIG_RT_3052_ESW) && ! defined(CONFIG_RALINK_MT7621)
static irqreturn_t esw_interrupt(int irq, void *dev_id)
{
unsigned long flags;
unsigned long reg_int_val;
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
unsigned long acl_int_val;
unsigned long mib_int_val;
#else
static unsigned long stat;
unsigned long stat_curr;
#endif
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
spin_lock_irqsave(&(ei_local->page_lock), flags);
reg_int_val = (*((volatile u32 *)(ESW_ISR))); //Interrupt Status Register
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
if (reg_int_val & P5_LINK_CH) {
esw_link_status_changed(5, dev_id);
}
if (reg_int_val & P4_LINK_CH) {
esw_link_status_changed(4, dev_id);
}
if (reg_int_val & P3_LINK_CH) {
esw_link_status_changed(3, dev_id);
}
if (reg_int_val & P2_LINK_CH) {
esw_link_status_changed(2, dev_id);
}
if (reg_int_val & P1_LINK_CH) {
esw_link_status_changed(1, dev_id);
}
if (reg_int_val & P0_LINK_CH) {
esw_link_status_changed(0, dev_id);
}
if (reg_int_val & ACL_INT) {
acl_int_val = sysRegRead(ESW_AISR);
sysRegWrite(ESW_AISR, acl_int_val);
}
if (reg_int_val & MIB_INT) {
mib_int_val = sysRegRead(ESW_P0_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P0_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p0_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p0_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p0_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p0_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P1_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P1_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p1_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p1_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p1_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p1_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P2_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P2_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p2_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p2_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p2_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p2_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P3_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P3_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p3_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p3_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p3_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p3_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P4_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P4_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p4_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p4_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p4_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p4_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P5_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P5_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p5_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p5_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p5_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p5_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P6_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P6_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p6_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p6_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p6_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p6_tx_byte_cnt ++;
}
#if defined (CONFIG_RALINK_MT7620)
mib_int_val = sysRegRead(ESW_P7_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P7_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p7_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p7_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p7_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p7_tx_byte_cnt ++;
}
#endif
}
#else // not RT6855
if (reg_int_val & PORT_ST_CHG) {
printk("RT305x_ESW: Link Status Changed\n");
stat_curr = *((volatile u32 *)(RALINK_ETH_SW_BASE+0x80));
#ifdef CONFIG_WAN_AT_P0
//link down --> link up : send signal to user application
//link up --> link down : ignore
if ((stat & (1<<25)) || !(stat_curr & (1<<25)))
#else
if ((stat & (1<<29)) || !(stat_curr & (1<<29)))
#endif
goto out;
schedule_work(&ei_local->kill_sig_wq);
out:
stat = stat_curr;
}
#endif // defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)//
sysRegWrite(ESW_ISR, reg_int_val);
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
return IRQ_HANDLED;
}
#elif defined (CONFIG_RT_3052_ESW) && defined(CONFIG_RALINK_MT7621)
static irqreturn_t esw_interrupt(int irq, void *dev_id)
{
unsigned long flags;
unsigned int reg_int_val;
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
spin_lock_irqsave(&(ei_local->page_lock), flags);
mii_mgr_read(31, 0x700c, &reg_int_val);
if (reg_int_val & P4_LINK_CH) {
esw_link_status_changed(4, dev_id);
}
if (reg_int_val & P3_LINK_CH) {
esw_link_status_changed(3, dev_id);
}
if (reg_int_val & P2_LINK_CH) {
esw_link_status_changed(2, dev_id);
}
if (reg_int_val & P1_LINK_CH) {
esw_link_status_changed(1, dev_id);
}
if (reg_int_val & P0_LINK_CH) {
esw_link_status_changed(0, dev_id);
}
mii_mgr_write(31, 0x700c, 0x1f); //ack switch link change
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
return IRQ_HANDLED;
}
#endif
static int ei_start_xmit_fake(struct sk_buff* skb, struct net_device *dev)
{
return ei_start_xmit(skb, dev, 1);
}
#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
void dump_phy_reg(int port_no, int from, int to, int is_local)
{
u32 i=0;
u32 temp=0;
if(is_local==0) {
printk("Global Register\n");
printk("===============");
mii_mgr_write(0, 31, 0); //select global register
for(i=from;i<=to;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
} else {
mii_mgr_write(0, 31, 0x8000); //select local register
printk("\n\nLocal Register Port %d\n",port_no);
printk("===============");
for(i=from;i<=to;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
}
printk("\n");
}
#else
void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no)
{
u32 i=0;
u32 temp=0;
u32 r31=0;
if(is_local==0) {
printk("\n\nGlobal Register Page %d\n",page_no);
printk("===============");
r31 |= 0 << 15; //global
r31 |= ((page_no&0x7) << 12); //page no
mii_mgr_write(port_no, 31, r31); //select global page x
for(i=16;i<32;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
}else {
printk("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
printk("===============");
r31 |= 1 << 15; //local
r31 |= ((page_no&0x7) << 12); //page no
mii_mgr_write(port_no, 31, r31); //select local page x
for(i=16;i<32;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
}
printk("\n");
}
#endif
int ei_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
#if defined(CONFIG_RT_3052_ESW) || defined(CONFIG_RAETH_QDMA)
esw_reg reg;
#endif
#if defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628)
esw_rate ratelimit;
#endif
#if defined(CONFIG_RT_3052_ESW)
unsigned int offset = 0;
unsigned int value = 0;
#endif
ra_mii_ioctl_data mii;
switch (cmd) {
#if defined(CONFIG_RAETH_QDMA)
#define _HQOS_REG(x) (*((volatile u32 *)(RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + x)))
case RAETH_QDMA_REG_READ:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_HQOS_MAX)
return -EINVAL;
reg.val = _HQOS_REG(reg.off);
//printk("read reg off:%x val:%x\n", reg.off, reg.val);
copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
break;
case RAETH_QDMA_REG_WRITE:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_HQOS_MAX)
return -EINVAL;
_HQOS_REG(reg.off) = reg.val;
//printk("write reg off:%x val:%x\n", reg.off, reg.val);
break;
case RAETH_QDMA_READ_CPU_CLK:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
reg.val = get_surfboard_sysclk();
//printk("read reg off:%x val:%x\n", reg.off, reg.val);
copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
break;
case RAETH_QDMA_QUEUE_MAPPING:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
M2Q_table[reg.off] = reg.val;
//printk(" M2Q_table[%d] is %d.\n", reg.off, M2Q_table[reg.off]);
break;
#endif
case RAETH_MII_READ:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
break;
case RAETH_MII_WRITE:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
break;
#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT8590)
case RAETH_MII_READ_CL45:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
mii_mgr_read_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, &mii.val_out);
copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
break;
case RAETH_MII_WRITE_CL45:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
mii_mgr_write_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, mii.val_in);
break;
#endif
#if defined(CONFIG_RT_3052_ESW)
#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
case RAETH_ESW_REG_READ:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_ESW_MAX)
return -EINVAL;
reg.val = _ESW_REG(reg.off);
//printk("read reg off:%x val:%x\n", reg.off, reg.val);
copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
break;
case RAETH_ESW_REG_WRITE:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_ESW_MAX)
return -EINVAL;
_ESW_REG(reg.off) = reg.val;
//printk("write reg off:%x val:%x\n", reg.off, reg.val);
break;
case RAETH_ESW_PHY_DUMP:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
if (reg.val ==32 ) {//dump all phy register
/* Global Register 0~31
* Local Register 0~31
*/
dump_phy_reg(0, 0, 31, 0); //dump global register
for(offset=0;offset<5;offset++) {
dump_phy_reg(offset, 0, 31, 1); //dump local register
}
} else {
dump_phy_reg(reg.val, 0, 31, 0); //dump global register
dump_phy_reg(reg.val, 0, 31, 1); //dump local register
}
#else
/* SPEC defined Register 0~15
* Global Register 16~31 for each page
* Local Register 16~31 for each page
*/
printk("SPEC defined Register");
if (reg.val ==32 ) {//dump all phy register
int i = 0;
for(i=0; i<5; i++){
printk("\n[Port %d]===============",i);
for(offset=0;offset<16;offset++) {
if(offset%8==0) {
printk("\n");
}
mii_mgr_read(i,offset, &value);
printk("%02d: %04X ",offset, value);
}
}
}
else{
printk("\n[Port %d]===============",reg.val);
for(offset=0;offset<16;offset++) {
if(offset%8==0) {
printk("\n");
}
mii_mgr_read(reg.val,offset, &value);
printk("%02d: %04X ",offset, value);
}
}
#if defined (CONFIG_RALINK_MT7628)
for(offset=0;offset<7;offset++) { //global register page 0~6
#else
for(offset=0;offset<5;offset++) { //global register page 0~4
#endif
if(reg.val == 32) //dump all phy register
dump_phy_reg(0, 16, 31, 0, offset);
else
dump_phy_reg(reg.val, 16, 31, 0, offset);
}
if (reg.val == 32) {//dump all phy register
#if !defined (CONFIG_RAETH_HAS_PORT4)
for(offset=0;offset<5;offset++) { //local register port 0-port4
#else
for(offset=0;offset<4;offset++) { //local register port 0-port3
#endif
dump_phy_reg(offset, 16, 31, 1, 0); //dump local page 0
dump_phy_reg(offset, 16, 31, 1, 1); //dump local page 1
dump_phy_reg(offset, 16, 31, 1, 2); //dump local page 2
dump_phy_reg(offset, 16, 31, 1, 3); //dump local page 3
}
}else {
dump_phy_reg(reg.val, 16, 31, 1, 0); //dump local page 0
dump_phy_reg(reg.val, 16, 31, 1, 1); //dump local page 1
dump_phy_reg(reg.val, 16, 31, 1, 2); //dump local page 2
dump_phy_reg(reg.val, 16, 31, 1, 3); //dump local page 3
}
#endif
break;
#if defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
case RAETH_ESW_INGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
offset = 0x11c + (4 * (ratelimit.port / 2));
value = _ESW_REG(offset);
if((ratelimit.port % 2) == 0)
{
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 14);
value |= (0x07 << 10);
value |= ratelimit.bw;
}
}
else if((ratelimit.port % 2) == 1)
{
value &= 0x0000ffff;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 30);
value |= (0x07 << 26);
value |= (ratelimit.bw << 16);
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
_ESW_REG(offset) = value;
break;
case RAETH_ESW_EGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
offset = 0x140 + (4 * (ratelimit.port / 2));
value = _ESW_REG(offset);
if((ratelimit.port % 2) == 0)
{
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 12);
value |= (0x03 << 10);
value |= ratelimit.bw;
}
}
else if((ratelimit.port % 2) == 1)
{
value &= 0x0000ffff;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 28);
value |= (0x03 << 26);
value |= (ratelimit.bw << 16);
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
_ESW_REG(offset) = value;
break;
#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)
#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
case RAETH_ESW_INGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
#if defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7621)
offset = 0x1800 + (0x100 * ratelimit.port);
#else
offset = 0x1080 + (0x100 * ratelimit.port);
#endif
value = _ESW_REG(offset);
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 15);
if (ratelimit.bw < 100)
{
value |= (0x0 << 8);
value |= ratelimit.bw;
}else if(ratelimit.bw < 1000)
{
value |= (0x1 << 8);
value |= ratelimit.bw/10;
}else if(ratelimit.bw < 10000)
{
value |= (0x2 << 8);
value |= ratelimit.bw/100;
}else if(ratelimit.bw < 100000)
{
value |= (0x3 << 8);
value |= ratelimit.bw/1000;
}else
{
value |= (0x4 << 8);
value |= ratelimit.bw/10000;
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
#ifndef CONFIG_RALINK_MT7621
_ESW_REG(offset) = value;
#else
mii_mgr_write(0x1f, offset, value);
#endif
break;
case RAETH_ESW_EGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
offset = 0x1040 + (0x100 * ratelimit.port);
value = _ESW_REG(offset);
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 15);
if (ratelimit.bw < 100)
{
value |= (0x0 << 8);
value |= ratelimit.bw;
}else if(ratelimit.bw < 1000)
{
value |= (0x1 << 8);
value |= ratelimit.bw/10;
}else if(ratelimit.bw < 10000)
{
value |= (0x2 << 8);
value |= ratelimit.bw/100;
}else if(ratelimit.bw < 100000)
{
value |= (0x3 << 8);
value |= ratelimit.bw/1000;
}else
{
value |= (0x4 << 8);
value |= ratelimit.bw/10000;
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
#ifndef CONFIG_RALINK_MT7621
_ESW_REG(offset) = value;
#else
mii_mgr_write(0x1f, offset, value);
#endif
break;
#endif
#endif // CONFIG_RT_3052_ESW
default:
return -EOPNOTSUPP;
}
return 0;
}
/*
* Set new MTU size
* Change the mtu of Raeth Ethernet Device
*/
static int ei_change_mtu(struct net_device *dev, int new_mtu)
{
END_DEVICE *ei_local = netdev_priv(dev); // get priv ei_local pointer from net_dev structure
if ( ei_local == NULL ) {
printk(KERN_EMERG "%s: ei_change_mtu passed a non-existent private pointer from net_dev!\n", dev->name);
return -ENXIO;
}
if ( (new_mtu > 4096) || (new_mtu < 64)) {
return -EINVAL;
}
#ifndef CONFIG_RAETH_JUMBOFRAME
if ( new_mtu > 1500 ) {
return -EINVAL;
}
#endif
dev->mtu = new_mtu;
return 0;
}
#ifdef CONFIG_RAETH_HW_VLAN_RX
static void ei_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
END_DEVICE *ei_local = netdev_priv(dev);
ei_local->vlgrp = grp;
/* enable HW VLAN RX */
sysRegWrite(CDMP_EG_CTRL, 1);
}
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static const struct net_device_ops ei_netdev_ops = {
.ndo_init = rather_probe,
.ndo_open = ei_open,
.ndo_stop = ei_close,
.ndo_start_xmit = ei_start_xmit_fake,
.ndo_get_stats = ra_get_stats,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = ei_change_mtu,
.ndo_do_ioctl = ei_ioctl,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_RAETH_HW_VLAN_RX
.ndo_vlan_rx_register = ei_vlan_rx_register,
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = raeth_clean,
#endif
// .ndo_tx_timeout = ei_tx_timeout,
};
#endif
void ra2880_setup_dev_fptable(struct net_device *dev)
{
RAETH_PRINT(__FUNCTION__ "is called!\n");
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
dev->netdev_ops = &ei_netdev_ops;
#else
dev->open = ei_open;
dev->stop = ei_close;
dev->hard_start_xmit = ei_start_xmit_fake;
dev->get_stats = ra_get_stats;
dev->set_mac_address = ei_set_mac_addr;
dev->change_mtu = ei_change_mtu;
dev->mtu = 1500;
dev->do_ioctl = ei_ioctl;
// dev->tx_timeout = ei_tx_timeout;
#ifdef CONFIG_RAETH_NAPI
dev->poll = &raeth_clean;
#if defined (CONFIG_RAETH_ROUTER)
dev->weight = 32;
#elif defined (CONFIG_RT_3052_ESW)
dev->weight = 32;
#else
dev->weight = 128;
#endif
#endif
#endif
#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
dev->ethtool_ops = &ra_ethtool_ops;
#endif
#define TX_TIMEOUT (5*HZ)
dev->watchdog_timeo = TX_TIMEOUT;
}
/* reset frame engine */
void fe_reset(void)
{
#if defined (CONFIG_RALINK_RT6855A)
/* FIXME */
#else
u32 val;
val = sysRegRead(RSTCTRL);
// RT5350 need to reset ESW and FE at the same to avoid PDMA panic //
#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
val = val | RALINK_FE_RST | RALINK_ESW_RST ;
#else
val = val | RALINK_FE_RST;
#endif
sysRegWrite(RSTCTRL, val);
#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628)
val = val & ~(RALINK_FE_RST | RALINK_ESW_RST);
#else
val = val & ~(RALINK_FE_RST);
#endif
sysRegWrite(RSTCTRL, val);
#endif
}
/* set TRGMII */
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
void trgmii_set_7621(void)
{
u32 val = 0;
u32 val_0 = 0;
val = sysRegRead(RSTCTRL);
// MT7621 need to reset GMAC and FE first //
val = val | RALINK_FE_RST | RALINK_ETH_RST ;
sysRegWrite(RSTCTRL, val);
//set TRGMII clock//
val_0 = sysRegRead(CLK_CFG_0);
val_0 &= 0xffffff9f;
val_0 |= (0x1 << 5);
sysRegWrite(CLK_CFG_0, val_0);
mdelay(1);
val_0 = sysRegRead(CLK_CFG_0);
printk("set CLK_CFG_0 = 0x%x!!!!!!!!!!!!!!!!!!1\n",val_0);
val = val & ~(RALINK_FE_RST | RALINK_ETH_RST);
sysRegWrite(RSTCTRL, val);
}
void trgmii_set_7530(void)
{
// set MT7530 //
#if 0
mii_mgr_write(31, 103, 0x0020);
//disable EEE
mii_mgr_write(0, 0x16, 0);
mii_mgr_write(1, 0x16, 0);
mii_mgr_write(2, 0x16, 0);
mii_mgr_write(3, 0x16, 0);
mii_mgr_write(4, 0x16, 0);
//PLL reset for E2
mii_mgr_write(31, 104, 0x0608);
mii_mgr_write(31, 104, 0x2608);
mii_mgr_write(31, 0x7808, 0x0);
mdelay(1);
mii_mgr_write(31, 0x7804, 0x01017e8f);
mdelay(1);
mii_mgr_write(31, 0x7808, 0x1);
mdelay(1);
#endif
#if 1
//CL45 command
//PLL to 150Mhz
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x404);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x0780);//40Mhz XTAL for 150Mhz CLK
//mii_mgr_write(0, 14, 0x0C00);//ori
mdelay(1);
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x409);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x57);
mdelay(1);
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x40a);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x57);
//PLL BIAS en
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x403);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x1800);
mdelay(1);
//BIAS LPF en
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x403);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x1c00);
//sys PLL en
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x401);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0xc020);
//LCDDDS PWDS
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x406);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0xa030);
mdelay(1);
//GSW_2X_CLK
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x410);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x0003);
//enable P6
mii_mgr_write(31, 0x3600, 0x5e33b);
//enable TRGMII
mii_mgr_write(31, 0x7830, 0x1);
#endif
}
#endif
void ei_reset_task(struct work_struct *work)
{
struct net_device *dev = dev_raether;
ei_close(dev);
ei_open(dev);
return;
}
void ei_tx_timeout(struct net_device *dev)
{
END_DEVICE *ei_local = netdev_priv(dev);
schedule_work(&ei_local->reset_task);
}
void setup_statistics(END_DEVICE* ei_local)
{
ei_local->stat.tx_packets = 0;
ei_local->stat.tx_bytes = 0;
ei_local->stat.tx_dropped = 0;
ei_local->stat.tx_errors = 0;
ei_local->stat.tx_aborted_errors= 0;
ei_local->stat.tx_carrier_errors= 0;
ei_local->stat.tx_fifo_errors = 0;
ei_local->stat.tx_heartbeat_errors = 0;
ei_local->stat.tx_window_errors = 0;
ei_local->stat.rx_packets = 0;
ei_local->stat.rx_bytes = 0;
ei_local->stat.rx_dropped = 0;
ei_local->stat.rx_errors = 0;
ei_local->stat.rx_length_errors = 0;
ei_local->stat.rx_over_errors = 0;
ei_local->stat.rx_crc_errors = 0;
ei_local->stat.rx_frame_errors = 0;
ei_local->stat.rx_fifo_errors = 0;
ei_local->stat.rx_missed_errors = 0;
ei_local->stat.collisions = 0;
#if defined (CONFIG_RAETH_QOS)
ei_local->tx3_full = 0;
ei_local->tx2_full = 0;
ei_local->tx1_full = 0;
ei_local->tx0_full = 0;
#else
ei_local->tx_full = 0;
#endif
#ifdef CONFIG_RAETH_NAPI
atomic_set(&ei_local->irq_sem, 1);
#endif
}
/**
* rather_probe - pick up ethernet port at boot time
* @dev: network device to probe
*
* This routine probe the ethernet port at boot time.
*
*
*/
int __init rather_probe(struct net_device *dev)
{
int i;
END_DEVICE *ei_local = netdev_priv(dev);
struct sockaddr addr;
unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
fe_reset();
//Get mac0 address from flash
#ifdef RA_MTD_RW_BY_NUM
i = ra_mtd_read(2, GMAC0_OFFSET, 6, addr.sa_data);
#else
i = ra_mtd_read_nm("Factory", GMAC0_OFFSET, 6, addr.sa_data);
#endif
//If reading mtd failed or mac0 is empty, generate a mac address
if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) ||
(memcmp(addr.sa_data, zero2, 6) == 0)) {
unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
net_srandom(jiffies);
memcpy(addr.sa_data, mac_addr01234, 5);
addr.sa_data[5] = net_random()&0xFF;
}
#ifdef CONFIG_RAETH_NAPI
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
netif_napi_add(dev, &ei_local->napi, raeth_clean, 128);
#endif
#endif
ei_set_mac_addr(dev, &addr);
spin_lock_init(&ei_local->page_lock);
ether_setup(dev);
#ifdef CONFIG_RAETH_LRO
ei_local->lro_mgr.dev = dev;
memset(&ei_local->lro_mgr.stats, 0, sizeof(ei_local->lro_mgr.stats));
ei_local->lro_mgr.features = LRO_F_NAPI;
ei_local->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
ei_local->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
ei_local->lro_mgr.max_desc = ARRAY_SIZE(ei_local->lro_arr);
ei_local->lro_mgr.max_aggr = 64;
ei_local->lro_mgr.frag_align_pad = 0;
ei_local->lro_mgr.lro_arr = ei_local->lro_arr;
ei_local->lro_mgr.get_skb_header = rt_get_skb_header;
#endif
setup_statistics(ei_local);
return 0;
}
#ifdef CONFIG_PSEUDO_SUPPORT
int VirtualIF_ioctl(struct net_device * net_dev,
struct ifreq * ifr, int cmd)
{
ra_mii_ioctl_data mii;
switch (cmd) {
case RAETH_MII_READ:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
break;
case RAETH_MII_WRITE:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
struct net_device_stats *VirtualIF_get_stats(struct net_device *dev)
{
PSEUDO_ADAPTER *pAd = netdev_priv(dev);
return &pAd->stat;
}
int VirtualIF_open(struct net_device * dev)
{
PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
printk("%s: ===> VirtualIF_open\n", dev->name);
#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
*((volatile u32 *)(FE_INT_ENABLE2)) |= (1<<25); //enable GE2 link change intr for MT7530 delay setting
#endif
netif_start_queue(pPesueoAd->PseudoDev);
return 0;
}
int VirtualIF_close(struct net_device * dev)
{
PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
printk("%s: ===> VirtualIF_close\n", dev->name);
netif_stop_queue(pPesueoAd->PseudoDev);
return 0;
}
int VirtualIFSendPackets(struct sk_buff * pSkb,
struct net_device * dev)
{
PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
END_DEVICE *ei_local __maybe_unused;
//printk("VirtualIFSendPackets --->\n");
ei_local = netdev_priv(dev);
if (!(pPesueoAd->RaethDev->flags & IFF_UP)) {
dev_kfree_skb_any(pSkb);
return 0;
}
//pSkb->cb[40]=0x5a;
pSkb->dev = pPesueoAd->RaethDev;
ei_start_xmit(pSkb, pPesueoAd->RaethDev, 2);
return 0;
}
void virtif_setup_statistics(PSEUDO_ADAPTER* pAd)
{
pAd->stat.tx_packets = 0;
pAd->stat.tx_bytes = 0;
pAd->stat.tx_dropped = 0;
pAd->stat.tx_errors = 0;
pAd->stat.tx_aborted_errors= 0;
pAd->stat.tx_carrier_errors= 0;
pAd->stat.tx_fifo_errors = 0;
pAd->stat.tx_heartbeat_errors = 0;
pAd->stat.tx_window_errors = 0;
pAd->stat.rx_packets = 0;
pAd->stat.rx_bytes = 0;
pAd->stat.rx_dropped = 0;
pAd->stat.rx_errors = 0;
pAd->stat.rx_length_errors = 0;
pAd->stat.rx_over_errors = 0;
pAd->stat.rx_crc_errors = 0;
pAd->stat.rx_frame_errors = 0;
pAd->stat.rx_fifo_errors = 0;
pAd->stat.rx_missed_errors = 0;
pAd->stat.collisions = 0;
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static const struct net_device_ops VirtualIF_netdev_ops = {
.ndo_open = VirtualIF_open,
.ndo_stop = VirtualIF_close,
.ndo_start_xmit = VirtualIFSendPackets,
.ndo_get_stats = VirtualIF_get_stats,
.ndo_set_mac_address = ei_set_mac2_addr,
.ndo_change_mtu = ei_change_mtu,
.ndo_do_ioctl = VirtualIF_ioctl,
.ndo_validate_addr = eth_validate_addr,
};
#endif
// Register pseudo interface
void RAETH_Init_PSEUDO(pEND_DEVICE pAd, struct net_device *net_dev)
{
int index;
struct net_device *dev;
PSEUDO_ADAPTER *pPseudoAd;
int i = 0;
struct sockaddr addr;
unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
for (index = 0; index < MAX_PSEUDO_ENTRY; index++) {
dev = alloc_etherdev(sizeof(PSEUDO_ADAPTER));
if (NULL == dev)
{
printk(" alloc_etherdev for PSEUDO_ADAPTER failed.\n");
return;
}
strcpy(dev->name, DEV2_NAME);
//Get mac2 address from flash
#ifdef RA_MTD_RW_BY_NUM
i = ra_mtd_read(2, GMAC2_OFFSET, 6, addr.sa_data);
#else
i = ra_mtd_read_nm("Factory", GMAC2_OFFSET, 6, addr.sa_data);
#endif
//If reading mtd failed or mac0 is empty, generate a mac address
if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) ||
(memcmp(addr.sa_data, zero2, 6) == 0)) {
unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
net_srandom(jiffies);
memcpy(addr.sa_data, mac_addr01234, 5);
addr.sa_data[5] = net_random()&0xFF;
}
ei_set_mac2_addr(dev, &addr);
ether_setup(dev);
pPseudoAd = netdev_priv(dev);
pPseudoAd->PseudoDev = dev;
pPseudoAd->RaethDev = net_dev;
virtif_setup_statistics(pPseudoAd);
pAd->PseudoDev = dev;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
dev->netdev_ops = &VirtualIF_netdev_ops;
#else
dev->hard_start_xmit = VirtualIFSendPackets;
dev->stop = VirtualIF_close;
dev->open = VirtualIF_open;
dev->do_ioctl = VirtualIF_ioctl;
dev->set_mac_address = ei_set_mac2_addr;
dev->get_stats = VirtualIF_get_stats;
dev->change_mtu = ei_change_mtu;
dev->mtu = 1500;
#endif
dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
#if defined(CONFIG_RALINK_MT7620)
#if defined (CONFIG_RAETH_TSO)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
}
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
}
#endif
#else
#if defined (CONFIG_RAETH_TSO)
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
#endif
#endif // CONFIG_RALINK_MT7620 //
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
dev->vlan_features = dev->features;
#endif
#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
dev->ethtool_ops = &ra_virt_ethtool_ops;
// init mii structure
pPseudoAd->mii_info.dev = dev;
pPseudoAd->mii_info.mdio_read = mdio_virt_read;
pPseudoAd->mii_info.mdio_write = mdio_virt_write;
pPseudoAd->mii_info.phy_id_mask = 0x1f;
pPseudoAd->mii_info.reg_num_mask = 0x1f;
pPseudoAd->mii_info.phy_id = 0x1e;
pPseudoAd->mii_info.supports_gmii = mii_check_gmii_support(&pPseudoAd->mii_info);
#endif
// Register this device
register_netdevice(dev);
}
}
#endif
/**
* ei_open - Open/Initialize the ethernet port.
* @dev: network device to initialize
*
* This routine goes all-out, setting everything
* up a new at each open, even though many of these registers should only need to be set once at boot.
*/
int ei_open(struct net_device *dev)
{
int i, err;
unsigned long flags;
END_DEVICE *ei_local;
#ifdef CONFIG_RAETH_LRO
const char *lan_ip_tmp;
#ifdef CONFIG_DUAL_IMAGE
#define RT2860_NVRAM 1
#else
#define RT2860_NVRAM 0
#endif
#endif // CONFIG_RAETH_LRO //
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if (!try_module_get(THIS_MODULE))
{
printk("%s: Cannot reserve module\n", __FUNCTION__);
return -1;
}
#else
MOD_INC_USE_COUNT;
#endif
printk("Raeth %s (",RAETH_VERSION);
#if defined (CONFIG_RAETH_NAPI)
printk("NAPI\n");
#elif defined (CONFIG_RA_NETWORK_TASKLET_BH)
printk("Tasklet");
#elif defined (CONFIG_RA_NETWORK_WORKQUEUE_BH)
printk("Workqueue");
#endif
#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
printk(",SkbRecycle");
#endif
printk(")\n");
ei_local = netdev_priv(dev); // get device pointer from System
// unsigned int flags;
if (ei_local == NULL)
{
printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
return -ENXIO;
}
/* receiving packet buffer allocation - NUM_RX_DESC x MAX_RX_LENGTH */
for ( i = 0; i < NUM_RX_DESC; i++)
{
#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
ei_local->netrx0_skbuf[i] = skbmgr_dev_alloc_skb2k();
#else
ei_local->netrx0_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
#endif
if (ei_local->netrx0_skbuf[i] == NULL ) {
printk("rx skbuff buffer allocation failed!");
} else {
#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
skb_reserve(ei_local->netrx0_skbuf[i], NET_IP_ALIGN);
#endif
}
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
if (ei_local->netrx1_skbuf[i] == NULL ) {
printk("rx1 skbuff buffer allocation failed!");
} else {
#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN);
#endif
}
#endif
}
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
trgmii_set_7621(); //reset FE/GMAC in this function
#endif
fe_dma_init(dev);
fe_sw_init(); //initialize fe and switch register
err = request_irq( dev->irq, ei_interrupt, IRQF_DISABLED, dev->name, dev); // try to fix irq in open
if (err)
return err;
if ( dev->dev_addr != NULL) {
ra2880MacAddressSet((void *)(dev->dev_addr));
} else {
printk("dev->dev_addr is empty !\n");
}
#if defined (CONFIG_RT_3052_ESW)
err = request_irq(SURFBOARDINT_ESW, esw_interrupt, IRQF_DISABLED, "Ralink_ESW", dev);
if (err)
return err;
INIT_WORK(&ei_local->kill_sig_wq, kill_sig_workq);
#if defined (CONFIG_RALINK_MT7621)
mii_mgr_write(31, 0x7008, 0x1f); //enable switch link change intr
#else
*((volatile u32 *)(RALINK_INTCL_BASE + 0x34)) = (1<<17);
*((volatile u32 *)(ESW_IMR)) &= ~(ESW_INT_ALL);
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
*((volatile u32 *)(ESW_P0_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P1_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P2_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P3_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P4_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P5_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P6_IntMn)) &= ~(MSK_CNT_INT_ALL);
#endif
#if defined(CONFIG_RALINK_MT7620)
*((volatile u32 *)(ESW_P7_IntMn)) &= ~(MSK_CNT_INT_ALL);
#endif
#endif
#endif // CONFIG_RT_3052_ESW //
spin_lock_irqsave(&(ei_local->page_lock), flags);
#ifdef DELAY_INT
sysRegWrite(RAETH_DLY_INT_CFG, DELAY_INT_INIT);
sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT);
#else
sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL);
#endif
#ifdef CONFIG_RAETH_QDMA
#ifdef DELAY_INT
sysRegWrite(QDMA_DELAY_INT, DELAY_INT_INIT);
sysRegWrite(QFE_INT_ENABLE, QFE_INT_DLY_INIT);
#else
sysRegWrite(QFE_INT_ENABLE, QFE_INT_ALL);
#endif
#endif
INIT_WORK(&ei_local->reset_task, ei_reset_task);
#ifdef WORKQUEUE_BH
#ifndef CONFIG_RAETH_NAPI
INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
#endif // CONFIG_RAETH_NAPI //
#else
#ifndef CONFIG_RAETH_NAPI
#if defined (TASKLET_WORKQUEUE_SW)
working_schedule = init_schedule;
INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
tasklet_init(&ei_local->rx_tasklet, ei_receive_workq, 0);
#else
tasklet_init(&ei_local->rx_tasklet, ei_receive, 0);
#endif
#endif // CONFIG_RAETH_NAPI //
#endif // WORKQUEUE_BH //
netif_start_queue(dev);
#ifdef CONFIG_RAETH_NAPI
atomic_dec(&ei_local->irq_sem);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
napi_enable(&ei_local->napi);
#else
netif_poll_enable(dev);
#endif
#endif
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
#ifdef CONFIG_PSEUDO_SUPPORT
if(ei_local->PseudoDev == NULL) {
RAETH_Init_PSEUDO(ei_local, dev);
}
if(ei_local->PseudoDev == NULL)
printk("Open PseudoDev failed.\n");
else
VirtualIF_open(ei_local->PseudoDev);
#endif
#ifdef CONFIG_RAETH_LRO
lan_ip_tmp = nvram_get(RT2860_NVRAM, "lan_ipaddr");
str_to_ip(&lan_ip, lan_ip_tmp);
lro_para.lan_ip1 = lan_ip = htonl(lan_ip);
#endif // CONFIG_RAETH_LRO //
forward_config(dev);
return 0;
}
/**
* ei_close - shut down network device
* @dev: network device to clear
*
* This routine shut down network device.
*
*
*/
int ei_close(struct net_device *dev)
{
int i;
END_DEVICE *ei_local = netdev_priv(dev); // device pointer
netif_stop_queue(dev);
ra2880stop(ei_local);
free_irq(dev->irq, dev);
#if defined (CONFIG_RT_3052_ESW)
free_irq(SURFBOARDINT_ESW, dev);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
cancel_work_sync(&ei_local->reset_task);
#endif
#ifdef CONFIG_PSEUDO_SUPPORT
VirtualIF_close(ei_local->PseudoDev);
#endif
#ifdef WORKQUEUE_BH
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
cancel_work_sync(&ei_local->rx_wq);
#endif
#else
#if defined (TASKLET_WORKQUEUE_SW)
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
cancel_work_sync(&ei_local->rx_wq);
#endif
#endif
tasklet_kill(&ei_local->tx_tasklet);
tasklet_kill(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
for ( i = 0; i < NUM_RX_DESC; i++)
{
if (ei_local->netrx0_skbuf[i] != NULL) {
dev_kfree_skb(ei_local->netrx0_skbuf[i]);
ei_local->netrx0_skbuf[i] = NULL;
}
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if (ei_local->netrx1_skbuf[i] != NULL) {
dev_kfree_skb(ei_local->netrx1_skbuf[i]);
ei_local->netrx1_skbuf[i] = NULL;
}
#endif
}
for ( i = 0; i < NUM_TX_DESC; i++)
{
if((ei_local->skb_free[i]!=(struct sk_buff *)0xFFFFFFFF) && (ei_local->skb_free[i]!= 0))
{
dev_kfree_skb_any(ei_local->skb_free[i]);
}
}
/* TX Ring */
#ifdef CONFIG_RAETH_QDMA
if (ei_local->txd_pool != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct QDMA_txdesc), ei_local->txd_pool, ei_local->phy_txd_pool);
}
if (ei_local->free_head != NULL){
pci_free_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), ei_local->free_head, ei_local->phy_free_head);
}
if (ei_local->free_page_head != NULL){
pci_free_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, ei_local->free_page_head, ei_local->phy_free_page_head);
}
#else
if (ei_local->tx_ring0 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring0, ei_local->phy_tx_ring0);
}
#endif
#if defined (CONFIG_RAETH_QOS)
if (ei_local->tx_ring1 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring1, ei_local->phy_tx_ring1);
}
#if !defined (CONFIG_RALINK_RT2880)
if (ei_local->tx_ring2 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring2, ei_local->phy_tx_ring2);
}
if (ei_local->tx_ring3 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring3, ei_local->phy_tx_ring3);
}
#endif
#endif
/* RX Ring */
#ifdef CONFIG_32B_DESC
kfree(ei_local->rx_ring0);
#else
pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring0, ei_local->phy_rx_ring0);
#endif
#ifdef CONFIG_RAETH_QDMA
#ifdef CONFIG_32B_DESC
kfree(ei_local->qrx_ring);
#else
pci_free_consistent(NULL, NUM_QRX_DESC*sizeof(struct PDMA_rxdesc), ei_local->qrx_ring, ei_local->phy_qrx_ring);
#endif
#endif
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
#ifdef CONFIG_32B_DESC
kfree(ei_local->rx_ring1);
#else
pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1);
#endif
#endif
printk("Free TX/RX Ring Memory!\n");
#ifdef CONFIG_RAETH_NAPI
atomic_inc(&ei_local->irq_sem);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
napi_disable(&ei_local->napi);
#else
netif_poll_disable(dev);
#endif
#endif
fe_reset();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
module_put(THIS_MODULE);
#else
MOD_DEC_USE_COUNT;
#endif
return 0;
}
#if defined (CONFIG_RT6855A_FPGA)
void rt6855A_eth_gpio_reset(void)
{
u8 ether_gpio = 12;
/* Load the ethernet gpio value to reset Ethernet PHY */
*(unsigned long *)(RALINK_PIO_BASE + 0x00) |= 1<<(ether_gpio<<1);
*(unsigned long *)(RALINK_PIO_BASE + 0x14) |= 1<<(ether_gpio);
*(unsigned long *)(RALINK_PIO_BASE + 0x04) &= ~(1<<ether_gpio);
udelay(100000);
*(unsigned long *)(RALINK_PIO_BASE + 0x04) |= (1<<ether_gpio);
/* must wait for 0.6 seconds after reset*/
udelay(600000);
}
#endif
#if defined(CONFIG_RALINK_RT6855A)
void rt6855A_gsw_init(void)
{
u32 phy_val=0;
u32 rev=0;
#if defined (CONFIG_RT6855A_FPGA)
/*keep dump switch mode */
rt6855A_eth_gpio_reset();
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e353;//(P0,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e353;//(P1,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
/* In order to use 10M/Full on FPGA board. We configure phy capable to
* 10M Full/Half duplex, so we can use auto-negotiation on PC side */
for(i=6;i<8;i++){
mii_mgr_write(i, 4, 0x07e1); //Capable of 10M&100M Full/Half Duplex, flow control on/off
//mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
mii_mgr_read(i, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(i, 9, phy_val);
}
#elif defined (CONFIG_RT6855A_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1ec) = 0x0fffffff;//Set PSE should pause 4 tx ring as default
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1f0) = 0x0fffffff;//switch IOT more stable
*(unsigned long *)(CKGCR) &= ~(0x3 << 4); //keep rx/tx port clock ticking, disable internal clock-gating to avoid switch stuck
/*
*Reg 31: Page Control
* Bit 15 => PortPageSel, 1=local, 0=global
* Bit 14:12 => PageSel, local:0~3, global:0~4
*
*Reg16~30:Local/Global registers
*
*/
/*correct PHY setting J8.0*/
mii_mgr_read(0, 31, &rev);
rev &= (0x0f);
mii_mgr_write(1, 31, 0x4000); //global, page 4
mii_mgr_write(1, 16, 0xd4cc);
mii_mgr_write(1, 17, 0x7444);
mii_mgr_write(1, 19, 0x0112);
mii_mgr_write(1, 21, 0x7160);
mii_mgr_write(1, 22, 0x10cf);
mii_mgr_write(1, 26, 0x0777);
if(rev == 0){
mii_mgr_write(1, 25, 0x0102);
mii_mgr_write(1, 29, 0x8641);
}
else{
mii_mgr_write(1, 25, 0x0212);
mii_mgr_write(1, 29, 0x4640);
}
mii_mgr_write(1, 31, 0x2000); //global, page 2
mii_mgr_write(1, 21, 0x0655);
mii_mgr_write(1, 22, 0x0fd3);
mii_mgr_write(1, 23, 0x003d);
mii_mgr_write(1, 24, 0x096e);
mii_mgr_write(1, 25, 0x0fed);
mii_mgr_write(1, 26, 0x0fc4);
mii_mgr_write(1, 31, 0x1000); //global, page 1
mii_mgr_write(1, 17, 0xe7f8);
mii_mgr_write(1, 31, 0xa000); //local, page 2
mii_mgr_write(0, 16, 0x0e0e);
mii_mgr_write(1, 16, 0x0c0c);
mii_mgr_write(2, 16, 0x0f0f);
mii_mgr_write(3, 16, 0x1010);
mii_mgr_write(4, 16, 0x0909);
mii_mgr_write(0, 17, 0x0000);
mii_mgr_write(1, 17, 0x0000);
mii_mgr_write(2, 17, 0x0000);
mii_mgr_write(3, 17, 0x0000);
mii_mgr_write(4, 17, 0x0000);
#endif
#if defined (CONFIG_RT6855A_ASIC)
#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12
*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
//rt6855/6 need to modify TX/RX phase
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0xc;//TX/RX CLOCK Phase select
enable_auto_negotiate(1);
if (isICPlusGigaPHY(1)) {
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
phy_val |= 1<<10; //enable pause ability
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}
if (isMarvellGigaPHY(1)) {
printk("Reset MARVELL phy1\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}
if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#else // Port 5 Disabled //
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
#endif
#endif
}
#endif
#if defined (CONFIG_RALINK_MT7621)
void setup_external_gsw(void)
{
u32 regValue;
/* reduce RGMII2 PAD driving strength */
*(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
//enable MDIO
regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
regValue &= ~(0x3 << 12);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
//RGMII1=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
//GMAC1= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x00008000);//(GE1, Link down)
//RGMII2=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
//GMAC2= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2005e33b);//(GE2, Force 1000M/FD, FC ON)
}
void IsSwitchVlanTableBusy(void)
{
int j = 0;
unsigned int value = 0;
for (j = 0; j < 20; j++) {
mii_mgr_read(31, 0x90, &value);
if ((value & 0x80000000) == 0 ){ //table busy
break;
}
udelay(70000);
}
if (j == 20)
printk("set vlan timeout value=0x%x.\n", value);
}
void LANWANPartition(void)
{
/*Set MT7530 */
#ifdef CONFIG_WAN_AT_P0
printk("set LAN/WAN WLLLL\n");
//WLLLL, wan at P0
//LAN/WAN ports as security mode
mii_mgr_write(31, 0x2004, 0xff0003);//port0
mii_mgr_write(31, 0x2104, 0xff0003);//port1
mii_mgr_write(31, 0x2204, 0xff0003);//port2
mii_mgr_write(31, 0x2304, 0xff0003);//port3
mii_mgr_write(31, 0x2404, 0xff0003);//port4
//set PVID
mii_mgr_write(31, 0x2014, 0x10002);//port0
mii_mgr_write(31, 0x2114, 0x10001);//port1
mii_mgr_write(31, 0x2214, 0x10001);//port2
mii_mgr_write(31, 0x2314, 0x10001);//port3
mii_mgr_write(31, 0x2414, 0x10001);//port4
/*port6 */
//VLAN member
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x40610001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
IsSwitchVlanTableBusy();
#endif
#ifdef CONFIG_WAN_AT_P4
printk("set LAN/WAN LLLLW\n");
//LLLLW, wan at P4
//LAN/WAN ports as security mode
mii_mgr_write(31, 0x2004, 0xff0003);//port0
mii_mgr_write(31, 0x2104, 0xff0003);//port1
mii_mgr_write(31, 0x2204, 0xff0003);//port2
mii_mgr_write(31, 0x2304, 0xff0003);//port3
mii_mgr_write(31, 0x2404, 0xff0003);//port4
//set PVID
mii_mgr_write(31, 0x2014, 0x10001);//port0
mii_mgr_write(31, 0x2114, 0x10001);//port1
mii_mgr_write(31, 0x2214, 0x10001);//port2
mii_mgr_write(31, 0x2314, 0x10001);//port3
mii_mgr_write(31, 0x2414, 0x10002);//port4
//VLAN member
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x404f0001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x40500001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
IsSwitchVlanTableBusy();
#endif
}
#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
void mt7621_eee_patch(void)
{
u32 i;
for(i=0;i<5;i++)
{
/* Enable EEE */
mii_mgr_write(i, 13, 0x07);
mii_mgr_write(i, 14, 0x3c);
mii_mgr_write(i, 13, 0x4007);
mii_mgr_write(i, 14, 0x6);
/* Forced Slave mode */
mii_mgr_write(i, 31, 0x0);
mii_mgr_write(i, 9, 0x1600);
/* Increase SlvDPSready time */
mii_mgr_write(i, 31, 0x52b5);
mii_mgr_write(i, 16, 0xafae);
mii_mgr_write(i, 18, 0x2f);
mii_mgr_write(i, 16, 0x8fae);
/* Incease post_update_timer */
mii_mgr_write(i, 31, 0x3);
mii_mgr_write(i, 17, 0x4b);
/* Adjust 100_mse_threshold */
mii_mgr_write(i, 13, 0x1e);
mii_mgr_write(i, 14, 0x123);
mii_mgr_write(i, 13, 0x401e);
mii_mgr_write(i, 14, 0xffff);
/* Disable mcc
mii_mgr_write(i, 13, 0x1e);
mii_mgr_write(i, 14, 0xa6);
mii_mgr_write(i, 13, 0x401e);
mii_mgr_write(i, 14, 0x300);
*/
}
}
#endif
void setup_internal_gsw(void)
{
u32 i;
u32 regValue;
#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)
/*Hardware reset Switch*/
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2);
udelay(1000);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2);
udelay(10000);
/* reduce RGMII2 PAD driving strength */
*(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
//RGMII1=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
//GMAC1= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
//enable MDIO to control MT7530
regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
regValue &= ~(0x3 << 12);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
for(i=0;i<=4;i++)
{
//turn off PHY
mii_mgr_read(i, 0x0 ,&regValue);
regValue |= (0x1<<11);
mii_mgr_write(i, 0x0, regValue);
}
mii_mgr_write(31, 0x7000, 0x3); //reset switch
udelay(100);
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
trgmii_set_7530(); //reset FE, config MDIO again
//enable MDIO to control MT7530
regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
regValue &= ~(0x3 << 12);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
// switch to APLL if TRGMII and DDR2
if ((sysRegRead(0xBE000010)>>4)&0x1)
{
apll_xtal_enable();
}
#endif
#if defined (CONFIG_MT7621_ASIC)
if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) {
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2005e30b);//(GE1, Force 1000M/FD, FC ON)
mii_mgr_write(31, 0x3600, 0x5e30b);
} else {
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2005e33b);//(GE1, Force 1000M/FD, FC ON)
mii_mgr_write(31, 0x3600, 0x5e33b);
}
#elif defined (CONFIG_MT7621_FPGA)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2005e337);//(GE1, Force 100M/FD, FC ON)
mii_mgr_write(31, 0x3600, 0x5e337);
#endif
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
#endif
#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)
//regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
mii_mgr_read(31, 0x7804 ,&regValue);
regValue &= ~(1<<8); //Enable Port 6
regValue |= (1<<6); //Disable Port 5
regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
#if defined (CONFIG_RAETH_GMAC2)
//RGMII2=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
//GMAC2= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
#if !defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x20056300);//(GE2, auto-polling)
enable_auto_negotiate(0);//set polling address
#endif
#if defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(31, 0x3500, 0x5e33b); //MT7530 P5 Force 1000, we can ignore this setting??????
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2005e33b);//(GE2, Force 1000)
#endif
/* set MT7530 Port 5 to PHY 0/4 mode */
#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
regValue &= ~((1<<13)|(1<<6));
regValue |= ((1<<7)|(1<<16)|(1<<20));
#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
regValue &= ~((1<<13)|(1<<6)|(1<<20));
regValue |= ((1<<7)|(1<<16));
#endif
#if defined (CONFIG_RAETH_8023AZ_EEE)
regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
#endif
//sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
#endif
regValue |= (1<<16);//change HW-TRAP
printk("change HW-TRAP to 0x%x\n",regValue);
mii_mgr_write(31, 0x7804 ,regValue);
#endif
regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10);
regValue = (regValue >> 6) & 0x7;
if(regValue >= 6) { //25Mhz Xtal
/* do nothing */
} else if(regValue >=3) { //40Mhz
mii_mgr_write(0, 13, 0x1f); // disable MT7530 core clock
mii_mgr_write(0, 14, 0x410);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x0);
mii_mgr_write(0, 13, 0x1f); // disable MT7530 PLL
mii_mgr_write(0, 14, 0x40d);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x2020);
mii_mgr_write(0, 13, 0x1f); // for MT7530 core clock = 500Mhz
mii_mgr_write(0, 14, 0x40e);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x119);
mii_mgr_write(0, 13, 0x1f); // enable MT7530 PLL
mii_mgr_write(0, 14, 0x40d);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x2820);
udelay(20); //suggest by CD
mii_mgr_write(0, 13, 0x1f); // enable MT7530 core clock
mii_mgr_write(0, 14, 0x410);
mii_mgr_write(0, 13, 0x401f);
}else { //20Mhz Xtal
/* TODO */
}
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
mii_mgr_write(0, 14, 0x3); /*TRGMII*/
#else
mii_mgr_write(0, 14, 0x1); /*RGMII*/
/* set MT7530 central align */
mii_mgr_read(31, 0x7830, &regValue);
regValue &= ~1;
regValue |= 1<<1;
mii_mgr_write(31, 0x7830, regValue);
mii_mgr_read(31, 0x7a40, &regValue);
regValue &= ~(1<<30);
mii_mgr_write(31, 0x7a40, regValue);
regValue = 0x855;
mii_mgr_write(31, 0x7a78, regValue);
#endif
#if !defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(31, 0x7b00, 0x102); //delay setting for 10/1000M
mii_mgr_write(31, 0x7b04, 0x14); //delay setting for 10/1000M
#endif
#if 0
for(i=0;i<=4;i++) {
mii_mgr_read(i, 4, &regValue);
regValue |= (3<<7); //turn on 100Base-T Advertisement
//regValue &= ~(3<<7); //turn off 100Base-T Advertisement
mii_mgr_write(i, 4, regValue);
mii_mgr_read(i, 9, &regValue);
regValue |= (3<<8); //turn on 1000Base-T Advertisement
//regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
mii_mgr_write(i, 9, regValue);
//restart AN
mii_mgr_read(i, 0, &regValue);
regValue |= (1 << 9);
mii_mgr_write(i, 0, regValue);
}
#endif
/*Tx Driving*/
mii_mgr_write(31, 0x7a54, 0x44); //lower driving
mii_mgr_write(31, 0x7a5c, 0x44); //lower driving
mii_mgr_write(31, 0x7a64, 0x44); //lower driving
mii_mgr_write(31, 0x7a6c, 0x44); //lower driving
mii_mgr_write(31, 0x7a74, 0x44); //lower driving
mii_mgr_write(31, 0x7a7c, 0x44); //lower driving
LANWANPartition();
#if !defined (CONFIG_RAETH_8023AZ_EEE)
//disable EEE
for(i=0;i<=4;i++)
{
mii_mgr_write(i, 13, 0x7);
mii_mgr_write(i, 14, 0x3C);
mii_mgr_write(i, 13, 0x4007);
mii_mgr_write(i, 14, 0x0);
}
//Disable EEE 10Base-Te:
for(i=0;i<=4;i++)
{
mii_mgr_write(i, 13, 0x1f);
mii_mgr_write(i, 14, 0x027b);
mii_mgr_write(i, 13, 0x401f);
mii_mgr_write(i, 14, 0x1177);
}
#endif
for(i=0;i<=4;i++)
{
//turn on PHY
mii_mgr_read(i, 0x0 ,&regValue);
regValue &= ~(0x1<<11);
mii_mgr_write(i, 0x0, regValue);
}
mii_mgr_read(31, 0x7808 ,&regValue);
regValue |= (3<<16); //Enable INTR
mii_mgr_write(31, 0x7808 ,regValue);
#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
mt7621_eee_patch();
#endif
}
#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
void apll_xtal_enable(void)
{
unsigned long data = 0;
unsigned long regValue = 0;
/* Firstly, reset all required register to default value */
sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008000);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
/* toggle RG_XPTL_CHG */
sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008800);
sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008c00);
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0014);
data &= ~(0x0000ffc0);
regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10);
regValue = (regValue >> 6) & 0x7;
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0x1d, 8);
}else {
data |= REGBIT(0x17, 8);
}
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0x1, 6);
}
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, data);
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0018);
data &= ~(0xf0773f00);
data |= REGBIT(0x3, 28);
data |= REGBIT(0x2, 20);
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0x3, 16);
}else {
data |= REGBIT(0x2, 16);
}
data |= REGBIT(0x3, 12);
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0xd, 8);
}else {
data |= REGBIT(0x7, 8);
}
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, data);
if(regValue < 6) { //20/40Mhz Xtal
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
}else {
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39);
}
//*Common setting - Set PLLGP_CTRL_4 *//
///* 1. Bit 31 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data &= ~(REGBIT(0x1, 31));
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 2. Bit 0 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 0);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 3. Bit 3 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 3);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 4. Bit 8 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 8);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 5. Bit 6 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 6);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 6. Bit 7 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 5);
data |= REGBIT(0x1, 7);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 7. Bit 17 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data &= ~REGBIT(0x1, 17);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 8. TRGMII TX CLK SEL APLL */
data = sysRegRead(0xbe00002c);
data &= 0xffffff9f;
data |= 0x40;
sysRegWrite(0xbe00002c, data);
}
#endif
#endif
#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
void rt_gsw_init(void)
{
#if defined (CONFIG_P4_MAC_TO_PHY_MODE) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
u32 phy_val=0;
#endif
#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
u32 i=0;
#elif defined (CONFIG_MT7620_ASIC)
u32 is_BGA=0;
#endif
#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
unsigned int regValue = 0;
#endif
#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
/*keep dump switch mode */
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x5e333;//(P2, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x5e333;//(P3, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
#if defined (CONFIG_RAETH_HAS_PORT4)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#else
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e333;//(P4, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
#endif
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
/* In order to use 10M/Full on FPGA board. We configure phy capable to
* 10M Full/Half duplex, so we can use auto-negotiation on PC side */
#if defined (CONFIG_RAETH_HAS_PORT4)
for(i=0;i<4;i++){
#else
for(i=0;i<5;i++){
#endif
mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
}
#endif
#if defined (CONFIG_PDMA_NEW)
*(unsigned long *)(SYSCFG1) |= (0x1 << 8); //PCIE_RC_MODE=1
#endif
#if defined (CONFIG_MT7620_ASIC) && !defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
is_BGA = (sysRegRead(RALINK_SYSCTL_BASE + 0xc) >> 16) & 0x1;
/*
* Reg 31: Page Control
* Bit 15 => PortPageSel, 1=local, 0=global
* Bit 14:12 => PageSel, local:0~3, global:0~4
*
* Reg16~30:Local/Global registers
*
*/
/*correct PHY setting L3.0 BGA*/
mii_mgr_write(1, 31, 0x4000); //global, page 4
mii_mgr_write(1, 17, 0x7444);
if(is_BGA){
mii_mgr_write(1, 19, 0x0114);
}else{
mii_mgr_write(1, 19, 0x0117);
}
mii_mgr_write(1, 22, 0x10cf);
mii_mgr_write(1, 25, 0x6212);
mii_mgr_write(1, 26, 0x0777);
mii_mgr_write(1, 29, 0x4000);
mii_mgr_write(1, 28, 0xc077);
mii_mgr_write(1, 24, 0x0000);
mii_mgr_write(1, 31, 0x3000); //global, page 3
mii_mgr_write(1, 17, 0x4838);
mii_mgr_write(1, 31, 0x2000); //global, page 2
if(is_BGA){
mii_mgr_write(1, 21, 0x0515);
mii_mgr_write(1, 22, 0x0053);
mii_mgr_write(1, 23, 0x00bf);
mii_mgr_write(1, 24, 0x0aaf);
mii_mgr_write(1, 25, 0x0fad);
mii_mgr_write(1, 26, 0x0fc1);
}else{
mii_mgr_write(1, 21, 0x0517);
mii_mgr_write(1, 22, 0x0fd2);
mii_mgr_write(1, 23, 0x00bf);
mii_mgr_write(1, 24, 0x0aab);
mii_mgr_write(1, 25, 0x00ae);
mii_mgr_write(1, 26, 0x0fff);
}
mii_mgr_write(1, 31, 0x1000); //global, page 1
mii_mgr_write(1, 17, 0xe7f8);
mii_mgr_write(1, 31, 0x8000); //local, page 0
mii_mgr_write(0, 30, 0xa000);
mii_mgr_write(1, 30, 0xa000);
mii_mgr_write(2, 30, 0xa000);
mii_mgr_write(3, 30, 0xa000);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 30, 0xa000);
#endif
mii_mgr_write(0, 4, 0x05e1);
mii_mgr_write(1, 4, 0x05e1);
mii_mgr_write(2, 4, 0x05e1);
mii_mgr_write(3, 4, 0x05e1);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 4, 0x05e1);
#endif
mii_mgr_write(1, 31, 0xa000); //local, page 2
mii_mgr_write(0, 16, 0x1111);
mii_mgr_write(1, 16, 0x1010);
mii_mgr_write(2, 16, 0x1515);
mii_mgr_write(3, 16, 0x0f0f);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 16, 0x1313);
#endif
#if !defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(1, 31, 0xb000); //local, page 3
mii_mgr_write(0, 17, 0x0);
mii_mgr_write(1, 17, 0x0);
mii_mgr_write(2, 17, 0x0);
mii_mgr_write(3, 17, 0x0);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 17, 0x0);
#endif
#endif
#endif
#if defined(CONFIG_RALINK_MT7620)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
*(unsigned long *)(RALINK_ETH_SW_BASE+0x701c) = 0x800000c; //enlarge FE2SW_IPG
}
#endif // CONFIG_RAETH_7620 //
#if defined (CONFIG_MT7620_FPGA)|| defined (CONFIG_MT7620_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0x7f7f7fe0;//Set Port6 CPU Port
#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c; //disable port 0 ~ 4 internal phy, set phy base address to 12
/*MT7620 need mac learning for PPE*/
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
//rxclk_skew, txclk_skew = 0
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;//(P4, AN)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
//rxclk_skew, txclk_skew = 0
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
/* set MT7530 Port 0 to PHY mode */
mii_mgr_read(31, 0x7804 ,&regValue);
#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
regValue &= ~((1<<13)|(1<<6)|(1<<5)|(1<<15));
regValue |= ((1<<7)|(1<<16)|(1<<20)|(1<<24));
//mii_mgr_write(31, 0x7804 ,0x115c8f);
#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
regValue &= ~((1<<13)|(1<<6)|(1<<20)|(1<<5)|(1<<15));
regValue |= ((1<<7)|(1<<16)|(1<<24));
#endif
regValue &= ~(1<<8); //Enable Port 6
mii_mgr_write(31, 0x7804 ,regValue); //bit 24 standalone switch
/* set MT7530 central align */
mii_mgr_read(31, 0x7830, &regValue);
regValue &= ~1;
regValue |= 1<<1;
mii_mgr_write(31, 0x7830, regValue);
mii_mgr_read(31, 0x7a40, &regValue);
regValue &= ~(1<<30);
mii_mgr_write(31, 0x7a40, regValue);
regValue = 0x855;
mii_mgr_write(31, 0x7a78, regValue);
/*AN should be set after MT7530 HWSTRAP*/
#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000100;//(P0, AN polling)
#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000504;//(P4, AN polling)
#endif
#endif
#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
*(unsigned long *)(SYSCFG1) |= (0x1 << 12);
#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
enable_auto_negotiate(1);
if (isICPlusGigaPHY(1)) {
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
phy_val |= 1<<10; //enable pause ability
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}else if (isMarvellGigaPHY(1)) {
#if defined (CONFIG_MT7620_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
#endif
printk("Reset MARVELL phy1\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}else if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
*(unsigned long *)(SYSCFG1) |= (0x2 << 12);
#else // Port 5 Disabled //
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
*(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode
#endif
#endif
#if defined (CONFIG_P4_RGMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e33b;//(P4, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
//rxclk_skew, txclk_skew = 0
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
#elif defined (CONFIG_P4_MII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
*(unsigned long *)(SYSCFG1) |= (0x1 << 14);
#elif defined (CONFIG_P4_MAC_TO_PHY_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
enable_auto_negotiate(1);
if (isICPlusGigaPHY(2)) {
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, &phy_val);
phy_val |= 1<<10; //enable pause ability
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
phy_val |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
}else if (isMarvellGigaPHY(2)) {
#if defined (CONFIG_MT7620_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, phy_val);
#endif
printk("Reset MARVELL phy2\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
}else if (isVtssGigaPHY(2)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P4_RMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE1_MODE=RvMii Mode
*(unsigned long *)(SYSCFG1) |= (0x2 << 14);
#elif defined (CONFIG_GE_RGMII_MT7530_P0_AN) || defined (CONFIG_GE_RGMII_MT7530_P4_AN)
#else // Port 4 Disabled //
*(unsigned long *)(SYSCFG1) |= (0x3 << 14); //GE2_MODE=RJ45 Mode
*(unsigned long *)(0xb0000060) |= (1 << 10); //set RGMII2 to GPIO mode
#endif
}
#endif
#if defined (CONFIG_RALINK_MT7628)
void mt7628_ephy_init(void)
{
int i;
u32 phy_val;
mii_mgr_write(0, 31, 0x2000); //change G2 page
mii_mgr_write(0, 26, 0x0000);
for(i=0; i<5; i++){
mii_mgr_write(i, 31, 0x8000); //change L0 page
mii_mgr_write(i, 0, 0x3100);
#if defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_read(i, 26, &phy_val);// EEE setting
phy_val |= (1 << 5);
mii_mgr_write(i, 26, phy_val);
#else
//disable EEE
mii_mgr_write(i, 13, 0x7);
mii_mgr_write(i, 14, 0x3C);
mii_mgr_write(i, 13, 0x4007);
mii_mgr_write(i, 14, 0x0);
#endif
mii_mgr_write(i, 30, 0xa000);
mii_mgr_write(i, 31, 0xa000); // change L2 page
mii_mgr_write(i, 16, 0x0606);
mii_mgr_write(i, 23, 0x0f0e);
mii_mgr_write(i, 24, 0x1610);
mii_mgr_write(i, 30, 0x1f15);
mii_mgr_write(i, 28, 0x6111);
mii_mgr_read(i, 4, &phy_val);
phy_val |= (1 << 10);
mii_mgr_write(i, 4, phy_val);
}
//100Base AOI setting
mii_mgr_write(0, 31, 0x5000); //change G5 page
mii_mgr_write(0, 19, 0x004a);
mii_mgr_write(0, 20, 0x015a);
mii_mgr_write(0, 21, 0x00ee);
mii_mgr_write(0, 22, 0x0033);
mii_mgr_write(0, 23, 0x020a);
mii_mgr_write(0, 24, 0x0000);
mii_mgr_write(0, 25, 0x024a);
mii_mgr_write(0, 26, 0x035a);
mii_mgr_write(0, 27, 0x02ee);
mii_mgr_write(0, 28, 0x0233);
mii_mgr_write(0, 29, 0x000a);
mii_mgr_write(0, 30, 0x0000);
/* Fix EPHY idle state abnormal behavior */
mii_mgr_write(0, 31, 0x4000); //change G4 page
mii_mgr_write(0, 29, 0x000d);
mii_mgr_write(0, 30, 0x0500);
}
#endif
#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
void rt305x_esw_init(void)
{
int i=0;
u32 phy_val=0, val=0;
#if defined (CONFIG_RT3052_ASIC)
u32 phy_val2;
#endif
#if defined (CONFIG_RT5350_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0168) = 0x17;
#endif
/*
* FC_RLS_TH=200, FC_SET_TH=160
* DROP_RLS=120, DROP_SET_TH=80
*/
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0008) = 0xC8A07850;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00E4) = 0x00000000;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0014) = 0x00405555;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0050) = 0x00002001;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0090) = 0x00007f7f;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0098) = 0x00007f3f; //disable VLAN
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00CC) = 0x0002500c;
#ifndef CONFIG_UNH_TEST
*(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x0008a301; //hashing algorithm=XOR48, aging interval=300sec
#else
/*
* bit[30]:1 Backoff Algorithm Option: The latest one to pass UNH test
* bit[29]:1 Length of Received Frame Check Enable
* bit[8]:0 Enable collision 16 packet abort and late collision abort
* bit[7:6]:01 Maximum Packet Length: 1518
*/
*(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x6008a241;
#endif
*(unsigned long *)(RALINK_ETH_SW_BASE+0x008C) = 0x02404040;
#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC) || defined (CONFIG_RT5350_ASIC) || defined (CONFIG_MT7628_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x3f502b28; //Change polling Ext PHY Addr=0x1F
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0x00000000;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x7d000000; //1us cycle number=125 (FE's clock=125Mhz)
#elif defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA) || defined (CONFIG_RT5350_FPGA) || defined (CONFIG_MT7628_FPGA)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x00f03ff9; //polling Ext PHY Addr=0x0, force port5 as 100F/D (disable auto-polling)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0xffdf1f00;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x0d000000; //1us cycle number=13 (FE's clock=12.5Mhz)
/* In order to use 10M/Full on FPGA board. We configure phy capable to
* 10M Full/Half duplex, so we can use auto-negotiation on PC side */
for(i=0;i<5;i++){
mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
}
#endif
/*
* set port 5 force to 1000M/Full when connecting to switch or iNIC
*/
#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3fff; //force 1000M full duplex
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0xf<<20); //rxclk_skew, txclk_skew = 0
#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
#if defined (CONFIG_RALINK_RT3352)
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
*(unsigned long *)(SYSCFG1) |= (0x1 << 12);
#endif
#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(0xb0000060) &= ~(1 << 7); //set MDIO to Normal mode
#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC)
enable_auto_negotiate(1);
#endif
if (isMarvellGigaPHY(1)) {
#if defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
#endif
printk("\n Reset MARVELL phy\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}
if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
#if defined (CONFIG_RALINK_RT3352)
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
*(unsigned long *)(SYSCFG1) |= (0x2 << 12);
#endif
#else // Port 5 Disabled //
#if defined (CONFIG_RALINK_RT3052)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
*(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
*(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO41-GPIO50)
*(unsigned long *)(0xb0000674) = 0xFFF; //GPIO41-GPIO50 output mode
*(unsigned long *)(0xb000067C) = 0x0; //GPIO41-GPIO50 output low
#elif defined (CONFIG_RALINK_RT3352)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
*(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
*(unsigned long *)(0xb0000624) = 0xC0000000; //GPIO22-GPIO23 output mode
*(unsigned long *)(0xb000062C) = 0xC0000000; //GPIO22-GPIO23 output high
*(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO24-GPIO35)
*(unsigned long *)(0xb000064C) = 0xFFF; //GPIO24-GPIO35 output mode
*(unsigned long *)(0xb0000654) = 0xFFF; //GPIO24-GPIO35 output high
#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
/* do nothing */
#endif
#endif // CONFIG_P5_RGMII_TO_MAC_MODE //
#if defined (CONFIG_RT3052_ASIC)
rw_rf_reg(0, 0, &phy_val);
phy_val = phy_val >> 4;
if(phy_val > 0x5) {
rw_rf_reg(0, 26, &phy_val);
phy_val2 = (phy_val | (0x3 << 5));
rw_rf_reg(1, 26, &phy_val2);
// reset EPHY
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
rw_rf_reg(1, 26, &phy_val);
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
//#define ENABLE_LDPS
#if defined (ENABLE_LDPS)
mii_mgr_write(0, 12, 0x7eaa);
mii_mgr_write(0, 22, 0x252f); //tune TP_IDL tail and head waveform, enable power down slew rate control
#else
mii_mgr_write(0, 12, 0x0);
mii_mgr_write(0, 22, 0x052f);
#endif
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
} else {
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 22, 0x052f); //tune TP_IDL tail and head waveform
mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
}
#elif defined (CONFIG_RT3352_ASIC)
//PHY IOT
// reset EPHY
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7016); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
mii_mgr_write(0, 12, 0x7eaa);
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
#elif defined (CONFIG_RT5350_ASIC)
//PHY IOT
// reset EPHY
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7015); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
mii_mgr_write(0, 12, 0x7eaa);
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
#elif defined (CONFIG_MT7628_ASIC)
/*INIT MT7628 PHY HERE*/
val = sysRegRead(RT2880_AGPIOCFG_REG);
#if defined (CONFIG_ETH_ONE_PORT_ONLY)
val |= (MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
val = val & ~(MT7628_P0_EPHY_AIO_EN);
#else
val = val & ~(MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
#endif
if ((*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x8))) & 0x10000)
val &= ~0x1f0000;
sysRegWrite(RT2880_AGPIOCFG_REG, val);
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
val = sysRegRead(RALINK_SYSCTL_BASE + 0x64);
#if defined (CONFIG_ETH_ONE_PORT_ONLY)
val &= 0xf003f003;
val |= 0x05540554;
sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0 EPHY LED mode
#else
val &= 0xf003f003;
sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0~P4 EPHY LED mode
#endif
udelay(5000);
mt7628_ephy_init();
#endif
}
#endif
/**
* ra2882eth_init - Module Init code
*
* Called by kernel to register net_device
*
*/
int __init ra2882eth_init(void)
{
int ret;
struct net_device *dev = alloc_etherdev(sizeof(END_DEVICE));
#ifdef CONFIG_RALINK_VISTA_BASIC
int sw_id=0;
mii_mgr_read(29, 31, &sw_id);
is_switch_175c = (sw_id == 0x175c) ? 1:0;
#endif
if (!dev)
return -ENOMEM;
strcpy(dev->name, DEV_NAME);
dev->irq = IRQ_ENET0;
dev->addr_len = 6;
dev->base_addr = RALINK_FRAME_ENGINE_BASE;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
rather_probe(dev);
#else
dev->init = rather_probe;
#endif
ra2880_setup_dev_fptable(dev);
/* net_device structure Init */
ethtool_init(dev);
printk("Ralink APSoC Ethernet Driver Initilization. %s %d rx/tx descriptors allocated, mtu = %d!\n", RAETH_VERSION, NUM_RX_DESC, dev->mtu);
#ifdef CONFIG_RAETH_NAPI
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
printk("NAPI enable, Tx Ring = %d, Rx Ring = %d\n", NUM_TX_DESC, NUM_RX_DESC);
#else
printk("NAPI enable, weight = %d, Tx Ring = %d, Rx Ring = %d\n", dev->weight, NUM_TX_DESC, NUM_RX_DESC);
#endif
#endif
/* Register net device for the driver */
if ( register_netdev(dev) != 0) {
printk(KERN_WARNING " " __FILE__ ": No ethernet port found.\n");
return -ENXIO;
}
#ifdef CONFIG_RAETH_NETLINK
csr_netlink_init();
#endif
ret = debug_proc_init();
dev_raether = dev;
return ret;
}
void fe_sw_init(void)
{
#if defined (CONFIG_GIGAPHY) || defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
unsigned int regValue = 0;
#endif
// Case1: RT288x/RT3883/MT7621 GE1 + GigaPhy
#if defined (CONFIG_GE1_RGMII_AN)
enable_auto_negotiate(1);
if (isMarvellGigaPHY(1)) {
#if defined (CONFIG_RT3883_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
printk("\n Reset MARVELL phy\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &regValue);
regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
regValue |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
#elif defined (CONFIG_MT7621_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
regValue |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
#endif
}
if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 1);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &regValue);
printk("Vitesse phy skew: %x --> ", regValue);
regValue |= (0x3<<12);
regValue &= ~(0x3<<14);
printk("%x\n", regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0);
}
#if defined (CONFIG_RALINK_MT7621)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x20056300);//(P0, Auto mode)
#endif
#endif // CONFIG_GE1_RGMII_AN //
// Case2: RT3883/MT7621 GE2 + GigaPhy
#if defined (CONFIG_GE2_RGMII_AN)
enable_auto_negotiate(2);
if (isMarvellGigaPHY(2)) {
#if defined (CONFIG_RT3883_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &regValue);
regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
regValue |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
#elif defined (CONFIG_MT7621_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
regValue |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
#endif
}
if (isVtssGigaPHY(2)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 1);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &regValue);
printk("Vitesse phy skew: %x --> ", regValue);
regValue |= (0x3<<12);
regValue &= ~(0x3<<14);
printk("%x\n", regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0);
}
#if defined (CONFIG_RALINK_MT7621)
//RGMII2=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
//GMAC2= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x20056300);//(P1, Auto mode)
#endif
#endif // CONFIG_GE2_RGMII_AN //
// Case3: RT305x/RT335x/RT6855/RT6855A/MT7620 + EmbeddedSW
#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_RALINK_MT7621)
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
rt_gsw_init();
#elif defined(CONFIG_RALINK_RT6855A)
rt6855A_gsw_init();
#else
rt305x_esw_init();
#endif
#endif
// Case4: RT288x/RT388x/MT7621 GE1 + Internal GigaSW
#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)
#if defined (CONFIG_RALINK_MT7621)
/*MT7530 Init*/
setup_internal_gsw();
#else
sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_1000_FD);
#endif
#endif
// Case5: RT388x/MT7621 GE2 + GigaSW
#if defined (CONFIG_GE2_RGMII_FORCE_1000)
#if defined (CONFIG_RALINK_MT7621)
setup_external_gsw();
#else
sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_1000_FD);
#endif
#endif
// Case6: RT288x GE1 /RT388x,MT7621 GE1/GE2 + (10/100 Switch or 100PHY)
#if defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
//set GMAC to MII or RvMII mode
#if defined (CONFIG_RALINK_RT3883)
regValue = sysRegRead(SYSCFG1);
#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE1_MII_AN)
regValue &= ~(0x3 << 12);
regValue |= 0x1 << 12; // GE1 MII Mode
#elif defined (CONFIG_GE1_RVMII_FORCE_100)
regValue &= ~(0x3 << 12);
regValue |= 0x2 << 12; // GE1 RvMII Mode
#endif
#if defined (CONFIG_GE2_MII_FORCE_100) || defined (CONFIG_GE2_MII_AN)
regValue &= ~(0x3 << 14);
regValue |= 0x1 << 14; // GE2 MII Mode
#elif defined (CONFIG_GE2_RVMII_FORCE_100)
regValue &= ~(0x3 << 14);
regValue |= 0x2 << 14; // GE2 RvMII Mode
#endif
sysRegWrite(SYSCFG1, regValue);
#endif // CONFIG_RALINK_RT3883 //
#elif defined (CONFIG_RALINK_MT7621)
#if defined (CONFIG_GE1_MII_FORCE_100)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x5e337);//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#endif
#if defined (CONFIG_GE2_MII_FORCE_100)
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x5e337);//(P1, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#endif
#if defined (CONFIG_GE1_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
enable_auto_negotiate(1);
#if defined (CONFIG_RALINK_MT7621)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x20056300);//(P0, Auto mode)
#endif
#endif
#if defined (CONFIG_GE2_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
enable_auto_negotiate(2);
#if defined (CONFIG_RALINK_MT7621)
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x20056300);//(P1, Auto mode)
#endif
#endif
#else
#if defined (CONFIG_GE1_MII_FORCE_100)
#if defined (CONFIG_RALINK_MT7621)
#else
sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_100_FD);
#endif
#endif
#if defined (CONFIG_GE2_MII_FORCE_100)
#if defined (CONFIG_RALINK_MT7621)
#else
sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_100_FD);
#endif
#endif
//add switch configuration here for other switch chips.
#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE2_MII_FORCE_100)
// IC+ 175x: force IC+ switch cpu port is 100/FD
mii_mgr_write(29, 22, 0x8420);
#endif
#endif // defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) //
}
/**
* ra2882eth_cleanup_module - Module Exit code
*
* Cmd 'rmmod' will invode the routine to exit the module
*
*/
void ra2882eth_cleanup_module(void)
{
struct net_device *dev = dev_raether;
END_DEVICE *ei_local;
ei_local = netdev_priv(dev);
#ifdef CONFIG_PSEUDO_SUPPORT
unregister_netdev(ei_local->PseudoDev);
free_netdev(ei_local->PseudoDev);
#endif
unregister_netdev(dev);
RAETH_PRINT("Free ei_local and unregister netdev...\n");
free_netdev(dev);
debug_proc_exit();
#ifdef CONFIG_RAETH_NETLINK
csr_netlink_end();
#endif
}
EXPORT_SYMBOL(set_fe_dma_glo_cfg);
module_init(ra2882eth_init);
module_exit(ra2882eth_cleanup_module);
MODULE_LICENSE("GPL");
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/if_ether.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/rt2880/surfboardint.h>
#if defined (CONFIG_RAETH_TSO)
#include <linux/tcp.h>
#include <net/ipv6.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <linux/in.h>
#include <linux/ppp_defs.h>
#include <linux/if_pppox.h>
#endif
#if defined (CONFIG_RAETH_LRO)
#include <linux/inet_lro.h>
#endif
#include <linux/delay.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
#include <linux/sched.h>
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
#include <asm/rt2880/rt_mmap.h>
#else
#include <linux/libata-compat.h>
#endif
#include "ra2882ethreg.h"
#include "raether.h"
#include "ra_mac.h"
#include "ra_ioctl.h"
#include "ra_rfrw.h"
#ifdef CONFIG_RAETH_NETLINK
#include "ra_netlink.h"
#endif
#if defined (CONFIG_RAETH_QOS)
#include "ra_qos.h"
#endif
#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
#include "../../../net/nat/hw_nat/ra_nat.h"
#endif
#if defined (TASKLET_WORKQUEUE_SW)
int init_schedule;
int working_schedule;
#endif
#ifdef CONFIG_RAETH_NAPI
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static int raeth_clean(struct napi_struct *napi, int budget);
#else
static int raeth_clean(struct net_device *dev, int *budget);
#endif
static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do);
#else
static int rt2880_eth_recv(struct net_device* dev);
#endif
#if !defined(CONFIG_RA_NAT_NONE)
/* bruce+
*/
extern int (*ra_sw_nat_hook_rx)(struct sk_buff *skb);
extern int (*ra_sw_nat_hook_tx)(struct sk_buff *skb, int gmac_no);
#endif
#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
/* Qwert+
*/
#include <asm/mipsregs.h>
extern int (*ra_classifier_hook_tx)(struct sk_buff *skb, unsigned long cur_cycle);
extern int (*ra_classifier_hook_rx)(struct sk_buff *skb, unsigned long cur_cycle);
#endif /* CONFIG_RA_CLASSIFIER */
#if defined (CONFIG_RALINK_RT3052_MP2)
int32_t mcast_rx(struct sk_buff * skb);
int32_t mcast_tx(struct sk_buff * skb);
#endif
#ifdef MTK_NEW_COMBO_EMMC_SUPPORT
int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf)
{
/* TODO */
return 0;
}
#else
#ifdef RA_MTD_RW_BY_NUM
int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
#else
int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
#endif
#endif
#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
void setup_internal_gsw(void);
#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
void apll_xtal_enable(void);
#define REGBIT(x, n) (x << n)
#endif
#endif
/* gmac driver feature set config */
#if defined (CONFIG_RAETH_NAPI) || defined (CONFIG_RAETH_QOS)
#undef DELAY_INT
#else
#define DELAY_INT 1
#endif
//#define CONFIG_UNH_TEST
/* end of config */
#if defined (CONFIG_RAETH_JUMBOFRAME)
#define MAX_RX_LENGTH 4096
#else
#define MAX_RX_LENGTH 1536
#endif
struct net_device *dev_raether;
static int rx_dma_owner_idx;
static int rx_dma_owner_idx0;
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
static int rx_dma_owner_idx1;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
int rx_calc_idx1;
#endif
#endif
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
int rx_calc_idx0;
#endif
static int pending_recv;
static struct PDMA_rxdesc *rx_ring;
unsigned long tx_ring_full=0;
#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
unsigned short p0_rx_good_cnt = 0;
unsigned short p1_rx_good_cnt = 0;
unsigned short p2_rx_good_cnt = 0;
unsigned short p3_rx_good_cnt = 0;
unsigned short p4_rx_good_cnt = 0;
unsigned short p5_rx_good_cnt = 0;
unsigned short p6_rx_good_cnt = 0;
unsigned short p0_tx_good_cnt = 0;
unsigned short p1_tx_good_cnt = 0;
unsigned short p2_tx_good_cnt = 0;
unsigned short p3_tx_good_cnt = 0;
unsigned short p4_tx_good_cnt = 0;
unsigned short p5_tx_good_cnt = 0;
unsigned short p6_tx_good_cnt = 0;
unsigned short p0_rx_byte_cnt = 0;
unsigned short p1_rx_byte_cnt = 0;
unsigned short p2_rx_byte_cnt = 0;
unsigned short p3_rx_byte_cnt = 0;
unsigned short p4_rx_byte_cnt = 0;
unsigned short p5_rx_byte_cnt = 0;
unsigned short p6_rx_byte_cnt = 0;
unsigned short p0_tx_byte_cnt = 0;
unsigned short p1_tx_byte_cnt = 0;
unsigned short p2_tx_byte_cnt = 0;
unsigned short p3_tx_byte_cnt = 0;
unsigned short p4_tx_byte_cnt = 0;
unsigned short p5_tx_byte_cnt = 0;
unsigned short p6_tx_byte_cnt = 0;
#if defined(CONFIG_RALINK_MT7620)
unsigned short p7_rx_good_cnt = 0;
unsigned short p7_tx_good_cnt = 0;
unsigned short p7_rx_byte_cnt = 0;
unsigned short p7_tx_byte_cnt = 0;
#endif
#endif
#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
#include "ra_ethtool.h"
extern struct ethtool_ops ra_ethtool_ops;
#ifdef CONFIG_PSEUDO_SUPPORT
extern struct ethtool_ops ra_virt_ethtool_ops;
#endif // CONFIG_PSEUDO_SUPPORT //
#endif // (CONFIG_ETHTOOL //
#ifdef CONFIG_RALINK_VISTA_BASIC
int is_switch_175c = 1;
#endif
unsigned int M2Q_table[64] = {0};
EXPORT_SYMBOL(M2Q_table);
#if defined (CONFIG_RAETH_LRO)
unsigned int lan_ip;
struct lro_para_struct lro_para;
int lro_flush_needed;
extern char const *nvram_get(int index, char *name);
#endif
#define KSEG1 0xa0000000
#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1))
#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1)
extern int fe_dma_init(struct net_device *dev);
extern int ei_start_xmit(struct sk_buff* skb, struct net_device *dev, int gmac_no);
extern void ei_xmit_housekeeping(unsigned long unused);
extern inline int rt2880_eth_send(struct net_device* dev, struct sk_buff *skb, int gmac_no);
#if 0
void skb_dump(struct sk_buff* sk) {
unsigned int i;
printk("skb_dump: from %s with len %d (%d) headroom=%d tailroom=%d\n",
sk->dev?sk->dev->name:"ip stack",sk->len,sk->truesize,
skb_headroom(sk),skb_tailroom(sk));
//for(i=(unsigned int)sk->head;i<=(unsigned int)sk->tail;i++) {
for(i=(unsigned int)sk->head;i<=(unsigned int)sk->data+20;i++) {
if((i % 20) == 0)
printk("\n");
if(i==(unsigned int)sk->data) printk("{");
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
if(i==(unsigned int)sk->transport_header) printk("#");
if(i==(unsigned int)sk->network_header) printk("|");
if(i==(unsigned int)sk->mac_header) printk("*");
#else
if(i==(unsigned int)sk->h.raw) printk("#");
if(i==(unsigned int)sk->nh.raw) printk("|");
if(i==(unsigned int)sk->mac.raw) printk("*");
#endif
printk("%02X-",*((unsigned char*)i));
if(i==(unsigned int)sk->tail) printk("}");
}
printk("\n");
}
#endif
#if defined (CONFIG_GIGAPHY) || defined (CONFIG_P5_MAC_TO_PHY_MODE) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
int isICPlusGigaPHY(int ge)
{
u32 phy_id0 = 0, phy_id1 = 0;
#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
if (ge == 2) {
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id1 = 0;
}
}
else
#endif
#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
{
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id1 = 0;
}
}
#endif
if ((phy_id0 == EV_ICPLUS_PHY_ID0) && ((phy_id1 & 0xfff0) == EV_ICPLUS_PHY_ID1))
return 1;
return 0;
}
int isMarvellGigaPHY(int ge)
{
u32 phy_id0 = 0, phy_id1 = 0;
#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
if (ge == 2) {
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id1 = 0;
}
}
else
#endif
#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
{
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id1 = 0;
}
}
#endif
;
if ((phy_id0 == EV_MARVELL_PHY_ID0) && (phy_id1 == EV_MARVELL_PHY_ID1))
return 1;
return 0;
}
int isVtssGigaPHY(int ge)
{
u32 phy_id0 = 0, phy_id1 = 0;
#if defined (CONFIG_GE2_RGMII_AN) || defined (CONFIG_P4_MAC_TO_PHY_MODE)
if (ge == 2) {
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 2, &phy_id0)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 3, &phy_id1)) {
printk("\n Read PhyID 1 is Fail!!\n");
phy_id1 = 0;
}
}
else
#endif
#if defined (CONFIG_GE1_RGMII_AN) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
{
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 2, &phy_id0)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id0 =0;
}
if (!mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 3, &phy_id1)) {
printk("\n Read PhyID 0 is Fail!!\n");
phy_id1 = 0;
}
}
#endif
;
if ((phy_id0 == EV_VTSS_PHY_ID0) && (phy_id1 == EV_VTSS_PHY_ID1))
return 1;
return 0;
}
#endif
/*
* Set the hardware MAC address.
*/
static int ei_set_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if(netif_running(dev))
return -EBUSY;
ra2880MacAddressSet(addr->sa_data);
return 0;
}
#ifdef CONFIG_PSEUDO_SUPPORT
static int ei_set_mac2_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
if(netif_running(dev))
return -EBUSY;
ra2880Mac2AddressSet(addr->sa_data);
return 0;
}
#endif
void set_fe_dma_glo_cfg(void)
{
int dma_glo_cfg=0;
#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
int fe_glo_cfg=0;
#endif
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)
dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_32DWORDS);
#elif defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621)
dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_16DWORDS);
#else
dma_glo_cfg = (TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN | PDMA_BT_SIZE_4DWORDS);
#endif
#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
dma_glo_cfg |= (RX_2B_OFFSET);
#endif
#if defined (CONFIG_32B_DESC)
dma_glo_cfg |= (DESC_32B_EN);
#endif
sysRegWrite(DMA_GLO_CFG, dma_glo_cfg);
#ifdef CONFIG_RAETH_QDMA
sysRegWrite(QDMA_GLO_CFG, dma_glo_cfg);
#endif
/* only the following chipset need to set it */
#if defined (CONFIG_RALINK_RT2880) || defined(CONFIG_RALINK_RT2883) || \
defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3883)
//set 1us timer count in unit of clock cycle
fe_glo_cfg = sysRegRead(FE_GLO_CFG);
fe_glo_cfg &= ~(0xff << 8); //clear bit8-bit15
fe_glo_cfg |= (((get_surfboard_sysclk()/1000000)) << 8);
sysRegWrite(FE_GLO_CFG, fe_glo_cfg);
#endif
}
int forward_config(struct net_device *dev)
{
#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
/* RT5350: No GDMA, PSE, CDMA, PPE */
unsigned int sdmVal;
sdmVal = sysRegRead(SDM_CON);
#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
sdmVal |= 0x7<<16; // UDPCS, TCPCS, IPCS=1
#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
#if defined (CONFIG_RAETH_SPECIAL_TAG)
sdmVal |= 0x1<<20; // TCI_81XX
#endif // CONFIG_RAETH_SPECIAL_TAG //
sysRegWrite(SDM_CON, sdmVal);
#else //Non RT5350 chipset
unsigned int regVal, regCsg;
#ifdef CONFIG_PSEUDO_SUPPORT
unsigned int regVal2;
#endif
#ifdef CONFIG_RAETH_HW_VLAN_TX
#if defined(CONFIG_RALINK_MT7620)
/* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x430) = 0x00010000;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x434) = 0x00030002;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x438) = 0x00050004;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x43C) = 0x00070006;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x440) = 0x00090008;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x444) = 0x000b000a;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x448) = 0x000d000c;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0x44C) = 0x000f000e;
#else
/*
* VLAN_IDX 0 = VLAN_ID 0
* .........
* VLAN_IDX 15 = VLAN ID 15
*
*/
/* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xa8) = 0x00010000;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xac) = 0x00030002;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb0) = 0x00050004;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb4) = 0x00070006;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xb8) = 0x00090008;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xbc) = 0x000b000a;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc0) = 0x000d000c;
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE + 0xc4) = 0x000f000e;
#endif
#endif
regVal = sysRegRead(GDMA1_FWD_CFG);
regCsg = sysRegRead(CDMA_CSG_CFG);
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 = sysRegRead(GDMA2_FWD_CFG);
#endif
//set unicast/multicast/broadcast frame to cpu
#if defined (CONFIG_RALINK_MT7620)
/* GDMA1 frames destination port is port0 CPU*/
regVal &= ~0x7;
#else
regVal &= ~0xFFFF;
regVal |= GDMA1_FWD_PORT;
#endif
regCsg &= ~0x7;
#if defined (CONFIG_RAETH_SPECIAL_TAG)
regVal |= (1 << 24); //GDM1_TCI_81xx
#endif
#ifdef CONFIG_RAETH_HW_VLAN_TX
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
dev->features |= NETIF_F_HW_VLAN_TX;
#else
dev->features |= NETIF_F_HW_VLAN_CTAG_TX;
#endif
#endif
#ifdef CONFIG_RAETH_HW_VLAN_RX
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
dev->features |= NETIF_F_HW_VLAN_RX;
#else
dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
#endif
#endif
#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
//enable ipv4 header checksum check
regVal |= GDM1_ICS_EN;
regCsg |= ICS_GEN_EN;
//enable tcp checksum check
regVal |= GDM1_TCS_EN;
regCsg |= TCS_GEN_EN;
//enable udp checksum check
regVal |= GDM1_UCS_EN;
regCsg |= UCS_GEN_EN;
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 &= ~0xFFFF;
regVal2 |= GDMA2_FWD_PORT;
regVal2 |= GDM1_ICS_EN;
regVal2 |= GDM1_TCS_EN;
regVal2 |= GDM1_UCS_EN;
#endif
dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
//#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
// dev->vlan_features |= NETIF_F_IP_CSUM;
//#endif
#if defined(CONFIG_RALINK_MT7620)
#if defined (CONFIG_RAETH_TSO)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
}
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
}
#endif // CONFIG_RAETH_TSOV6 //
#else
#if defined (CONFIG_RAETH_TSO)
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
#endif // CONFIG_RAETH_TSOV6 //
#endif // CONFIG_RALINK_MT7620 //
#else // Checksum offload disabled
//disable ipv4 header checksum check
regVal &= ~GDM1_ICS_EN;
regCsg &= ~ICS_GEN_EN;
//disable tcp checksum check
regVal &= ~GDM1_TCS_EN;
regCsg &= ~TCS_GEN_EN;
//disable udp checksum check
regVal &= ~GDM1_UCS_EN;
regCsg &= ~UCS_GEN_EN;
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 &= ~GDM1_ICS_EN;
regVal2 &= ~GDM1_TCS_EN;
regVal2 &= ~GDM1_UCS_EN;
#endif
dev->features &= ~NETIF_F_IP_CSUM; /* disable checksum TCP/UDP over IPv4 */
#endif // CONFIG_RAETH_CHECKSUM_OFFLOAD //
#ifdef CONFIG_RAETH_JUMBOFRAME
regVal |= GDM1_JMB_EN;
#ifdef CONFIG_PSEUDO_SUPPORT
regVal2 |= GDM1_JMB_EN;
#endif
#endif
sysRegWrite(GDMA1_FWD_CFG, regVal);
sysRegWrite(CDMA_CSG_CFG, regCsg);
#ifdef CONFIG_PSEUDO_SUPPORT
sysRegWrite(GDMA2_FWD_CFG, regVal2);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
dev->vlan_features = dev->features;
#endif
/*
* PSE_FQ_CFG register definition -
*
* Define max free queue page count in PSE. (31:24)
* RT2883/RT3883 - 0xff908000 (255 pages)
* RT3052 - 0x80504000 (128 pages)
* RT2880 - 0x80504000 (128 pages)
*
* In each page, there are 128 bytes in each page.
*
* 23:16 - free queue flow control release threshold
* 15:8 - free queue flow control assertion threshold
* 7:0 - free queue empty threshold
*
* The register affects QOS correctness in frame engine!
*/
#if defined(CONFIG_RALINK_RT2883) || defined(CONFIG_RALINK_RT3883)
sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_RT2883_PSE_FQ_CFG));
#elif defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || \
defined (CONFIG_RALINK_MT7628)
/*use default value*/
#else
sysRegWrite(PSE_FQ_CFG, cpu_to_le32(INIT_VALUE_OF_PSE_FQFC_CFG));
#endif
/*
*FE_RST_GLO register definition -
*Bit 0: PSE Rest
*Reset PSE after re-programming PSE_FQ_CFG.
*/
regVal = 0x1;
sysRegWrite(FE_RST_GL, regVal);
sysRegWrite(FE_RST_GL, 0); // update for RSTCTL issue
regCsg = sysRegRead(CDMA_CSG_CFG);
printk("CDMA_CSG_CFG = %0X\n",regCsg);
regVal = sysRegRead(GDMA1_FWD_CFG);
printk("GDMA1_FWD_CFG = %0X\n",regVal);
#ifdef CONFIG_PSEUDO_SUPPORT
regVal = sysRegRead(GDMA2_FWD_CFG);
printk("GDMA2_FWD_CFG = %0X\n",regVal);
#endif
#endif
return 1;
}
#ifdef CONFIG_RAETH_LRO
static int
rt_get_skb_header(struct sk_buff *skb, void **iphdr, void **tcph,
u64 *hdr_flags, void *priv)
{
struct iphdr *iph = NULL;
int vhdr_len = 0;
/*
* Make sure that this packet is Ethernet II, is not VLAN
* tagged, is IPv4, has a valid IP header, and is TCP.
*/
if (skb->protocol == 0x0081) {
vhdr_len = VLAN_HLEN;
}
iph = (struct iphdr *)(skb->data + vhdr_len);
if (iph->daddr != lro_para.lan_ip1) {
return -1;
}
if(iph->protocol != IPPROTO_TCP) {
return -1;
} else {
*iphdr = iph;
*tcph = skb->data + (iph->ihl << 2) + vhdr_len;
*hdr_flags = LRO_IPV4 | LRO_TCP;
lro_flush_needed = 1;
return 0;
}
}
#endif // CONFIG_RAETH_LRO //
#ifdef CONFIG_RAETH_NAPI
static int rt2880_eth_recv(struct net_device* dev, int *work_done, int work_to_do)
#else
static int rt2880_eth_recv(struct net_device* dev)
#endif
{
struct sk_buff *skb, *rx_skb;
unsigned int length = 0;
unsigned long RxProcessed;
int bReschedule = 0;
END_DEVICE* ei_local = netdev_priv(dev);
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
int rx_ring_no=0;
#endif
#if defined (CONFIG_RAETH_SPECIAL_TAG)
struct vlan_ethhdr *veth=NULL;
#endif
#ifdef CONFIG_PSEUDO_SUPPORT
PSEUDO_ADAPTER *pAd;
#endif
RxProcessed = 0;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx0 = (rx_calc_idx0 + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
#endif
#if defined (CONFIG_32B_DESC)
#if defined (CONFIG_MIPS)
dma_cache_sync(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#else
dma_sync_single_for_cpu(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#endif
#endif
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx1 = (rx_calc_idx1 + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx1 = (sysRegRead(RX_CALC_IDX1) + 1) % NUM_RX_DESC;
#endif
#if defined (CONFIG_32B_DESC)
#if defined (CONFIG_MIPS)
dma_cache_sync(NULL, &ei_local->rx_ring1[rx_dma_owner_idx1], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#else
dma_sync_single_for_cpu(NULL, &ei_local->rx_ring0[rx_dma_owner_idx0], sizeof(struct PDMA_rxdesc), DMA_FROM_DEVICE);
#endif
#endif
#endif
for ( ; ; ) {
#ifdef CONFIG_RAETH_NAPI
if(*work_done >= work_to_do)
break;
(*work_done)++;
#else
if (RxProcessed++ > NUM_RX_MAX_PROCESS)
{
// need to reschedule rx handle
bReschedule = 1;
break;
}
#endif
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if (ei_local->rx_ring1[rx_dma_owner_idx1].rxd_info2.DDONE_bit == 1) {
rx_ring = ei_local->rx_ring1;
rx_dma_owner_idx = rx_dma_owner_idx1;
// printk("rx_dma_owner_idx1=%x\n",rx_dma_owner_idx1);
rx_ring_no=1;
} else if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
rx_ring = ei_local->rx_ring0;
rx_dma_owner_idx = rx_dma_owner_idx0;
// printk("rx_dma_owner_idx0=%x\n",rx_dma_owner_idx0);
rx_ring_no=0;
} else {
break;
}
#else
if (ei_local->rx_ring0[rx_dma_owner_idx0].rxd_info2.DDONE_bit == 1) {
rx_ring = ei_local->rx_ring0;
rx_dma_owner_idx = rx_dma_owner_idx0;
} else {
break;
}
#endif
#if defined (CONFIG_32B_DESC)
prefetch(&rx_ring[(rx_dma_owner_idx + 1) % NUM_RX_DESC]);
#endif
/* skb processing */
length = rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0;
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if(rx_ring_no==1) {
rx_skb = ei_local->netrx1_skbuf[rx_dma_owner_idx];
rx_skb->data = ei_local->netrx1_skbuf[rx_dma_owner_idx]->data;
} else {
rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
}
#else
rx_skb = ei_local->netrx0_skbuf[rx_dma_owner_idx];
rx_skb->data = ei_local->netrx0_skbuf[rx_dma_owner_idx]->data;
#endif
rx_skb->len = length;
#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
rx_skb->data += NET_IP_ALIGN;
#endif
rx_skb->tail = rx_skb->data + length;
#ifdef CONFIG_PSEUDO_SUPPORT
if(rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
if(ei_local->PseudoDev!=NULL) {
rx_skb->dev = ei_local->PseudoDev;
rx_skb->protocol = eth_type_trans(rx_skb,ei_local->PseudoDev);
}else {
printk("ERROR: PseudoDev is still not initialize but receive packet from GMAC2\n");
}
}else{
rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb,dev);
}
#else
rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb,dev);
#endif
#ifdef CONFIG_RAETH_CHECKSUM_OFFLOAD
#if defined (CONFIG_PDMA_NEW)
if(rx_ring[rx_dma_owner_idx].rxd_info4.L4VLD) {
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
}else {
rx_skb->ip_summed = CHECKSUM_NONE;
}
#else
if(rx_ring[rx_dma_owner_idx].rxd_info4.IPFVLD_bit) {
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
}else {
rx_skb->ip_summed = CHECKSUM_NONE;
}
#endif
#else
rx_skb->ip_summed = CHECKSUM_NONE;
#endif
#if defined(CONFIG_RA_CLASSIFIER)||defined(CONFIG_RA_CLASSIFIER_MODULE)
/* Qwert+
*/
if(ra_classifier_hook_rx!= NULL)
{
#if defined(CONFIG_RALINK_EXTERNAL_TIMER)
ra_classifier_hook_rx(rx_skb, (*((volatile u32 *)(0xB0000D08))&0x0FFFF));
#else
ra_classifier_hook_rx(rx_skb, read_c0_count());
#endif
}
#endif /* CONFIG_RA_CLASSIFIER */
#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE)
if(ra_sw_nat_hook_rx != NULL) {
FOE_MAGIC_TAG(rx_skb)= FOE_MAGIC_GE;
*(uint32_t *)(FOE_INFO_START_ADDR(rx_skb)+2) = *(uint32_t *)&rx_ring[rx_dma_owner_idx].rxd_info4;
FOE_ALG(rx_skb) = 0;
}
#endif
/* We have to check the free memory size is big enough
* before pass the packet to cpu*/
#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
skb = skbmgr_dev_alloc_skb2k();
#else
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
skb = alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
#else
skb = __dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN, GFP_ATOMIC);
#endif
#endif
if (unlikely(skb == NULL))
{
printk(KERN_ERR "skb not available...\n");
#ifdef CONFIG_PSEUDO_SUPPORT
if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
if (ei_local->PseudoDev != NULL) {
pAd = netdev_priv(ei_local->PseudoDev);
pAd->stat.rx_dropped++;
}
} else
#endif
ei_local->stat.rx_dropped++;
bReschedule = 1;
break;
}
#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
skb_reserve(skb, NET_IP_ALIGN);
#endif
#if defined (CONFIG_RAETH_SPECIAL_TAG)
// port0: 0x8100 => 0x8100 0001
// port1: 0x8101 => 0x8100 0002
// port2: 0x8102 => 0x8100 0003
// port3: 0x8103 => 0x8100 0004
// port4: 0x8104 => 0x8100 0005
// port5: 0x8105 => 0x8100 0006
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)
veth = (struct vlan_ethhdr *)(rx_skb->mac_header);
#else
veth = (struct vlan_ethhdr *)(rx_skb->mac.raw);
#endif
/*donot check 0x81 due to MT7530 SPEC*/
//if((veth->h_vlan_proto & 0xFF) == 0x81)
{
veth->h_vlan_TCI = htons( (((veth->h_vlan_proto >> 8) & 0xF) + 1) );
rx_skb->protocol = veth->h_vlan_proto = htons(ETH_P_8021Q);
}
#endif
/* ra_sw_nat_hook_rx return 1 --> continue
* ra_sw_nat_hook_rx return 0 --> FWD & without netif_rx
*/
#if !defined(CONFIG_RA_NAT_NONE)
if((ra_sw_nat_hook_rx == NULL) ||
(ra_sw_nat_hook_rx!= NULL && ra_sw_nat_hook_rx(rx_skb)))
#endif
{
#if defined (CONFIG_RALINK_RT3052_MP2)
if(mcast_rx(rx_skb)==0) {
kfree_skb(rx_skb);
}else
#endif
#if defined (CONFIG_RAETH_LRO)
if (rx_skb->ip_summed == CHECKSUM_UNNECESSARY) {
lro_receive_skb(&ei_local->lro_mgr, rx_skb, NULL);
//LroStatsUpdate(&ei_local->lro_mgr,0);
} else
#endif
#ifdef CONFIG_RAETH_NAPI
netif_receive_skb(rx_skb);
#else
#ifdef CONFIG_RAETH_HW_VLAN_RX
if(ei_local->vlgrp && rx_ring[rx_dma_owner_idx].rxd_info2.TAG) {
vlan_hwaccel_rx(rx_skb, ei_local->vlgrp, rx_ring[rx_dma_owner_idx].rxd_info3.VID);
} else {
netif_rx(rx_skb);
}
#else
#ifdef CONFIG_RAETH_CPU_LOOPBACK
skb_push(rx_skb,ETH_HLEN);
ei_start_xmit(rx_skb, dev, 1);
#else
netif_rx(rx_skb);
#endif
#endif
#endif
}
#ifdef CONFIG_PSEUDO_SUPPORT
if (rx_ring[rx_dma_owner_idx].rxd_info4.SP == 2) {
if (ei_local->PseudoDev != NULL) {
pAd = netdev_priv(ei_local->PseudoDev);
pAd->stat.rx_packets++;
pAd->stat.rx_bytes += length;
}
} else
#endif
{
ei_local->stat.rx_packets++;
ei_local->stat.rx_bytes += length;
}
#if defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
rx_ring[rx_dma_owner_idx].rxd_info2.PLEN0 = MAX_RX_LENGTH;
rx_ring[rx_dma_owner_idx].rxd_info2.LS0 = 0;
#endif
rx_ring[rx_dma_owner_idx].rxd_info2.DDONE_bit = 0;
rx_ring[rx_dma_owner_idx].rxd_info1.PDP0 = dma_map_single(NULL, skb->data, MAX_RX_LENGTH, PCI_DMA_FROMDEVICE);
#ifdef CONFIG_32B_DESC
dma_cache_sync(NULL, &rx_ring[rx_dma_owner_idx], sizeof(struct PDMA_rxdesc), DMA_TO_DEVICE);
#endif
/* Move point to next RXD which wants to alloc*/
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if(rx_ring_no==0) {
sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_calc_idx0 = rx_dma_owner_idx;
#endif
}else {
sysRegWrite(RAETH_RX_CALC_IDX1, rx_dma_owner_idx);
ei_local->netrx1_skbuf[rx_dma_owner_idx] = skb;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_calc_idx1 = rx_dma_owner_idx;
#endif
}
#else
sysRegWrite(RAETH_RX_CALC_IDX0, rx_dma_owner_idx);
ei_local->netrx0_skbuf[rx_dma_owner_idx] = skb;
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_calc_idx0 = rx_dma_owner_idx;
#endif
#endif
/* Update to Next packet point that was received.
*/
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if(rx_ring_no==0) {
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
#endif
}else {
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx1 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx1 = (sysRegRead(RAETH_RX_CALC_IDX1) + 1) % NUM_RX_DESC;
#endif
}
#else
#ifdef CONFIG_RAETH_RW_PDMAPTR_FROM_VAR
rx_dma_owner_idx0 = (rx_dma_owner_idx + 1) % NUM_RX_DESC;
#else
rx_dma_owner_idx0 = (sysRegRead(RAETH_RX_CALC_IDX0) + 1) % NUM_RX_DESC;
#endif
#endif
} /* for */
#if defined (CONFIG_RAETH_LRO)
if (lro_flush_needed) {
//LroStatsUpdate(&ei_local->lro_mgr,1);
lro_flush_all(&ei_local->lro_mgr);
lro_flush_needed = 0;
}
#endif
return bReschedule;
}
///////////////////////////////////////////////////////////////////
/////
///// ra_get_stats - gather packet information for management plane
/////
///// Pass net_device_stats to the upper layer.
/////
/////
///// RETURNS: pointer to net_device_stats
///////////////////////////////////////////////////////////////////
struct net_device_stats *ra_get_stats(struct net_device *dev)
{
END_DEVICE *ei_local = netdev_priv(dev);
return &ei_local->stat;
}
#if defined (CONFIG_RT_3052_ESW)
void kill_sig_workq(struct work_struct *work)
{
struct file *fp;
char pid[8];
struct task_struct *p = NULL;
//read udhcpc pid from file, and send signal USR2,USR1 to get a new IP
fp = filp_open("/var/run/udhcpc.pid", O_RDONLY, 0);
if (IS_ERR(fp))
return;
if (fp->f_op && fp->f_op->read) {
if (fp->f_op->read(fp, pid, 8, &fp->f_pos) > 0) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
p = pid_task(find_get_pid(simple_strtoul(pid, NULL, 10)), PIDTYPE_PID);
#else
p = find_task_by_pid(simple_strtoul(pid, NULL, 10));
#endif
if (NULL != p) {
send_sig(SIGUSR2, p, 0);
send_sig(SIGUSR1, p, 0);
}
}
}
filp_close(fp, NULL);
}
#endif
///////////////////////////////////////////////////////////////////
/////
///// ra2880Recv - process the next incoming packet
/////
///// Handle one incoming packet. The packet is checked for errors and sent
///// to the upper layer.
/////
///// RETURNS: OK on success or ERROR.
///////////////////////////////////////////////////////////////////
#ifndef CONFIG_RAETH_NAPI
#if defined WORKQUEUE_BH || defined (TASKLET_WORKQUEUE_SW)
void ei_receive_workq(struct work_struct *work)
#else
void ei_receive(unsigned long unused) // device structure
#endif // WORKQUEUE_BH //
{
struct net_device *dev = dev_raether;
END_DEVICE *ei_local = netdev_priv(dev);
unsigned long reg_int_mask=0;
int bReschedule=0;
if(tx_ring_full==0){
bReschedule = rt2880_eth_recv(dev);
if(bReschedule)
{
#ifdef WORKQUEUE_BH
schedule_work(&ei_local->rx_wq);
#else
#if defined (TASKLET_WORKQUEUE_SW)
if (working_schedule == 1)
schedule_work(&ei_local->rx_wq);
else
#endif
tasklet_hi_schedule(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
}else{
reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
#if defined(DELAY_INT)
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
#else
sysRegWrite(RAETH_FE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1));
#endif
#ifdef CONFIG_RAETH_QDMA
reg_int_mask=sysRegRead(QFE_INT_ENABLE);
#if defined(DELAY_INT)
sysRegWrite(QFE_INT_ENABLE, reg_int_mask| RX_DLY_INT);
#else
sysRegWrite(QFE_INT_ENABLE, (reg_int_mask | RX_DONE_INT0 | RX_DONE_INT1));
#endif
#endif
}
}else{
#ifdef WORKQUEUE_BH
schedule_work(&ei_local->rx_wq);
#else
#if defined (TASKLET_WORKQUEUE_SW)
if (working_schedule == 1)
schedule_work(&ei_local->rx_wq);
else
#endif
tasklet_schedule(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
}
}
#endif
#ifdef CONFIG_RAETH_NAPI
static int
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
raeth_clean(struct napi_struct *napi, int budget)
#else
raeth_clean(struct net_device *netdev, int *budget)
#endif
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
struct net_device *netdev=dev_raether;
int work_to_do = budget;
#else
int work_to_do = min(*budget, netdev->quota);
#endif
END_DEVICE *ei_local =netdev_priv(netdev);
int work_done = 0;
unsigned long reg_int_mask=0;
ei_xmit_housekeeping(0);
rt2880_eth_recv(netdev, &work_done, work_to_do);
/* this could control when to re-enable interrupt, 0-> mean never enable interrupt*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
*budget -= work_done;
netdev->quota -= work_done;
#endif
/* if no Tx and not enough Rx work done, exit the polling mode */
if(( (work_done < work_to_do)) || !netif_running(netdev)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
napi_complete(&ei_local->napi);
#else
netif_rx_complete(netdev);
#endif
atomic_dec_and_test(&ei_local->irq_sem);
sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL); // ack all fe interrupts
reg_int_mask=sysRegRead(RAETH_FE_INT_ENABLE);
#ifdef DELAY_INT
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask |RAETH_FE_INT_DLY_INIT); // init delay interrupt only
#else
sysRegWrite(RAETH_FE_INT_ENABLE,reg_int_mask | RAETH_FE_INT_SETTING);
#endif
#ifdef CONFIG_RAETH_QDMA
sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
reg_int_mask=sysRegRead(QFE_INT_ENABLE);
#ifdef DELAY_INT
sysRegWrite(QFE_INT_ENABLE, reg_int_mask |QFE_INT_DLY_INIT); // init delay interrupt only
#else
sysRegWrite(QFE_INT_ENABLE,reg_int_mask | (RX_DONE_INT0 | RX_DONE_INT1 | RLS_DONE_INT));
#endif
#endif // CONFIG_RAETH_QDMA //
return 0;
}
return 1;
}
#endif
void gsw_delay_setting(void)
{
#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
END_DEVICE *ei_local = netdev_priv(dev_raether);
int reg_int_val = 0;
int link_speed = 0;
reg_int_val = sysRegRead(FE_INT_STATUS2);
if( reg_int_val & BIT(25))
{
if(sysRegRead(RALINK_ETH_SW_BASE+0x0208) & 0x1) // link up
{
link_speed = (sysRegRead(RALINK_ETH_SW_BASE+0x0208)>>2 & 0x3);
if(link_speed == 1)
{
// delay setting for 100M
if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
mii_mgr_write(31, 0x7b00, 8);
printk("MT7621 GE2 link rate to 100M\n");
} else
{
//delay setting for 10/1000M
if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101)
mii_mgr_write(31, 0x7b00, 0x102);
printk("MT7621 GE2 link rate to 10M/1G\n");
}
schedule_work(&ei_local->kill_sig_wq);
}
}
sysRegWrite(FE_INT_STATUS2, reg_int_val);
#endif
}
/**
* ei_interrupt - handle controler interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
static irqreturn_t ei_interrupt(int irq, void *dev_id)
#else
static irqreturn_t ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
#endif
{
#if !defined(CONFIG_RAETH_NAPI)
unsigned long reg_int_val;
unsigned long reg_int_mask=0;
unsigned int recv = 0;
unsigned int transmit __maybe_unused = 0;
unsigned long flags;
#endif
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
//Qwert
/*
unsigned long old,cur,dcycle;
static int cnt = 0;
static unsigned long max_dcycle = 0,tcycle = 0;
old = read_c0_count();
*/
if (dev == NULL)
{
printk (KERN_ERR "net_interrupt(): irq %x for unknown device.\n", IRQ_ENET0);
return IRQ_NONE;
}
#ifdef CONFIG_RAETH_NAPI
gsw_delay_setting();
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
if(napi_schedule_prep(&ei_local->napi)) {
#else
if(netif_rx_schedule_prep(dev)) {
#endif
atomic_inc(&ei_local->irq_sem);
sysRegWrite(RAETH_FE_INT_ENABLE, 0);
#ifdef CONFIG_RAETH_QDMA
sysRegWrite(QFE_INT_ENABLE, 0);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
__napi_schedule(&ei_local->napi);
#else
__netif_rx_schedule(dev);
#endif
}
#else
spin_lock_irqsave(&(ei_local->page_lock), flags);
reg_int_val = sysRegRead(RAETH_FE_INT_STATUS);
#ifdef CONFIG_RAETH_QDMA
reg_int_val |= sysRegRead(QFE_INT_STATUS);
#endif
#if defined (DELAY_INT)
if((reg_int_val & RX_DLY_INT))
recv = 1;
if (reg_int_val & RAETH_TX_DLY_INT)
transmit = 1;
#else
if((reg_int_val & RX_DONE_INT0))
recv = 1;
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if((reg_int_val & RX_DONE_INT1))
recv = 1;
#endif
if (reg_int_val & RAETH_TX_DONE_INT0)
transmit |= RAETH_TX_DONE_INT0;
#if defined (CONFIG_RAETH_QOS)
if (reg_int_val & TX_DONE_INT1)
transmit |= TX_DONE_INT1;
if (reg_int_val & TX_DONE_INT2)
transmit |= TX_DONE_INT2;
if (reg_int_val & TX_DONE_INT3)
transmit |= TX_DONE_INT3;
#endif //CONFIG_RAETH_QOS
#endif //DELAY_INT
#if defined (DELAY_INT)
sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_DLY_INIT);
#else
sysRegWrite(RAETH_FE_INT_STATUS, RAETH_FE_INT_ALL);
#endif
#ifdef CONFIG_RAETH_QDMA
#if defined (DELAY_INT)
sysRegWrite(QFE_INT_STATUS, QFE_INT_DLY_INIT);
#else
sysRegWrite(QFE_INT_STATUS, QFE_INT_ALL);
#endif
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
if(transmit)
ei_xmit_housekeeping(0);
#else
ei_xmit_housekeeping(0);
#endif
if (((recv == 1) || (pending_recv ==1)) && (tx_ring_full==0))
{
reg_int_mask = sysRegRead(RAETH_FE_INT_ENABLE);
#if defined (DELAY_INT)
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
#else
sysRegWrite(RAETH_FE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1));
#endif //DELAY_INT
#ifdef CONFIG_RAETH_QDMA
reg_int_mask = sysRegRead(QFE_INT_ENABLE);
#if defined (DELAY_INT)
sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DLY_INT));
#else
sysRegWrite(QFE_INT_ENABLE, reg_int_mask & ~(RX_DONE_INT0 | RX_DONE_INT1));
#endif //DELAY_INT
#endif
pending_recv=0;
#ifdef WORKQUEUE_BH
schedule_work(&ei_local->rx_wq);
#else
#if defined (TASKLET_WORKQUEUE_SW)
if (working_schedule == 1)
schedule_work(&ei_local->rx_wq);
else
#endif
tasklet_hi_schedule(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
}
else if (recv == 1 && tx_ring_full==1)
{
pending_recv=1;
}
else if((recv == 0) && (transmit == 0))
{
gsw_delay_setting();
}
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
#endif
return IRQ_HANDLED;
}
#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \
defined (CONFIG_RALINK_MT7620)|| defined (CONFIG_RALINK_MT7621)
static void esw_link_status_changed(int port_no, void *dev_id)
{
unsigned int reg_val;
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined (CONFIG_RALINK_MT7620)
reg_val = *((volatile u32 *)(RALINK_ETH_SW_BASE+ 0x3008 + (port_no*0x100)));
#elif defined (CONFIG_RALINK_MT7621)
mii_mgr_read(31, (0x3008 + (port_no*0x100)), &reg_val);
#endif
if(reg_val & 0x1) {
printk("ESW: Link Status Changed - Port%d Link UP\n", port_no);
#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(port_no, 31, 0x52b5);
mii_mgr_write(port_no, 16, 0xb780);
mii_mgr_write(port_no, 17, 0x00e0);
mii_mgr_write(port_no, 16, 0x9780);
#endif
#if defined (CONFIG_WAN_AT_P0)
if(port_no==0) {
schedule_work(&ei_local->kill_sig_wq);
}
#elif defined (CONFIG_WAN_AT_P4)
if(port_no==4) {
schedule_work(&ei_local->kill_sig_wq);
}
#endif
} else {
printk("ESW: Link Status Changed - Port%d Link Down\n", port_no);
#if defined (CONFIG_RALINK_MT7621) && defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(port_no, 31, 0x52b5);
mii_mgr_write(port_no, 16, 0xb780);
mii_mgr_write(port_no, 17, 0x0000);
mii_mgr_write(port_no, 16, 0x9780);
#endif
}
}
#endif
#if defined (CONFIG_RT_3052_ESW) && ! defined(CONFIG_RALINK_MT7621)
static irqreturn_t esw_interrupt(int irq, void *dev_id)
{
unsigned long flags;
unsigned long reg_int_val;
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
unsigned long acl_int_val;
unsigned long mib_int_val;
#else
static unsigned long stat;
unsigned long stat_curr;
#endif
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
spin_lock_irqsave(&(ei_local->page_lock), flags);
reg_int_val = (*((volatile u32 *)(ESW_ISR))); //Interrupt Status Register
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
if (reg_int_val & P5_LINK_CH) {
esw_link_status_changed(5, dev_id);
}
if (reg_int_val & P4_LINK_CH) {
esw_link_status_changed(4, dev_id);
}
if (reg_int_val & P3_LINK_CH) {
esw_link_status_changed(3, dev_id);
}
if (reg_int_val & P2_LINK_CH) {
esw_link_status_changed(2, dev_id);
}
if (reg_int_val & P1_LINK_CH) {
esw_link_status_changed(1, dev_id);
}
if (reg_int_val & P0_LINK_CH) {
esw_link_status_changed(0, dev_id);
}
if (reg_int_val & ACL_INT) {
acl_int_val = sysRegRead(ESW_AISR);
sysRegWrite(ESW_AISR, acl_int_val);
}
if (reg_int_val & MIB_INT) {
mib_int_val = sysRegRead(ESW_P0_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P0_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p0_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p0_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p0_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p0_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P1_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P1_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p1_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p1_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p1_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p1_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P2_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P2_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p2_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p2_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p2_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p2_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P3_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P3_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p3_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p3_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p3_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p3_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P4_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P4_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p4_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p4_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p4_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p4_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P5_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P5_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p5_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p5_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p5_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p5_tx_byte_cnt ++;
}
mib_int_val = sysRegRead(ESW_P6_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P6_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p6_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p6_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p6_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p6_tx_byte_cnt ++;
}
#if defined (CONFIG_RALINK_MT7620)
mib_int_val = sysRegRead(ESW_P7_IntSn);
if(mib_int_val){
sysRegWrite(ESW_P7_IntSn, mib_int_val);
if(mib_int_val & RX_GOOD_CNT)
p7_rx_good_cnt ++;
if(mib_int_val & TX_GOOD_CNT)
p7_tx_good_cnt ++;
if(mib_int_val & RX_GOCT_CNT)
p7_rx_byte_cnt ++;
if(mib_int_val & TX_GOCT_CNT)
p7_tx_byte_cnt ++;
}
#endif
}
#else // not RT6855
if (reg_int_val & PORT_ST_CHG) {
printk("RT305x_ESW: Link Status Changed\n");
stat_curr = *((volatile u32 *)(RALINK_ETH_SW_BASE+0x80));
#ifdef CONFIG_WAN_AT_P0
//link down --> link up : send signal to user application
//link up --> link down : ignore
if ((stat & (1<<25)) || !(stat_curr & (1<<25)))
#else
if ((stat & (1<<29)) || !(stat_curr & (1<<29)))
#endif
goto out;
schedule_work(&ei_local->kill_sig_wq);
out:
stat = stat_curr;
}
#endif // defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A)//
sysRegWrite(ESW_ISR, reg_int_val);
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
return IRQ_HANDLED;
}
#elif defined (CONFIG_RT_3052_ESW) && defined(CONFIG_RALINK_MT7621)
static irqreturn_t esw_interrupt(int irq, void *dev_id)
{
unsigned long flags;
unsigned int reg_int_val;
struct net_device *dev = (struct net_device *) dev_id;
END_DEVICE *ei_local = netdev_priv(dev);
spin_lock_irqsave(&(ei_local->page_lock), flags);
mii_mgr_read(31, 0x700c, &reg_int_val);
if (reg_int_val & P4_LINK_CH) {
esw_link_status_changed(4, dev_id);
}
if (reg_int_val & P3_LINK_CH) {
esw_link_status_changed(3, dev_id);
}
if (reg_int_val & P2_LINK_CH) {
esw_link_status_changed(2, dev_id);
}
if (reg_int_val & P1_LINK_CH) {
esw_link_status_changed(1, dev_id);
}
if (reg_int_val & P0_LINK_CH) {
esw_link_status_changed(0, dev_id);
}
mii_mgr_write(31, 0x700c, 0x1f); //ack switch link change
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
return IRQ_HANDLED;
}
#endif
static int ei_start_xmit_fake(struct sk_buff* skb, struct net_device *dev)
{
return ei_start_xmit(skb, dev, 1);
}
#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
void dump_phy_reg(int port_no, int from, int to, int is_local)
{
u32 i=0;
u32 temp=0;
if(is_local==0) {
printk("Global Register\n");
printk("===============");
mii_mgr_write(0, 31, 0); //select global register
for(i=from;i<=to;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
} else {
mii_mgr_write(0, 31, 0x8000); //select local register
printk("\n\nLocal Register Port %d\n",port_no);
printk("===============");
for(i=from;i<=to;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
}
printk("\n");
}
#else
void dump_phy_reg(int port_no, int from, int to, int is_local, int page_no)
{
u32 i=0;
u32 temp=0;
u32 r31=0;
if(is_local==0) {
printk("\n\nGlobal Register Page %d\n",page_no);
printk("===============");
r31 |= 0 << 15; //global
r31 |= ((page_no&0x7) << 12); //page no
mii_mgr_write(port_no, 31, r31); //select global page x
for(i=16;i<32;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
}else {
printk("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
printk("===============");
r31 |= 1 << 15; //local
r31 |= ((page_no&0x7) << 12); //page no
mii_mgr_write(port_no, 31, r31); //select local page x
for(i=16;i<32;i++) {
if(i%8==0) {
printk("\n");
}
mii_mgr_read(port_no,i, &temp);
printk("%02d: %04X ",i, temp);
}
}
printk("\n");
}
#endif
int ei_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
#if defined(CONFIG_RT_3052_ESW) || defined(CONFIG_RAETH_QDMA)
esw_reg reg;
#endif
#if defined(CONFIG_RALINK_RT3352) || defined(CONFIG_RALINK_RT5350) || \
defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628)
esw_rate ratelimit;
#endif
#if defined(CONFIG_RT_3052_ESW)
unsigned int offset = 0;
unsigned int value = 0;
#endif
ra_mii_ioctl_data mii;
switch (cmd) {
#if defined(CONFIG_RAETH_QDMA)
#define _HQOS_REG(x) (*((volatile u32 *)(RALINK_FRAME_ENGINE_BASE + QDMA_RELATED + x)))
case RAETH_QDMA_REG_READ:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_HQOS_MAX)
return -EINVAL;
reg.val = _HQOS_REG(reg.off);
//printk("read reg off:%x val:%x\n", reg.off, reg.val);
copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
break;
case RAETH_QDMA_REG_WRITE:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_HQOS_MAX)
return -EINVAL;
_HQOS_REG(reg.off) = reg.val;
//printk("write reg off:%x val:%x\n", reg.off, reg.val);
break;
case RAETH_QDMA_READ_CPU_CLK:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
reg.val = get_surfboard_sysclk();
//printk("read reg off:%x val:%x\n", reg.off, reg.val);
copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
break;
case RAETH_QDMA_QUEUE_MAPPING:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
M2Q_table[reg.off] = reg.val;
//printk(" M2Q_table[%d] is %d.\n", reg.off, M2Q_table[reg.off]);
break;
#endif
case RAETH_MII_READ:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
break;
case RAETH_MII_WRITE:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
break;
#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_ARCH_MT8590)
case RAETH_MII_READ_CL45:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
mii_mgr_read_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, &mii.val_out);
copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
break;
case RAETH_MII_WRITE_CL45:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//mii_mgr_cl45_set_address(mii.port_num, mii.dev_addr, mii.reg_addr);
mii_mgr_write_cl45(mii.port_num, mii.dev_addr, mii.reg_addr, mii.val_in);
break;
#endif
#if defined(CONFIG_RT_3052_ESW)
#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
case RAETH_ESW_REG_READ:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_ESW_MAX)
return -EINVAL;
reg.val = _ESW_REG(reg.off);
//printk("read reg off:%x val:%x\n", reg.off, reg.val);
copy_to_user(ifr->ifr_data, &reg, sizeof(reg));
break;
case RAETH_ESW_REG_WRITE:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
if (reg.off > REG_ESW_MAX)
return -EINVAL;
_ESW_REG(reg.off) = reg.val;
//printk("write reg off:%x val:%x\n", reg.off, reg.val);
break;
case RAETH_ESW_PHY_DUMP:
copy_from_user(&reg, ifr->ifr_data, sizeof(reg));
#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350)
if (reg.val ==32 ) {//dump all phy register
/* Global Register 0~31
* Local Register 0~31
*/
dump_phy_reg(0, 0, 31, 0); //dump global register
for(offset=0;offset<5;offset++) {
dump_phy_reg(offset, 0, 31, 1); //dump local register
}
} else {
dump_phy_reg(reg.val, 0, 31, 0); //dump global register
dump_phy_reg(reg.val, 0, 31, 1); //dump local register
}
#else
/* SPEC defined Register 0~15
* Global Register 16~31 for each page
* Local Register 16~31 for each page
*/
printk("SPEC defined Register");
if (reg.val ==32 ) {//dump all phy register
int i = 0;
for(i=0; i<5; i++){
printk("\n[Port %d]===============",i);
for(offset=0;offset<16;offset++) {
if(offset%8==0) {
printk("\n");
}
mii_mgr_read(i,offset, &value);
printk("%02d: %04X ",offset, value);
}
}
}
else{
printk("\n[Port %d]===============",reg.val);
for(offset=0;offset<16;offset++) {
if(offset%8==0) {
printk("\n");
}
mii_mgr_read(reg.val,offset, &value);
printk("%02d: %04X ",offset, value);
}
}
#if defined (CONFIG_RALINK_MT7628)
for(offset=0;offset<7;offset++) { //global register page 0~6
#else
for(offset=0;offset<5;offset++) { //global register page 0~4
#endif
if(reg.val == 32) //dump all phy register
dump_phy_reg(0, 16, 31, 0, offset);
else
dump_phy_reg(reg.val, 16, 31, 0, offset);
}
if (reg.val == 32) {//dump all phy register
#if !defined (CONFIG_RAETH_HAS_PORT4)
for(offset=0;offset<5;offset++) { //local register port 0-port4
#else
for(offset=0;offset<4;offset++) { //local register port 0-port3
#endif
dump_phy_reg(offset, 16, 31, 1, 0); //dump local page 0
dump_phy_reg(offset, 16, 31, 1, 1); //dump local page 1
dump_phy_reg(offset, 16, 31, 1, 2); //dump local page 2
dump_phy_reg(offset, 16, 31, 1, 3); //dump local page 3
}
}else {
dump_phy_reg(reg.val, 16, 31, 1, 0); //dump local page 0
dump_phy_reg(reg.val, 16, 31, 1, 1); //dump local page 1
dump_phy_reg(reg.val, 16, 31, 1, 2); //dump local page 2
dump_phy_reg(reg.val, 16, 31, 1, 3); //dump local page 3
}
#endif
break;
#if defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
case RAETH_ESW_INGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
offset = 0x11c + (4 * (ratelimit.port / 2));
value = _ESW_REG(offset);
if((ratelimit.port % 2) == 0)
{
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 14);
value |= (0x07 << 10);
value |= ratelimit.bw;
}
}
else if((ratelimit.port % 2) == 1)
{
value &= 0x0000ffff;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 30);
value |= (0x07 << 26);
value |= (ratelimit.bw << 16);
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
_ESW_REG(offset) = value;
break;
case RAETH_ESW_EGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
offset = 0x140 + (4 * (ratelimit.port / 2));
value = _ESW_REG(offset);
if((ratelimit.port % 2) == 0)
{
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 12);
value |= (0x03 << 10);
value |= ratelimit.bw;
}
}
else if((ratelimit.port % 2) == 1)
{
value &= 0x0000ffff;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 28);
value |= (0x03 << 26);
value |= (ratelimit.bw << 16);
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
_ESW_REG(offset) = value;
break;
#elif defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621)
#define _ESW_REG(x) (*((volatile u32 *)(RALINK_ETH_SW_BASE + x)))
case RAETH_ESW_INGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
#if defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7621)
offset = 0x1800 + (0x100 * ratelimit.port);
#else
offset = 0x1080 + (0x100 * ratelimit.port);
#endif
value = _ESW_REG(offset);
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 15);
if (ratelimit.bw < 100)
{
value |= (0x0 << 8);
value |= ratelimit.bw;
}else if(ratelimit.bw < 1000)
{
value |= (0x1 << 8);
value |= ratelimit.bw/10;
}else if(ratelimit.bw < 10000)
{
value |= (0x2 << 8);
value |= ratelimit.bw/100;
}else if(ratelimit.bw < 100000)
{
value |= (0x3 << 8);
value |= ratelimit.bw/1000;
}else
{
value |= (0x4 << 8);
value |= ratelimit.bw/10000;
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
#ifndef CONFIG_RALINK_MT7621
_ESW_REG(offset) = value;
#else
mii_mgr_write(0x1f, offset, value);
#endif
break;
case RAETH_ESW_EGRESS_RATE:
copy_from_user(&ratelimit, ifr->ifr_data, sizeof(ratelimit));
offset = 0x1040 + (0x100 * ratelimit.port);
value = _ESW_REG(offset);
value &= 0xffff0000;
if(ratelimit.on_off == 1)
{
value |= (ratelimit.on_off << 15);
if (ratelimit.bw < 100)
{
value |= (0x0 << 8);
value |= ratelimit.bw;
}else if(ratelimit.bw < 1000)
{
value |= (0x1 << 8);
value |= ratelimit.bw/10;
}else if(ratelimit.bw < 10000)
{
value |= (0x2 << 8);
value |= ratelimit.bw/100;
}else if(ratelimit.bw < 100000)
{
value |= (0x3 << 8);
value |= ratelimit.bw/1000;
}else
{
value |= (0x4 << 8);
value |= ratelimit.bw/10000;
}
}
printk("offset = 0x%4x value=0x%x\n\r", offset, value);
#ifndef CONFIG_RALINK_MT7621
_ESW_REG(offset) = value;
#else
mii_mgr_write(0x1f, offset, value);
#endif
break;
#endif
#endif // CONFIG_RT_3052_ESW
default:
return -EOPNOTSUPP;
}
return 0;
}
/*
* Set new MTU size
* Change the mtu of Raeth Ethernet Device
*/
static int ei_change_mtu(struct net_device *dev, int new_mtu)
{
END_DEVICE *ei_local = netdev_priv(dev); // get priv ei_local pointer from net_dev structure
if ( ei_local == NULL ) {
printk(KERN_EMERG "%s: ei_change_mtu passed a non-existent private pointer from net_dev!\n", dev->name);
return -ENXIO;
}
if ( (new_mtu > 4096) || (new_mtu < 64)) {
return -EINVAL;
}
#ifndef CONFIG_RAETH_JUMBOFRAME
if ( new_mtu > 1500 ) {
return -EINVAL;
}
#endif
dev->mtu = new_mtu;
return 0;
}
#ifdef CONFIG_RAETH_HW_VLAN_RX
static void ei_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
END_DEVICE *ei_local = netdev_priv(dev);
ei_local->vlgrp = grp;
/* enable HW VLAN RX */
sysRegWrite(CDMP_EG_CTRL, 1);
}
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static const struct net_device_ops ei_netdev_ops = {
.ndo_init = rather_probe,
.ndo_open = ei_open,
.ndo_stop = ei_close,
.ndo_start_xmit = ei_start_xmit_fake,
.ndo_get_stats = ra_get_stats,
.ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = ei_change_mtu,
.ndo_do_ioctl = ei_ioctl,
.ndo_validate_addr = eth_validate_addr,
#ifdef CONFIG_RAETH_HW_VLAN_RX
.ndo_vlan_rx_register = ei_vlan_rx_register,
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = raeth_clean,
#endif
// .ndo_tx_timeout = ei_tx_timeout,
};
#endif
void ra2880_setup_dev_fptable(struct net_device *dev)
{
RAETH_PRINT(__FUNCTION__ "is called!\n");
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
dev->netdev_ops = &ei_netdev_ops;
#else
dev->open = ei_open;
dev->stop = ei_close;
dev->hard_start_xmit = ei_start_xmit_fake;
dev->get_stats = ra_get_stats;
dev->set_mac_address = ei_set_mac_addr;
dev->change_mtu = ei_change_mtu;
dev->mtu = 1500;
dev->do_ioctl = ei_ioctl;
// dev->tx_timeout = ei_tx_timeout;
#ifdef CONFIG_RAETH_NAPI
dev->poll = &raeth_clean;
#if defined (CONFIG_RAETH_ROUTER)
dev->weight = 32;
#elif defined (CONFIG_RT_3052_ESW)
dev->weight = 32;
#else
dev->weight = 128;
#endif
#endif
#endif
#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
dev->ethtool_ops = &ra_ethtool_ops;
#endif
#define TX_TIMEOUT (5*HZ)
dev->watchdog_timeo = TX_TIMEOUT;
}
/* reset frame engine */
void fe_reset(void)
{
#if defined (CONFIG_RALINK_RT6855A)
/* FIXME */
#else
u32 val;
val = sysRegRead(RSTCTRL);
// RT5350 need to reset ESW and FE at the same to avoid PDMA panic //
#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
val = val | RALINK_FE_RST | RALINK_ESW_RST ;
#else
val = val | RALINK_FE_RST;
#endif
sysRegWrite(RSTCTRL, val);
#if defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628)
val = val & ~(RALINK_FE_RST | RALINK_ESW_RST);
#else
val = val & ~(RALINK_FE_RST);
#endif
sysRegWrite(RSTCTRL, val);
#endif
}
/* set TRGMII */
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
void trgmii_set_7621(void)
{
u32 val = 0;
u32 val_0 = 0;
val = sysRegRead(RSTCTRL);
// MT7621 need to reset GMAC and FE first //
val = val | RALINK_FE_RST | RALINK_ETH_RST ;
sysRegWrite(RSTCTRL, val);
//set TRGMII clock//
val_0 = sysRegRead(CLK_CFG_0);
val_0 &= 0xffffff9f;
val_0 |= (0x1 << 5);
sysRegWrite(CLK_CFG_0, val_0);
mdelay(1);
val_0 = sysRegRead(CLK_CFG_0);
printk("set CLK_CFG_0 = 0x%x!!!!!!!!!!!!!!!!!!1\n",val_0);
val = val & ~(RALINK_FE_RST | RALINK_ETH_RST);
sysRegWrite(RSTCTRL, val);
}
void trgmii_set_7530(void)
{
// set MT7530 //
#if 0
mii_mgr_write(31, 103, 0x0020);
//disable EEE
mii_mgr_write(0, 0x16, 0);
mii_mgr_write(1, 0x16, 0);
mii_mgr_write(2, 0x16, 0);
mii_mgr_write(3, 0x16, 0);
mii_mgr_write(4, 0x16, 0);
//PLL reset for E2
mii_mgr_write(31, 104, 0x0608);
mii_mgr_write(31, 104, 0x2608);
mii_mgr_write(31, 0x7808, 0x0);
mdelay(1);
mii_mgr_write(31, 0x7804, 0x01017e8f);
mdelay(1);
mii_mgr_write(31, 0x7808, 0x1);
mdelay(1);
#endif
#if 1
//CL45 command
//PLL to 150Mhz
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x404);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x0780);//40Mhz XTAL for 150Mhz CLK
//mii_mgr_write(0, 14, 0x0C00);//ori
mdelay(1);
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x409);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x57);
mdelay(1);
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x40a);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x57);
//PLL BIAS en
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x403);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x1800);
mdelay(1);
//BIAS LPF en
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x403);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x1c00);
//sys PLL en
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x401);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0xc020);
//LCDDDS PWDS
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x406);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0xa030);
mdelay(1);
//GSW_2X_CLK
mii_mgr_write(0, 13, 0x1f);
mii_mgr_write(0, 14, 0x410);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x0003);
//enable P6
mii_mgr_write(31, 0x3600, 0x5e33b);
//enable TRGMII
mii_mgr_write(31, 0x7830, 0x1);
#endif
}
#endif
void ei_reset_task(struct work_struct *work)
{
struct net_device *dev = dev_raether;
ei_close(dev);
ei_open(dev);
return;
}
void ei_tx_timeout(struct net_device *dev)
{
END_DEVICE *ei_local = netdev_priv(dev);
schedule_work(&ei_local->reset_task);
}
void setup_statistics(END_DEVICE* ei_local)
{
ei_local->stat.tx_packets = 0;
ei_local->stat.tx_bytes = 0;
ei_local->stat.tx_dropped = 0;
ei_local->stat.tx_errors = 0;
ei_local->stat.tx_aborted_errors= 0;
ei_local->stat.tx_carrier_errors= 0;
ei_local->stat.tx_fifo_errors = 0;
ei_local->stat.tx_heartbeat_errors = 0;
ei_local->stat.tx_window_errors = 0;
ei_local->stat.rx_packets = 0;
ei_local->stat.rx_bytes = 0;
ei_local->stat.rx_dropped = 0;
ei_local->stat.rx_errors = 0;
ei_local->stat.rx_length_errors = 0;
ei_local->stat.rx_over_errors = 0;
ei_local->stat.rx_crc_errors = 0;
ei_local->stat.rx_frame_errors = 0;
ei_local->stat.rx_fifo_errors = 0;
ei_local->stat.rx_missed_errors = 0;
ei_local->stat.collisions = 0;
#if defined (CONFIG_RAETH_QOS)
ei_local->tx3_full = 0;
ei_local->tx2_full = 0;
ei_local->tx1_full = 0;
ei_local->tx0_full = 0;
#else
ei_local->tx_full = 0;
#endif
#ifdef CONFIG_RAETH_NAPI
atomic_set(&ei_local->irq_sem, 1);
#endif
}
/**
* rather_probe - pick up ethernet port at boot time
* @dev: network device to probe
*
* This routine probe the ethernet port at boot time.
*
*
*/
int __init rather_probe(struct net_device *dev)
{
int i;
END_DEVICE *ei_local = netdev_priv(dev);
struct sockaddr addr;
unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
fe_reset();
//Get mac0 address from flash
#ifdef RA_MTD_RW_BY_NUM
i = ra_mtd_read(2, GMAC0_OFFSET, 6, addr.sa_data);
#else
i = ra_mtd_read_nm("Factory", GMAC0_OFFSET, 6, addr.sa_data);
#endif
//If reading mtd failed or mac0 is empty, generate a mac address
if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) ||
(memcmp(addr.sa_data, zero2, 6) == 0)) {
unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
net_srandom(jiffies);
memcpy(addr.sa_data, mac_addr01234, 5);
addr.sa_data[5] = net_random()&0xFF;
}
#ifdef CONFIG_RAETH_NAPI
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
netif_napi_add(dev, &ei_local->napi, raeth_clean, 128);
#endif
#endif
ei_set_mac_addr(dev, &addr);
spin_lock_init(&ei_local->page_lock);
ether_setup(dev);
#ifdef CONFIG_RAETH_LRO
ei_local->lro_mgr.dev = dev;
memset(&ei_local->lro_mgr.stats, 0, sizeof(ei_local->lro_mgr.stats));
ei_local->lro_mgr.features = LRO_F_NAPI;
ei_local->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
ei_local->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
ei_local->lro_mgr.max_desc = ARRAY_SIZE(ei_local->lro_arr);
ei_local->lro_mgr.max_aggr = 64;
ei_local->lro_mgr.frag_align_pad = 0;
ei_local->lro_mgr.lro_arr = ei_local->lro_arr;
ei_local->lro_mgr.get_skb_header = rt_get_skb_header;
#endif
setup_statistics(ei_local);
return 0;
}
#ifdef CONFIG_PSEUDO_SUPPORT
int VirtualIF_ioctl(struct net_device * net_dev,
struct ifreq * ifr, int cmd)
{
ra_mii_ioctl_data mii;
switch (cmd) {
case RAETH_MII_READ:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
mii_mgr_read(mii.phy_id, mii.reg_num, &mii.val_out);
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_out);
copy_to_user(ifr->ifr_data, &mii, sizeof(mii));
break;
case RAETH_MII_WRITE:
copy_from_user(&mii, ifr->ifr_data, sizeof(mii));
//printk("phy %d, reg %d, val 0x%x\n", mii.phy_id, mii.reg_num, mii.val_in);
mii_mgr_write(mii.phy_id, mii.reg_num, mii.val_in);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
struct net_device_stats *VirtualIF_get_stats(struct net_device *dev)
{
PSEUDO_ADAPTER *pAd = netdev_priv(dev);
return &pAd->stat;
}
int VirtualIF_open(struct net_device * dev)
{
PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
printk("%s: ===> VirtualIF_open\n", dev->name);
#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN) || defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
*((volatile u32 *)(FE_INT_ENABLE2)) |= (1<<25); //enable GE2 link change intr for MT7530 delay setting
#endif
netif_start_queue(pPesueoAd->PseudoDev);
return 0;
}
int VirtualIF_close(struct net_device * dev)
{
PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
printk("%s: ===> VirtualIF_close\n", dev->name);
netif_stop_queue(pPesueoAd->PseudoDev);
return 0;
}
int VirtualIFSendPackets(struct sk_buff * pSkb,
struct net_device * dev)
{
PSEUDO_ADAPTER *pPesueoAd = netdev_priv(dev);
END_DEVICE *ei_local __maybe_unused;
//printk("VirtualIFSendPackets --->\n");
ei_local = netdev_priv(dev);
if (!(pPesueoAd->RaethDev->flags & IFF_UP)) {
dev_kfree_skb_any(pSkb);
return 0;
}
//pSkb->cb[40]=0x5a;
pSkb->dev = pPesueoAd->RaethDev;
ei_start_xmit(pSkb, pPesueoAd->RaethDev, 2);
return 0;
}
void virtif_setup_statistics(PSEUDO_ADAPTER* pAd)
{
pAd->stat.tx_packets = 0;
pAd->stat.tx_bytes = 0;
pAd->stat.tx_dropped = 0;
pAd->stat.tx_errors = 0;
pAd->stat.tx_aborted_errors= 0;
pAd->stat.tx_carrier_errors= 0;
pAd->stat.tx_fifo_errors = 0;
pAd->stat.tx_heartbeat_errors = 0;
pAd->stat.tx_window_errors = 0;
pAd->stat.rx_packets = 0;
pAd->stat.rx_bytes = 0;
pAd->stat.rx_dropped = 0;
pAd->stat.rx_errors = 0;
pAd->stat.rx_length_errors = 0;
pAd->stat.rx_over_errors = 0;
pAd->stat.rx_crc_errors = 0;
pAd->stat.rx_frame_errors = 0;
pAd->stat.rx_fifo_errors = 0;
pAd->stat.rx_missed_errors = 0;
pAd->stat.collisions = 0;
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
static const struct net_device_ops VirtualIF_netdev_ops = {
.ndo_open = VirtualIF_open,
.ndo_stop = VirtualIF_close,
.ndo_start_xmit = VirtualIFSendPackets,
.ndo_get_stats = VirtualIF_get_stats,
.ndo_set_mac_address = ei_set_mac2_addr,
.ndo_change_mtu = ei_change_mtu,
.ndo_do_ioctl = VirtualIF_ioctl,
.ndo_validate_addr = eth_validate_addr,
};
#endif
// Register pseudo interface
void RAETH_Init_PSEUDO(pEND_DEVICE pAd, struct net_device *net_dev)
{
int index;
struct net_device *dev;
PSEUDO_ADAPTER *pPseudoAd;
int i = 0;
struct sockaddr addr;
unsigned char zero1[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char zero2[6]={0x00,0x00,0x00,0x00,0x00,0x00};
for (index = 0; index < MAX_PSEUDO_ENTRY; index++) {
dev = alloc_etherdev(sizeof(PSEUDO_ADAPTER));
if (NULL == dev)
{
printk(" alloc_etherdev for PSEUDO_ADAPTER failed.\n");
return;
}
strcpy(dev->name, DEV2_NAME);
//Get mac2 address from flash
#ifdef RA_MTD_RW_BY_NUM
i = ra_mtd_read(2, GMAC2_OFFSET, 6, addr.sa_data);
#else
i = ra_mtd_read_nm("Factory", GMAC2_OFFSET, 6, addr.sa_data);
#endif
//If reading mtd failed or mac0 is empty, generate a mac address
if (i < 0 || ((memcmp(addr.sa_data, zero1, 6) == 0) || (addr.sa_data[0] & 0x1)) ||
(memcmp(addr.sa_data, zero2, 6) == 0)) {
unsigned char mac_addr01234[5] = {0x00, 0x0C, 0x43, 0x28, 0x80};
net_srandom(jiffies);
memcpy(addr.sa_data, mac_addr01234, 5);
addr.sa_data[5] = net_random()&0xFF;
}
ei_set_mac2_addr(dev, &addr);
ether_setup(dev);
pPseudoAd = netdev_priv(dev);
pPseudoAd->PseudoDev = dev;
pPseudoAd->RaethDev = net_dev;
virtif_setup_statistics(pPseudoAd);
pAd->PseudoDev = dev;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
dev->netdev_ops = &VirtualIF_netdev_ops;
#else
dev->hard_start_xmit = VirtualIFSendPackets;
dev->stop = VirtualIF_close;
dev->open = VirtualIF_open;
dev->do_ioctl = VirtualIF_ioctl;
dev->set_mac_address = ei_set_mac2_addr;
dev->get_stats = VirtualIF_get_stats;
dev->change_mtu = ei_change_mtu;
dev->mtu = 1500;
#endif
dev->features |= NETIF_F_IP_CSUM; /* Can checksum TCP/UDP over IPv4 */
#if defined(CONFIG_RALINK_MT7620)
#if defined (CONFIG_RAETH_TSO)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
}
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
}
#endif
#else
#if defined (CONFIG_RAETH_TSO)
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_TSO;
#endif // CONFIG_RAETH_TSO //
#if defined (CONFIG_RAETH_TSOV6)
dev->features |= NETIF_F_TSO6;
dev->features |= NETIF_F_IPV6_CSUM; /* Can checksum TCP/UDP over IPv6 */
#endif
#endif // CONFIG_RALINK_MT7620 //
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0)
dev->vlan_features = dev->features;
#endif
#if defined (CONFIG_ETHTOOL) /*&& defined (CONFIG_RAETH_ROUTER)*/
dev->ethtool_ops = &ra_virt_ethtool_ops;
// init mii structure
pPseudoAd->mii_info.dev = dev;
pPseudoAd->mii_info.mdio_read = mdio_virt_read;
pPseudoAd->mii_info.mdio_write = mdio_virt_write;
pPseudoAd->mii_info.phy_id_mask = 0x1f;
pPseudoAd->mii_info.reg_num_mask = 0x1f;
pPseudoAd->mii_info.phy_id = 0x1e;
pPseudoAd->mii_info.supports_gmii = mii_check_gmii_support(&pPseudoAd->mii_info);
#endif
// Register this device
register_netdevice(dev);
}
}
#endif
/**
* ei_open - Open/Initialize the ethernet port.
* @dev: network device to initialize
*
* This routine goes all-out, setting everything
* up a new at each open, even though many of these registers should only need to be set once at boot.
*/
int ei_open(struct net_device *dev)
{
int i, err;
unsigned long flags;
END_DEVICE *ei_local;
#ifdef CONFIG_RAETH_LRO
const char *lan_ip_tmp;
#ifdef CONFIG_DUAL_IMAGE
#define RT2860_NVRAM 1
#else
#define RT2860_NVRAM 0
#endif
#endif // CONFIG_RAETH_LRO //
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if (!try_module_get(THIS_MODULE))
{
printk("%s: Cannot reserve module\n", __FUNCTION__);
return -1;
}
#else
MOD_INC_USE_COUNT;
#endif
printk("Raeth %s (",RAETH_VERSION);
#if defined (CONFIG_RAETH_NAPI)
printk("NAPI\n");
#elif defined (CONFIG_RA_NETWORK_TASKLET_BH)
printk("Tasklet");
#elif defined (CONFIG_RA_NETWORK_WORKQUEUE_BH)
printk("Workqueue");
#endif
#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
printk(",SkbRecycle");
#endif
printk(")\n");
ei_local = netdev_priv(dev); // get device pointer from System
// unsigned int flags;
if (ei_local == NULL)
{
printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
return -ENXIO;
}
/* receiving packet buffer allocation - NUM_RX_DESC x MAX_RX_LENGTH */
for ( i = 0; i < NUM_RX_DESC; i++)
{
#if defined (CONFIG_RAETH_SKB_RECYCLE_2K)
ei_local->netrx0_skbuf[i] = skbmgr_dev_alloc_skb2k();
#else
ei_local->netrx0_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
#endif
if (ei_local->netrx0_skbuf[i] == NULL ) {
printk("rx skbuff buffer allocation failed!");
} else {
#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
skb_reserve(ei_local->netrx0_skbuf[i], NET_IP_ALIGN);
#endif
}
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
ei_local->netrx1_skbuf[i] = dev_alloc_skb(MAX_RX_LENGTH + NET_IP_ALIGN);
if (ei_local->netrx1_skbuf[i] == NULL ) {
printk("rx1 skbuff buffer allocation failed!");
} else {
#if !defined (CONFIG_RAETH_SCATTER_GATHER_RX_DMA)
skb_reserve(ei_local->netrx1_skbuf[i], NET_IP_ALIGN);
#endif
}
#endif
}
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
trgmii_set_7621(); //reset FE/GMAC in this function
#endif
fe_dma_init(dev);
fe_sw_init(); //initialize fe and switch register
err = request_irq( dev->irq, ei_interrupt, IRQF_DISABLED, dev->name, dev); // try to fix irq in open
if (err)
return err;
if ( dev->dev_addr != NULL) {
ra2880MacAddressSet((void *)(dev->dev_addr));
} else {
printk("dev->dev_addr is empty !\n");
}
#if defined (CONFIG_RT_3052_ESW)
err = request_irq(SURFBOARDINT_ESW, esw_interrupt, IRQF_DISABLED, "Ralink_ESW", dev);
if (err)
return err;
INIT_WORK(&ei_local->kill_sig_wq, kill_sig_workq);
#if defined (CONFIG_RALINK_MT7621)
mii_mgr_write(31, 0x7008, 0x1f); //enable switch link change intr
#else
*((volatile u32 *)(RALINK_INTCL_BASE + 0x34)) = (1<<17);
*((volatile u32 *)(ESW_IMR)) &= ~(ESW_INT_ALL);
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_RT6855A) || \
defined(CONFIG_RALINK_MT7620)
*((volatile u32 *)(ESW_P0_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P1_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P2_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P3_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P4_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P5_IntMn)) &= ~(MSK_CNT_INT_ALL);
*((volatile u32 *)(ESW_P6_IntMn)) &= ~(MSK_CNT_INT_ALL);
#endif
#if defined(CONFIG_RALINK_MT7620)
*((volatile u32 *)(ESW_P7_IntMn)) &= ~(MSK_CNT_INT_ALL);
#endif
#endif
#endif // CONFIG_RT_3052_ESW //
spin_lock_irqsave(&(ei_local->page_lock), flags);
#ifdef DELAY_INT
sysRegWrite(RAETH_DLY_INT_CFG, DELAY_INT_INIT);
sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_DLY_INIT);
#else
sysRegWrite(RAETH_FE_INT_ENABLE, RAETH_FE_INT_ALL);
#endif
#ifdef CONFIG_RAETH_QDMA
#ifdef DELAY_INT
sysRegWrite(QDMA_DELAY_INT, DELAY_INT_INIT);
sysRegWrite(QFE_INT_ENABLE, QFE_INT_DLY_INIT);
#else
sysRegWrite(QFE_INT_ENABLE, QFE_INT_ALL);
#endif
#endif
INIT_WORK(&ei_local->reset_task, ei_reset_task);
#ifdef WORKQUEUE_BH
#ifndef CONFIG_RAETH_NAPI
INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
#endif // CONFIG_RAETH_NAPI //
#else
#ifndef CONFIG_RAETH_NAPI
#if defined (TASKLET_WORKQUEUE_SW)
working_schedule = init_schedule;
INIT_WORK(&ei_local->rx_wq, ei_receive_workq);
tasklet_init(&ei_local->rx_tasklet, ei_receive_workq, 0);
#else
tasklet_init(&ei_local->rx_tasklet, ei_receive, 0);
#endif
#endif // CONFIG_RAETH_NAPI //
#endif // WORKQUEUE_BH //
netif_start_queue(dev);
#ifdef CONFIG_RAETH_NAPI
atomic_dec(&ei_local->irq_sem);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
napi_enable(&ei_local->napi);
#else
netif_poll_enable(dev);
#endif
#endif
spin_unlock_irqrestore(&(ei_local->page_lock), flags);
#ifdef CONFIG_PSEUDO_SUPPORT
if(ei_local->PseudoDev == NULL) {
RAETH_Init_PSEUDO(ei_local, dev);
}
if(ei_local->PseudoDev == NULL)
printk("Open PseudoDev failed.\n");
else
VirtualIF_open(ei_local->PseudoDev);
#endif
#ifdef CONFIG_RAETH_LRO
lan_ip_tmp = nvram_get(RT2860_NVRAM, "lan_ipaddr");
str_to_ip(&lan_ip, lan_ip_tmp);
lro_para.lan_ip1 = lan_ip = htonl(lan_ip);
#endif // CONFIG_RAETH_LRO //
forward_config(dev);
return 0;
}
/**
* ei_close - shut down network device
* @dev: network device to clear
*
* This routine shut down network device.
*
*
*/
int ei_close(struct net_device *dev)
{
int i;
END_DEVICE *ei_local = netdev_priv(dev); // device pointer
netif_stop_queue(dev);
ra2880stop(ei_local);
free_irq(dev->irq, dev);
#if defined (CONFIG_RT_3052_ESW)
free_irq(SURFBOARDINT_ESW, dev);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
cancel_work_sync(&ei_local->reset_task);
#endif
#ifdef CONFIG_PSEUDO_SUPPORT
VirtualIF_close(ei_local->PseudoDev);
#endif
#ifdef WORKQUEUE_BH
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
cancel_work_sync(&ei_local->rx_wq);
#endif
#else
#if defined (TASKLET_WORKQUEUE_SW)
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
cancel_work_sync(&ei_local->rx_wq);
#endif
#endif
tasklet_kill(&ei_local->tx_tasklet);
tasklet_kill(&ei_local->rx_tasklet);
#endif // WORKQUEUE_BH //
for ( i = 0; i < NUM_RX_DESC; i++)
{
if (ei_local->netrx0_skbuf[i] != NULL) {
dev_kfree_skb(ei_local->netrx0_skbuf[i]);
ei_local->netrx0_skbuf[i] = NULL;
}
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
if (ei_local->netrx1_skbuf[i] != NULL) {
dev_kfree_skb(ei_local->netrx1_skbuf[i]);
ei_local->netrx1_skbuf[i] = NULL;
}
#endif
}
for ( i = 0; i < NUM_TX_DESC; i++)
{
if((ei_local->skb_free[i]!=(struct sk_buff *)0xFFFFFFFF) && (ei_local->skb_free[i]!= 0))
{
dev_kfree_skb_any(ei_local->skb_free[i]);
}
}
/* TX Ring */
#ifdef CONFIG_RAETH_QDMA
if (ei_local->txd_pool != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct QDMA_txdesc), ei_local->txd_pool, ei_local->phy_txd_pool);
}
if (ei_local->free_head != NULL){
pci_free_consistent(NULL, NUM_QDMA_PAGE * sizeof(struct QDMA_txdesc), ei_local->free_head, ei_local->phy_free_head);
}
if (ei_local->free_page_head != NULL){
pci_free_consistent(NULL, NUM_QDMA_PAGE * QDMA_PAGE_SIZE, ei_local->free_page_head, ei_local->phy_free_page_head);
}
#else
if (ei_local->tx_ring0 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring0, ei_local->phy_tx_ring0);
}
#endif
#if defined (CONFIG_RAETH_QOS)
if (ei_local->tx_ring1 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring1, ei_local->phy_tx_ring1);
}
#if !defined (CONFIG_RALINK_RT2880)
if (ei_local->tx_ring2 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring2, ei_local->phy_tx_ring2);
}
if (ei_local->tx_ring3 != NULL) {
pci_free_consistent(NULL, NUM_TX_DESC*sizeof(struct PDMA_txdesc), ei_local->tx_ring3, ei_local->phy_tx_ring3);
}
#endif
#endif
/* RX Ring */
#ifdef CONFIG_32B_DESC
kfree(ei_local->rx_ring0);
#else
pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring0, ei_local->phy_rx_ring0);
#endif
#ifdef CONFIG_RAETH_QDMA
#ifdef CONFIG_32B_DESC
kfree(ei_local->qrx_ring);
#else
pci_free_consistent(NULL, NUM_QRX_DESC*sizeof(struct PDMA_rxdesc), ei_local->qrx_ring, ei_local->phy_qrx_ring);
#endif
#endif
#if defined (CONFIG_RAETH_MULTIPLE_RX_RING)
#ifdef CONFIG_32B_DESC
kfree(ei_local->rx_ring1);
#else
pci_free_consistent(NULL, NUM_RX_DESC*sizeof(struct PDMA_rxdesc), ei_local->rx_ring1, ei_local->phy_rx_ring1);
#endif
#endif
printk("Free TX/RX Ring Memory!\n");
#ifdef CONFIG_RAETH_NAPI
atomic_inc(&ei_local->irq_sem);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
napi_disable(&ei_local->napi);
#else
netif_poll_disable(dev);
#endif
#endif
fe_reset();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
module_put(THIS_MODULE);
#else
MOD_DEC_USE_COUNT;
#endif
return 0;
}
#if defined (CONFIG_RT6855A_FPGA)
void rt6855A_eth_gpio_reset(void)
{
u8 ether_gpio = 12;
/* Load the ethernet gpio value to reset Ethernet PHY */
*(unsigned long *)(RALINK_PIO_BASE + 0x00) |= 1<<(ether_gpio<<1);
*(unsigned long *)(RALINK_PIO_BASE + 0x14) |= 1<<(ether_gpio);
*(unsigned long *)(RALINK_PIO_BASE + 0x04) &= ~(1<<ether_gpio);
udelay(100000);
*(unsigned long *)(RALINK_PIO_BASE + 0x04) |= (1<<ether_gpio);
/* must wait for 0.6 seconds after reset*/
udelay(600000);
}
#endif
#if defined(CONFIG_RALINK_RT6855A)
void rt6855A_gsw_init(void)
{
u32 phy_val=0;
u32 rev=0;
#if defined (CONFIG_RT6855A_FPGA)
/*keep dump switch mode */
rt6855A_eth_gpio_reset();
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e353;//(P0,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e353;//(P1,Force mode,Link Up,100Mbps,Full-Duplex,FC ON)
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1,Force mode,Link Up,10Mbps,Full-Duplex,FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
/* In order to use 10M/Full on FPGA board. We configure phy capable to
* 10M Full/Half duplex, so we can use auto-negotiation on PC side */
for(i=6;i<8;i++){
mii_mgr_write(i, 4, 0x07e1); //Capable of 10M&100M Full/Half Duplex, flow control on/off
//mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
mii_mgr_read(i, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(i, 9, phy_val);
}
#elif defined (CONFIG_RT6855A_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0xffffffe0;//Set Port6 CPU Port
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1ec) = 0x0fffffff;//Set PSE should pause 4 tx ring as default
*(unsigned long *)(RALINK_FRAME_ENGINE_BASE+0x1f0) = 0x0fffffff;//switch IOT more stable
*(unsigned long *)(CKGCR) &= ~(0x3 << 4); //keep rx/tx port clock ticking, disable internal clock-gating to avoid switch stuck
/*
*Reg 31: Page Control
* Bit 15 => PortPageSel, 1=local, 0=global
* Bit 14:12 => PageSel, local:0~3, global:0~4
*
*Reg16~30:Local/Global registers
*
*/
/*correct PHY setting J8.0*/
mii_mgr_read(0, 31, &rev);
rev &= (0x0f);
mii_mgr_write(1, 31, 0x4000); //global, page 4
mii_mgr_write(1, 16, 0xd4cc);
mii_mgr_write(1, 17, 0x7444);
mii_mgr_write(1, 19, 0x0112);
mii_mgr_write(1, 21, 0x7160);
mii_mgr_write(1, 22, 0x10cf);
mii_mgr_write(1, 26, 0x0777);
if(rev == 0){
mii_mgr_write(1, 25, 0x0102);
mii_mgr_write(1, 29, 0x8641);
}
else{
mii_mgr_write(1, 25, 0x0212);
mii_mgr_write(1, 29, 0x4640);
}
mii_mgr_write(1, 31, 0x2000); //global, page 2
mii_mgr_write(1, 21, 0x0655);
mii_mgr_write(1, 22, 0x0fd3);
mii_mgr_write(1, 23, 0x003d);
mii_mgr_write(1, 24, 0x096e);
mii_mgr_write(1, 25, 0x0fed);
mii_mgr_write(1, 26, 0x0fc4);
mii_mgr_write(1, 31, 0x1000); //global, page 1
mii_mgr_write(1, 17, 0xe7f8);
mii_mgr_write(1, 31, 0xa000); //local, page 2
mii_mgr_write(0, 16, 0x0e0e);
mii_mgr_write(1, 16, 0x0c0c);
mii_mgr_write(2, 16, 0x0f0f);
mii_mgr_write(3, 16, 0x1010);
mii_mgr_write(4, 16, 0x0909);
mii_mgr_write(0, 17, 0x0000);
mii_mgr_write(1, 17, 0x0000);
mii_mgr_write(2, 17, 0x0000);
mii_mgr_write(3, 17, 0x0000);
mii_mgr_write(4, 17, 0x0000);
#endif
#if defined (CONFIG_RT6855A_ASIC)
#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c;//disable port0-port4 internal phy, set phy base address to 12
*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
//rt6855/6 need to modify TX/RX phase
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0xc;//TX/RX CLOCK Phase select
enable_auto_negotiate(1);
if (isICPlusGigaPHY(1)) {
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
phy_val |= 1<<10; //enable pause ability
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}
if (isMarvellGigaPHY(1)) {
printk("Reset MARVELL phy1\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}
if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#else // Port 5 Disabled //
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
#endif
#endif
}
#endif
#if defined (CONFIG_RALINK_MT7621)
void setup_external_gsw(void)
{
u32 regValue;
/* reduce RGMII2 PAD driving strength */
*(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
//enable MDIO
regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
regValue &= ~(0x3 << 12);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
//RGMII1=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
//GMAC1= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x00008000);//(GE1, Link down)
//RGMII2=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
//GMAC2= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2005e33b);//(GE2, Force 1000M/FD, FC ON)
}
void IsSwitchVlanTableBusy(void)
{
int j = 0;
unsigned int value = 0;
for (j = 0; j < 20; j++) {
mii_mgr_read(31, 0x90, &value);
if ((value & 0x80000000) == 0 ){ //table busy
break;
}
udelay(70000);
}
if (j == 20)
printk("set vlan timeout value=0x%x.\n", value);
}
void LANWANPartition(void)
{
/*Set MT7530 */
#ifdef CONFIG_WAN_AT_P0
printk("set LAN/WAN WLLLL\n");
//WLLLL, wan at P0
//LAN/WAN ports as security mode
mii_mgr_write(31, 0x2004, 0xff0003);//port0
mii_mgr_write(31, 0x2104, 0xff0003);//port1
mii_mgr_write(31, 0x2204, 0xff0003);//port2
mii_mgr_write(31, 0x2304, 0xff0003);//port3
mii_mgr_write(31, 0x2404, 0xff0003);//port4
//set PVID
mii_mgr_write(31, 0x2014, 0x10002);//port0
mii_mgr_write(31, 0x2114, 0x10001);//port1
mii_mgr_write(31, 0x2214, 0x10001);//port2
mii_mgr_write(31, 0x2314, 0x10001);//port3
mii_mgr_write(31, 0x2414, 0x10001);//port4
/*port6 */
//VLAN member
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x407e0001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x40610001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
IsSwitchVlanTableBusy();
#endif
#ifdef CONFIG_WAN_AT_P4
printk("set LAN/WAN LLLLW\n");
//LLLLW, wan at P4
//LAN/WAN ports as security mode
mii_mgr_write(31, 0x2004, 0xff0003);//port0
mii_mgr_write(31, 0x2104, 0xff0003);//port1
mii_mgr_write(31, 0x2204, 0xff0003);//port2
mii_mgr_write(31, 0x2304, 0xff0003);//port3
mii_mgr_write(31, 0x2404, 0xff0003);//port4
//set PVID
mii_mgr_write(31, 0x2014, 0x10001);//port0
mii_mgr_write(31, 0x2114, 0x10001);//port1
mii_mgr_write(31, 0x2214, 0x10001);//port2
mii_mgr_write(31, 0x2314, 0x10001);//port3
mii_mgr_write(31, 0x2414, 0x10002);//port4
//VLAN member
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x404f0001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001001);//VTCR, VID=1
IsSwitchVlanTableBusy();
mii_mgr_write(31, 0x94, 0x40500001);//VAWD1
mii_mgr_write(31, 0x90, 0x80001002);//VTCR, VID=2
IsSwitchVlanTableBusy();
#endif
}
#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
void mt7621_eee_patch(void)
{
u32 i;
for(i=0;i<5;i++)
{
/* Enable EEE */
mii_mgr_write(i, 13, 0x07);
mii_mgr_write(i, 14, 0x3c);
mii_mgr_write(i, 13, 0x4007);
mii_mgr_write(i, 14, 0x6);
/* Forced Slave mode */
mii_mgr_write(i, 31, 0x0);
mii_mgr_write(i, 9, 0x1600);
/* Increase SlvDPSready time */
mii_mgr_write(i, 31, 0x52b5);
mii_mgr_write(i, 16, 0xafae);
mii_mgr_write(i, 18, 0x2f);
mii_mgr_write(i, 16, 0x8fae);
/* Incease post_update_timer */
mii_mgr_write(i, 31, 0x3);
mii_mgr_write(i, 17, 0x4b);
/* Adjust 100_mse_threshold */
mii_mgr_write(i, 13, 0x1e);
mii_mgr_write(i, 14, 0x123);
mii_mgr_write(i, 13, 0x401e);
mii_mgr_write(i, 14, 0xffff);
/* Disable mcc
mii_mgr_write(i, 13, 0x1e);
mii_mgr_write(i, 14, 0xa6);
mii_mgr_write(i, 13, 0x401e);
mii_mgr_write(i, 14, 0x300);
*/
}
}
#endif
void setup_internal_gsw(void)
{
u32 i;
u32 regValue;
#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)
/*Hardware reset Switch*/
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) |= (0x1 << 2);
udelay(1000);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x34) &= ~(0x1 << 2);
udelay(10000);
/* reduce RGMII2 PAD driving strength */
*(volatile u_long *)(PAD_RGMII2_MDIO_CFG) &= ~(0x3 << 4);
//RGMII1=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 14);
//GMAC1= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 12);
//enable MDIO to control MT7530
regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
regValue &= ~(0x3 << 12);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
for(i=0;i<=4;i++)
{
//turn off PHY
mii_mgr_read(i, 0x0 ,&regValue);
regValue |= (0x1<<11);
mii_mgr_write(i, 0x0, regValue);
}
mii_mgr_write(31, 0x7000, 0x3); //reset switch
udelay(100);
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
trgmii_set_7530(); //reset FE, config MDIO again
//enable MDIO to control MT7530
regValue = le32_to_cpu(*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60));
regValue &= ~(0x3 << 12);
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) = regValue;
// switch to APLL if TRGMII and DDR2
if ((sysRegRead(0xBE000010)>>4)&0x1)
{
apll_xtal_enable();
}
#endif
#if defined (CONFIG_MT7621_ASIC)
if((sysRegRead(0xbe00000c)&0xFFFF)==0x0101) {
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2005e30b);//(GE1, Force 1000M/FD, FC ON)
mii_mgr_write(31, 0x3600, 0x5e30b);
} else {
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2005e33b);//(GE1, Force 1000M/FD, FC ON)
mii_mgr_write(31, 0x3600, 0x5e33b);
}
#elif defined (CONFIG_MT7621_FPGA)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x2005e337);//(GE1, Force 100M/FD, FC ON)
mii_mgr_write(31, 0x3600, 0x5e337);
#endif
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x00008000);//(GE2, Link down)
#endif
#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)
//regValue = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable*/
mii_mgr_read(31, 0x7804 ,&regValue);
regValue &= ~(1<<8); //Enable Port 6
regValue |= (1<<6); //Disable Port 5
regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
#if defined (CONFIG_RAETH_GMAC2)
//RGMII2=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
//GMAC2= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
#if !defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(31, 0x3500, 0x56300); //MT7530 P5 AN, we can ignore this setting??????
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x20056300);//(GE2, auto-polling)
enable_auto_negotiate(0);//set polling address
#endif
#if defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(31, 0x3500, 0x5e33b); //MT7530 P5 Force 1000, we can ignore this setting??????
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x2005e33b);//(GE2, Force 1000)
#endif
/* set MT7530 Port 5 to PHY 0/4 mode */
#if defined (CONFIG_GE_RGMII_INTERNAL_P0_AN)
regValue &= ~((1<<13)|(1<<6));
regValue |= ((1<<7)|(1<<16)|(1<<20));
#elif defined (CONFIG_GE_RGMII_INTERNAL_P4_AN)
regValue &= ~((1<<13)|(1<<6)|(1<<20));
regValue |= ((1<<7)|(1<<16));
#endif
#if defined (CONFIG_RAETH_8023AZ_EEE)
regValue |= (1<<13); //Port 5 as GMAC, no Internal PHY
#endif
//sysRegWrite(GDMA2_FWD_CFG, 0x20710000);
#endif
regValue |= (1<<16);//change HW-TRAP
printk("change HW-TRAP to 0x%x\n",regValue);
mii_mgr_write(31, 0x7804 ,regValue);
#endif
regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10);
regValue = (regValue >> 6) & 0x7;
if(regValue >= 6) { //25Mhz Xtal
/* do nothing */
} else if(regValue >=3) { //40Mhz
mii_mgr_write(0, 13, 0x1f); // disable MT7530 core clock
mii_mgr_write(0, 14, 0x410);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x0);
mii_mgr_write(0, 13, 0x1f); // disable MT7530 PLL
mii_mgr_write(0, 14, 0x40d);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x2020);
mii_mgr_write(0, 13, 0x1f); // for MT7530 core clock = 500Mhz
mii_mgr_write(0, 14, 0x40e);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x119);
mii_mgr_write(0, 13, 0x1f); // enable MT7530 PLL
mii_mgr_write(0, 14, 0x40d);
mii_mgr_write(0, 13, 0x401f);
mii_mgr_write(0, 14, 0x2820);
udelay(20); //suggest by CD
mii_mgr_write(0, 13, 0x1f); // enable MT7530 core clock
mii_mgr_write(0, 14, 0x410);
mii_mgr_write(0, 13, 0x401f);
}else { //20Mhz Xtal
/* TODO */
}
#if defined (CONFIG_GE1_TRGMII_FORCE_1200) && defined (CONFIG_MT7621_ASIC)
mii_mgr_write(0, 14, 0x3); /*TRGMII*/
#else
mii_mgr_write(0, 14, 0x1); /*RGMII*/
/* set MT7530 central align */
mii_mgr_read(31, 0x7830, &regValue);
regValue &= ~1;
regValue |= 1<<1;
mii_mgr_write(31, 0x7830, regValue);
mii_mgr_read(31, 0x7a40, &regValue);
regValue &= ~(1<<30);
mii_mgr_write(31, 0x7a40, regValue);
regValue = 0x855;
mii_mgr_write(31, 0x7a78, regValue);
#endif
#if !defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(31, 0x7b00, 0x102); //delay setting for 10/1000M
mii_mgr_write(31, 0x7b04, 0x14); //delay setting for 10/1000M
#endif
#if 0
for(i=0;i<=4;i++) {
mii_mgr_read(i, 4, &regValue);
regValue |= (3<<7); //turn on 100Base-T Advertisement
//regValue &= ~(3<<7); //turn off 100Base-T Advertisement
mii_mgr_write(i, 4, regValue);
mii_mgr_read(i, 9, &regValue);
regValue |= (3<<8); //turn on 1000Base-T Advertisement
//regValue &= ~(3<<8); //turn off 1000Base-T Advertisement
mii_mgr_write(i, 9, regValue);
//restart AN
mii_mgr_read(i, 0, &regValue);
regValue |= (1 << 9);
mii_mgr_write(i, 0, regValue);
}
#endif
/*Tx Driving*/
mii_mgr_write(31, 0x7a54, 0x44); //lower driving
mii_mgr_write(31, 0x7a5c, 0x44); //lower driving
mii_mgr_write(31, 0x7a64, 0x44); //lower driving
mii_mgr_write(31, 0x7a6c, 0x44); //lower driving
mii_mgr_write(31, 0x7a74, 0x44); //lower driving
mii_mgr_write(31, 0x7a7c, 0x44); //lower driving
LANWANPartition();
#if !defined (CONFIG_RAETH_8023AZ_EEE)
//disable EEE
for(i=0;i<=4;i++)
{
mii_mgr_write(i, 13, 0x7);
mii_mgr_write(i, 14, 0x3C);
mii_mgr_write(i, 13, 0x4007);
mii_mgr_write(i, 14, 0x0);
}
//Disable EEE 10Base-Te:
for(i=0;i<=4;i++)
{
mii_mgr_write(i, 13, 0x1f);
mii_mgr_write(i, 14, 0x027b);
mii_mgr_write(i, 13, 0x401f);
mii_mgr_write(i, 14, 0x1177);
}
#endif
for(i=0;i<=4;i++)
{
//turn on PHY
mii_mgr_read(i, 0x0 ,&regValue);
regValue &= ~(0x1<<11);
mii_mgr_write(i, 0x0, regValue);
}
mii_mgr_read(31, 0x7808 ,&regValue);
regValue |= (3<<16); //Enable INTR
mii_mgr_write(31, 0x7808 ,regValue);
#if defined (CONFIG_RAETH_8023AZ_EEE) && defined (CONFIG_RALINK_MT7621)
mt7621_eee_patch();
#endif
}
#if defined (CONFIG_GE1_TRGMII_FORCE_1200)
void apll_xtal_enable(void)
{
unsigned long data = 0;
unsigned long regValue = 0;
/* Firstly, reset all required register to default value */
sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008000);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
/* toggle RG_XPTL_CHG */
sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008800);
sysRegWrite(RALINK_ANA_CTRL_BASE, 0x00008c00);
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0014);
data &= ~(0x0000ffc0);
regValue = *(volatile u_long *)(RALINK_SYSCTL_BASE + 0x10);
regValue = (regValue >> 6) & 0x7;
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0x1d, 8);
}else {
data |= REGBIT(0x17, 8);
}
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0x1, 6);
}
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0014, data);
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x0018);
data &= ~(0xf0773f00);
data |= REGBIT(0x3, 28);
data |= REGBIT(0x2, 20);
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0x3, 16);
}else {
data |= REGBIT(0x2, 16);
}
data |= REGBIT(0x3, 12);
if(regValue < 6) { //20/40Mhz Xtal
data |= REGBIT(0xd, 8);
}else {
data |= REGBIT(0x7, 8);
}
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0018, data);
if(regValue < 6) { //20/40Mhz Xtal
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48);
}else {
sysRegWrite(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39);
}
//*Common setting - Set PLLGP_CTRL_4 *//
///* 1. Bit 31 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data &= ~(REGBIT(0x1, 31));
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 2. Bit 0 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 0);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 3. Bit 3 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 3);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 4. Bit 8 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 8);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 5. Bit 6 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 6);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 6. Bit 7 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data |= REGBIT(0x1, 5);
data |= REGBIT(0x1, 7);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 7. Bit 17 */
data = sysRegRead(RALINK_ANA_CTRL_BASE+0x001c);
data &= ~REGBIT(0x1, 17);
sysRegWrite(RALINK_ANA_CTRL_BASE+0x001c, data);
/* 8. TRGMII TX CLK SEL APLL */
data = sysRegRead(0xbe00002c);
data &= 0xffffff9f;
data |= 0x40;
sysRegWrite(0xbe00002c, data);
}
#endif
#endif
#if defined(CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
void rt_gsw_init(void)
{
#if defined (CONFIG_P4_MAC_TO_PHY_MODE) || defined (CONFIG_P5_MAC_TO_PHY_MODE)
u32 phy_val=0;
#endif
#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
u32 i=0;
#elif defined (CONFIG_MT7620_ASIC)
u32 is_BGA=0;
#endif
#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
unsigned int regValue = 0;
#endif
#if defined (CONFIG_RT6855_FPGA) || defined (CONFIG_MT7620_FPGA)
/*keep dump switch mode */
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3000) = 0x5e333;//(P0, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3100) = 0x5e333;//(P1, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3200) = 0x5e333;//(P2, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3300) = 0x5e333;//(P3, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
#if defined (CONFIG_RAETH_HAS_PORT4)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P4, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#else
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e333;//(P4, Force mode, Link Up, 10Mbps, Full-Duplex, FC ON)
#endif
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
/* In order to use 10M/Full on FPGA board. We configure phy capable to
* 10M Full/Half duplex, so we can use auto-negotiation on PC side */
#if defined (CONFIG_RAETH_HAS_PORT4)
for(i=0;i<4;i++){
#else
for(i=0;i<5;i++){
#endif
mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
}
#endif
#if defined (CONFIG_PDMA_NEW)
*(unsigned long *)(SYSCFG1) |= (0x1 << 8); //PCIE_RC_MODE=1
#endif
#if defined (CONFIG_MT7620_ASIC) && !defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
is_BGA = (sysRegRead(RALINK_SYSCTL_BASE + 0xc) >> 16) & 0x1;
/*
* Reg 31: Page Control
* Bit 15 => PortPageSel, 1=local, 0=global
* Bit 14:12 => PageSel, local:0~3, global:0~4
*
* Reg16~30:Local/Global registers
*
*/
/*correct PHY setting L3.0 BGA*/
mii_mgr_write(1, 31, 0x4000); //global, page 4
mii_mgr_write(1, 17, 0x7444);
if(is_BGA){
mii_mgr_write(1, 19, 0x0114);
}else{
mii_mgr_write(1, 19, 0x0117);
}
mii_mgr_write(1, 22, 0x10cf);
mii_mgr_write(1, 25, 0x6212);
mii_mgr_write(1, 26, 0x0777);
mii_mgr_write(1, 29, 0x4000);
mii_mgr_write(1, 28, 0xc077);
mii_mgr_write(1, 24, 0x0000);
mii_mgr_write(1, 31, 0x3000); //global, page 3
mii_mgr_write(1, 17, 0x4838);
mii_mgr_write(1, 31, 0x2000); //global, page 2
if(is_BGA){
mii_mgr_write(1, 21, 0x0515);
mii_mgr_write(1, 22, 0x0053);
mii_mgr_write(1, 23, 0x00bf);
mii_mgr_write(1, 24, 0x0aaf);
mii_mgr_write(1, 25, 0x0fad);
mii_mgr_write(1, 26, 0x0fc1);
}else{
mii_mgr_write(1, 21, 0x0517);
mii_mgr_write(1, 22, 0x0fd2);
mii_mgr_write(1, 23, 0x00bf);
mii_mgr_write(1, 24, 0x0aab);
mii_mgr_write(1, 25, 0x00ae);
mii_mgr_write(1, 26, 0x0fff);
}
mii_mgr_write(1, 31, 0x1000); //global, page 1
mii_mgr_write(1, 17, 0xe7f8);
mii_mgr_write(1, 31, 0x8000); //local, page 0
mii_mgr_write(0, 30, 0xa000);
mii_mgr_write(1, 30, 0xa000);
mii_mgr_write(2, 30, 0xa000);
mii_mgr_write(3, 30, 0xa000);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 30, 0xa000);
#endif
mii_mgr_write(0, 4, 0x05e1);
mii_mgr_write(1, 4, 0x05e1);
mii_mgr_write(2, 4, 0x05e1);
mii_mgr_write(3, 4, 0x05e1);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 4, 0x05e1);
#endif
mii_mgr_write(1, 31, 0xa000); //local, page 2
mii_mgr_write(0, 16, 0x1111);
mii_mgr_write(1, 16, 0x1010);
mii_mgr_write(2, 16, 0x1515);
mii_mgr_write(3, 16, 0x0f0f);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 16, 0x1313);
#endif
#if !defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_write(1, 31, 0xb000); //local, page 3
mii_mgr_write(0, 17, 0x0);
mii_mgr_write(1, 17, 0x0);
mii_mgr_write(2, 17, 0x0);
mii_mgr_write(3, 17, 0x0);
#if !defined (CONFIG_RAETH_HAS_PORT4)
mii_mgr_write(4, 17, 0x0);
#endif
#endif
#endif
#if defined(CONFIG_RALINK_MT7620)
if ((sysRegRead(0xB000000C) & 0xf) >= 0x5) {
*(unsigned long *)(RALINK_ETH_SW_BASE+0x701c) = 0x800000c; //enlarge FE2SW_IPG
}
#endif // CONFIG_RAETH_7620 //
#if defined (CONFIG_MT7620_FPGA)|| defined (CONFIG_MT7620_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3600) = 0x5e33b;//CPU Port6 Force Link 1G, FC ON
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0010) = 0x7f7f7fe0;//Set Port6 CPU Port
#if defined (CONFIG_P5_RGMII_TO_MAC_MODE) || defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e33b;//(P5, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7014) = 0x1f0c000c; //disable port 0 ~ 4 internal phy, set phy base address to 12
/*MT7620 need mac learning for PPE*/
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x250c) = 0x000fff10;//disable port5 mac learning
//*(unsigned long *)(RALINK_ETH_SW_BASE+0x260c) = 0x000fff10;//disable port6 mac learning
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
//rxclk_skew, txclk_skew = 0
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
#if defined (CONFIG_P5_RGMII_TO_MT7530_MODE)
*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x56330;//(P4, AN)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
//rxclk_skew, txclk_skew = 0
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
/* set MT7530 Port 0 to PHY mode */
mii_mgr_read(31, 0x7804 ,&regValue);
#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
regValue &= ~((1<<13)|(1<<6)|(1<<5)|(1<<15));
regValue |= ((1<<7)|(1<<16)|(1<<20)|(1<<24));
//mii_mgr_write(31, 0x7804 ,0x115c8f);
#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
regValue &= ~((1<<13)|(1<<6)|(1<<20)|(1<<5)|(1<<15));
regValue |= ((1<<7)|(1<<16)|(1<<24));
#endif
regValue &= ~(1<<8); //Enable Port 6
mii_mgr_write(31, 0x7804 ,regValue); //bit 24 standalone switch
/* set MT7530 central align */
mii_mgr_read(31, 0x7830, &regValue);
regValue &= ~1;
regValue |= 1<<1;
mii_mgr_write(31, 0x7830, regValue);
mii_mgr_read(31, 0x7a40, &regValue);
regValue &= ~(1<<30);
mii_mgr_write(31, 0x7a40, regValue);
regValue = 0x855;
mii_mgr_write(31, 0x7a78, regValue);
/*AN should be set after MT7530 HWSTRAP*/
#if defined (CONFIG_GE_RGMII_MT7530_P0_AN)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000100;//(P0, AN polling)
#elif defined (CONFIG_GE_RGMII_MT7530_P4_AN)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x7000) = 0xc5000504;//(P4, AN polling)
#endif
#endif
#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
*(unsigned long *)(SYSCFG1) |= (0x1 << 12);
#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RGMii Mode
enable_auto_negotiate(1);
if (isICPlusGigaPHY(1)) {
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, &phy_val);
phy_val |= 1<<10; //enable pause ability
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 4, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}else if (isMarvellGigaPHY(1)) {
#if defined (CONFIG_MT7620_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
#endif
printk("Reset MARVELL phy1\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}else if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
*(unsigned long *)(SYSCFG1) |= (0x2 << 12);
#else // Port 5 Disabled //
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3500) = 0x8000;//link down
*(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode
#endif
#endif
#if defined (CONFIG_P4_RGMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e33b;//(P4, Force mode, Link Up, 1000Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
//rxclk_skew, txclk_skew = 0
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
#elif defined (CONFIG_P4_MII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=Mii Mode
*(unsigned long *)(SYSCFG1) |= (0x1 << 14);
#elif defined (CONFIG_P4_MAC_TO_PHY_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
*(unsigned long *)(0xb0000060) &= ~(3 << 7); //set MDIO to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE2_MODE=RGMii Mode
enable_auto_negotiate(1);
if (isICPlusGigaPHY(2)) {
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, &phy_val);
phy_val |= 1<<10; //enable pause ability
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 4, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
phy_val |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
}else if (isMarvellGigaPHY(2)) {
#if defined (CONFIG_MT7620_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, phy_val);
#endif
printk("Reset MARVELL phy2\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, phy_val);
}else if (isVtssGigaPHY(2)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P4_RMII_TO_MAC_MODE)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x3400) = 0x5e337;//(P5, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
*(unsigned long *)(0xb0000060) &= ~(1 << 10); //set GE2 to Normal mode
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 14); //GE1_MODE=RvMii Mode
*(unsigned long *)(SYSCFG1) |= (0x2 << 14);
#elif defined (CONFIG_GE_RGMII_MT7530_P0_AN) || defined (CONFIG_GE_RGMII_MT7530_P4_AN)
#else // Port 4 Disabled //
*(unsigned long *)(SYSCFG1) |= (0x3 << 14); //GE2_MODE=RJ45 Mode
*(unsigned long *)(0xb0000060) |= (1 << 10); //set RGMII2 to GPIO mode
#endif
}
#endif
#if defined (CONFIG_RALINK_MT7628)
void mt7628_ephy_init(void)
{
int i;
u32 phy_val;
mii_mgr_write(0, 31, 0x2000); //change G2 page
mii_mgr_write(0, 26, 0x0000);
for(i=0; i<5; i++){
mii_mgr_write(i, 31, 0x8000); //change L0 page
mii_mgr_write(i, 0, 0x3100);
#if defined (CONFIG_RAETH_8023AZ_EEE)
mii_mgr_read(i, 26, &phy_val);// EEE setting
phy_val |= (1 << 5);
mii_mgr_write(i, 26, phy_val);
#else
//disable EEE
mii_mgr_write(i, 13, 0x7);
mii_mgr_write(i, 14, 0x3C);
mii_mgr_write(i, 13, 0x4007);
mii_mgr_write(i, 14, 0x0);
#endif
mii_mgr_write(i, 30, 0xa000);
mii_mgr_write(i, 31, 0xa000); // change L2 page
mii_mgr_write(i, 16, 0x0606);
mii_mgr_write(i, 23, 0x0f0e);
mii_mgr_write(i, 24, 0x1610);
mii_mgr_write(i, 30, 0x1f15);
mii_mgr_write(i, 28, 0x6111);
mii_mgr_read(i, 4, &phy_val);
phy_val |= (1 << 10);
mii_mgr_write(i, 4, phy_val);
}
//100Base AOI setting
mii_mgr_write(0, 31, 0x5000); //change G5 page
mii_mgr_write(0, 19, 0x004a);
mii_mgr_write(0, 20, 0x015a);
mii_mgr_write(0, 21, 0x00ee);
mii_mgr_write(0, 22, 0x0033);
mii_mgr_write(0, 23, 0x020a);
mii_mgr_write(0, 24, 0x0000);
mii_mgr_write(0, 25, 0x024a);
mii_mgr_write(0, 26, 0x035a);
mii_mgr_write(0, 27, 0x02ee);
mii_mgr_write(0, 28, 0x0233);
mii_mgr_write(0, 29, 0x000a);
mii_mgr_write(0, 30, 0x0000);
/* Fix EPHY idle state abnormal behavior */
mii_mgr_write(0, 31, 0x4000); //change G4 page
mii_mgr_write(0, 29, 0x000d);
mii_mgr_write(0, 30, 0x0500);
}
#endif
#if defined (CONFIG_RALINK_RT3052) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
void rt305x_esw_init(void)
{
int i=0;
u32 phy_val=0, val=0;
#if defined (CONFIG_RT3052_ASIC)
u32 phy_val2;
#endif
#if defined (CONFIG_RT5350_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0168) = 0x17;
#endif
/*
* FC_RLS_TH=200, FC_SET_TH=160
* DROP_RLS=120, DROP_SET_TH=80
*/
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0008) = 0xC8A07850;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00E4) = 0x00000000;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0014) = 0x00405555;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0050) = 0x00002001;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0090) = 0x00007f7f;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0098) = 0x00007f3f; //disable VLAN
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00CC) = 0x0002500c;
#ifndef CONFIG_UNH_TEST
*(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x0008a301; //hashing algorithm=XOR48, aging interval=300sec
#else
/*
* bit[30]:1 Backoff Algorithm Option: The latest one to pass UNH test
* bit[29]:1 Length of Received Frame Check Enable
* bit[8]:0 Enable collision 16 packet abort and late collision abort
* bit[7:6]:01 Maximum Packet Length: 1518
*/
*(unsigned long *)(RALINK_ETH_SW_BASE+0x009C) = 0x6008a241;
#endif
*(unsigned long *)(RALINK_ETH_SW_BASE+0x008C) = 0x02404040;
#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC) || defined (CONFIG_RT5350_ASIC) || defined (CONFIG_MT7628_ASIC)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x3f502b28; //Change polling Ext PHY Addr=0x1F
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0x00000000;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x7d000000; //1us cycle number=125 (FE's clock=125Mhz)
#elif defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA) || defined (CONFIG_RT5350_FPGA) || defined (CONFIG_MT7628_FPGA)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) = 0x00f03ff9; //polling Ext PHY Addr=0x0, force port5 as 100F/D (disable auto-polling)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0084) = 0xffdf1f00;
*(unsigned long *)(RALINK_ETH_SW_BASE+0x0110) = 0x0d000000; //1us cycle number=13 (FE's clock=12.5Mhz)
/* In order to use 10M/Full on FPGA board. We configure phy capable to
* 10M Full/Half duplex, so we can use auto-negotiation on PC side */
for(i=0;i<5;i++){
mii_mgr_write(i, 4, 0x0461); //Capable of 10M Full/Half Duplex, flow control on/off
mii_mgr_write(i, 0, 0xB100); //reset all digital logic, except phy_reg
}
#endif
/*
* set port 5 force to 1000M/Full when connecting to switch or iNIC
*/
#if defined (CONFIG_P5_RGMII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3fff; //force 1000M full duplex
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0xf<<20); //rxclk_skew, txclk_skew = 0
#elif defined (CONFIG_P5_MII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
#if defined (CONFIG_RALINK_RT3352)
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=Mii Mode
*(unsigned long *)(SYSCFG1) |= (0x1 << 12);
#endif
#elif defined (CONFIG_P5_MAC_TO_PHY_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(0xb0000060) &= ~(1 << 7); //set MDIO to Normal mode
#if defined (CONFIG_RT3052_ASIC) || defined (CONFIG_RT3352_ASIC)
enable_auto_negotiate(1);
#endif
if (isMarvellGigaPHY(1)) {
#if defined (CONFIG_RT3052_FPGA) || defined (CONFIG_RT3352_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &phy_val);
phy_val &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, phy_val);
#endif
printk("\n Reset MARVELL phy\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &phy_val);
phy_val |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, phy_val);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &phy_val);
phy_val |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, phy_val);
}
if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0001); //extended page
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &phy_val);
printk("Vitesse phy skew: %x --> ", phy_val);
phy_val |= (0x3<<12); // RGMII RX skew compensation= 2.0 ns
phy_val &= ~(0x3<<14);// RGMII TX skew compensation= 0 ns
printk("%x\n", phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, phy_val);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0x0000); //main registers
}
#elif defined (CONFIG_P5_RMII_TO_MAC_MODE)
*(unsigned long *)(0xb0000060) &= ~(1 << 9); //set RGMII to Normal mode
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1<<29); //disable port 5 auto-polling
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(0x3fff);
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) |= 0x3ffd; //force 100M full duplex
#if defined (CONFIG_RALINK_RT3352)
*(unsigned long *)(SYSCFG1) &= ~(0x3 << 12); //GE1_MODE=RvMii Mode
*(unsigned long *)(SYSCFG1) |= (0x2 << 12);
#endif
#else // Port 5 Disabled //
#if defined (CONFIG_RALINK_RT3052)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
*(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
*(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO41-GPIO50)
*(unsigned long *)(0xb0000674) = 0xFFF; //GPIO41-GPIO50 output mode
*(unsigned long *)(0xb000067C) = 0x0; //GPIO41-GPIO50 output low
#elif defined (CONFIG_RALINK_RT3352)
*(unsigned long *)(RALINK_ETH_SW_BASE+0x00C8) &= ~(1 << 29); //port5 auto polling disable
*(unsigned long *)(0xb0000060) |= (1 << 7); //set MDIO to GPIO mode (GPIO22-GPIO23)
*(unsigned long *)(0xb0000624) = 0xC0000000; //GPIO22-GPIO23 output mode
*(unsigned long *)(0xb000062C) = 0xC0000000; //GPIO22-GPIO23 output high
*(unsigned long *)(0xb0000060) |= (1 << 9); //set RGMII to GPIO mode (GPIO24-GPIO35)
*(unsigned long *)(0xb000064C) = 0xFFF; //GPIO24-GPIO35 output mode
*(unsigned long *)(0xb0000654) = 0xFFF; //GPIO24-GPIO35 output high
#elif defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_MT7628)
/* do nothing */
#endif
#endif // CONFIG_P5_RGMII_TO_MAC_MODE //
#if defined (CONFIG_RT3052_ASIC)
rw_rf_reg(0, 0, &phy_val);
phy_val = phy_val >> 4;
if(phy_val > 0x5) {
rw_rf_reg(0, 26, &phy_val);
phy_val2 = (phy_val | (0x3 << 5));
rw_rf_reg(1, 26, &phy_val2);
// reset EPHY
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
rw_rf_reg(1, 26, &phy_val);
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
//#define ENABLE_LDPS
#if defined (ENABLE_LDPS)
mii_mgr_write(0, 12, 0x7eaa);
mii_mgr_write(0, 22, 0x252f); //tune TP_IDL tail and head waveform, enable power down slew rate control
#else
mii_mgr_write(0, 12, 0x0);
mii_mgr_write(0, 22, 0x052f);
#endif
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
} else {
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7058); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0018); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 22, 0x052f); //tune TP_IDL tail and head waveform
mii_mgr_write(0, 27, 0x2fce); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
}
#elif defined (CONFIG_RT3352_ASIC)
//PHY IOT
// reset EPHY
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7016); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
mii_mgr_write(0, 12, 0x7eaa);
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
#elif defined (CONFIG_RT5350_ASIC)
//PHY IOT
// reset EPHY
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
//select local register
mii_mgr_write(0, 31, 0x8000);
for(i=0;i<5;i++){
mii_mgr_write(i, 26, 0x1600); //TX10 waveform coefficient //LSB=0 disable PHY
mii_mgr_write(i, 29, 0x7015); //TX100/TX10 AD/DA current bias
mii_mgr_write(i, 30, 0x0038); //TX100 slew rate control
}
//select global register
mii_mgr_write(0, 31, 0x0);
mii_mgr_write(0, 1, 0x4a40); //enlarge agcsel threshold 3 and threshold 2
mii_mgr_write(0, 2, 0x6254); //enlarge agcsel threshold 5 and threshold 4
mii_mgr_write(0, 3, 0xa17f); //enlarge agcsel threshold 6
mii_mgr_write(0, 12, 0x7eaa);
mii_mgr_write(0, 14, 0x65); //longer TP_IDL tail length
mii_mgr_write(0, 16, 0x0684); //increased squelch pulse count threshold.
mii_mgr_write(0, 17, 0x0fe0); //set TX10 signal amplitude threshold to minimum
mii_mgr_write(0, 18, 0x40ba); //set squelch amplitude to higher threshold
mii_mgr_write(0, 22, 0x253f); //tune TP_IDL tail and head waveform, enable power down slew rate control
mii_mgr_write(0, 27, 0x2fda); //set PLL/Receive bias current are calibrated
mii_mgr_write(0, 28, 0xc410); //change PLL/Receive bias current to internal(RT3350)
mii_mgr_write(0, 29, 0x598b); //change PLL bias current to internal(RT3052_MP3)
mii_mgr_write(0, 31, 0x8000); //select local register
for(i=0;i<5;i++){
//LSB=1 enable PHY
mii_mgr_read(i, 26, &phy_val);
phy_val |= 0x0001;
mii_mgr_write(i, 26, phy_val);
}
#elif defined (CONFIG_MT7628_ASIC)
/*INIT MT7628 PHY HERE*/
val = sysRegRead(RT2880_AGPIOCFG_REG);
#if defined (CONFIG_ETH_ONE_PORT_ONLY)
val |= (MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
val = val & ~(MT7628_P0_EPHY_AIO_EN);
#else
val = val & ~(MT7628_P0_EPHY_AIO_EN | MT7628_P1_EPHY_AIO_EN | MT7628_P2_EPHY_AIO_EN | MT7628_P3_EPHY_AIO_EN | MT7628_P4_EPHY_AIO_EN);
#endif
if ((*((volatile u32 *)(RALINK_SYSCTL_BASE + 0x8))) & 0x10000)
val &= ~0x1f0000;
sysRegWrite(RT2880_AGPIOCFG_REG, val);
val = sysRegRead(RSTCTRL);
val = val | RALINK_EPHY_RST;
sysRegWrite(RSTCTRL, val);
val = val & ~(RALINK_EPHY_RST);
sysRegWrite(RSTCTRL, val);
val = sysRegRead(RALINK_SYSCTL_BASE + 0x64);
#if defined (CONFIG_ETH_ONE_PORT_ONLY)
val &= 0xf003f003;
val |= 0x05540554;
sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0 EPHY LED mode
#else
val &= 0xf003f003;
sysRegWrite(RALINK_SYSCTL_BASE + 0x64, val); // set P0~P4 EPHY LED mode
#endif
udelay(5000);
mt7628_ephy_init();
#endif
}
#endif
/**
* ra2882eth_init - Module Init code
*
* Called by kernel to register net_device
*
*/
int __init ra2882eth_init(void)
{
int ret;
struct net_device *dev = alloc_etherdev(sizeof(END_DEVICE));
#ifdef CONFIG_RALINK_VISTA_BASIC
int sw_id=0;
mii_mgr_read(29, 31, &sw_id);
is_switch_175c = (sw_id == 0x175c) ? 1:0;
#endif
if (!dev)
return -ENOMEM;
strcpy(dev->name, DEV_NAME);
dev->irq = IRQ_ENET0;
dev->addr_len = 6;
dev->base_addr = RALINK_FRAME_ENGINE_BASE;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
rather_probe(dev);
#else
dev->init = rather_probe;
#endif
ra2880_setup_dev_fptable(dev);
/* net_device structure Init */
ethtool_init(dev);
printk("Ralink APSoC Ethernet Driver Initilization. %s %d rx/tx descriptors allocated, mtu = %d!\n", RAETH_VERSION, NUM_RX_DESC, dev->mtu);
#ifdef CONFIG_RAETH_NAPI
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35)
printk("NAPI enable, Tx Ring = %d, Rx Ring = %d\n", NUM_TX_DESC, NUM_RX_DESC);
#else
printk("NAPI enable, weight = %d, Tx Ring = %d, Rx Ring = %d\n", dev->weight, NUM_TX_DESC, NUM_RX_DESC);
#endif
#endif
/* Register net device for the driver */
if ( register_netdev(dev) != 0) {
printk(KERN_WARNING " " __FILE__ ": No ethernet port found.\n");
return -ENXIO;
}
#ifdef CONFIG_RAETH_NETLINK
csr_netlink_init();
#endif
ret = debug_proc_init();
dev_raether = dev;
return ret;
}
void fe_sw_init(void)
{
#if defined (CONFIG_GIGAPHY) || defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
unsigned int regValue = 0;
#endif
// Case1: RT288x/RT3883/MT7621 GE1 + GigaPhy
#if defined (CONFIG_GE1_RGMII_AN)
enable_auto_negotiate(1);
if (isMarvellGigaPHY(1)) {
#if defined (CONFIG_RT3883_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
printk("\n Reset MARVELL phy\n");
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, &regValue);
regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 20, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
regValue |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
#elif defined (CONFIG_MT7621_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 9, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, &regValue);
regValue |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 0, regValue);
#endif
}
if (isVtssGigaPHY(1)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 1);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, &regValue);
printk("Vitesse phy skew: %x --> ", regValue);
regValue |= (0x3<<12);
regValue &= ~(0x3<<14);
printk("%x\n", regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 28, regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR, 31, 0);
}
#if defined (CONFIG_RALINK_MT7621)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x20056300);//(P0, Auto mode)
#endif
#endif // CONFIG_GE1_RGMII_AN //
// Case2: RT3883/MT7621 GE2 + GigaPhy
#if defined (CONFIG_GE2_RGMII_AN)
enable_auto_negotiate(2);
if (isMarvellGigaPHY(2)) {
#if defined (CONFIG_RT3883_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, &regValue);
regValue |= 1<<7; //Add delay to RX_CLK for RXD Outputs
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 20, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
regValue |= 1<<15; //PHY Software Reset
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
#elif defined (CONFIG_MT7621_FPGA)
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, &regValue);
regValue &= ~(3<<8); //turn off 1000Base-T Advertisement (9.9=1000Full, 9.8=1000Half)
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 9, regValue);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, &regValue);
regValue |= 1<<9; //restart AN
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 0, regValue);
#endif
}
if (isVtssGigaPHY(2)) {
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 1);
mii_mgr_read(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, &regValue);
printk("Vitesse phy skew: %x --> ", regValue);
regValue |= (0x3<<12);
regValue &= ~(0x3<<14);
printk("%x\n", regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 28, regValue);
mii_mgr_write(CONFIG_MAC_TO_GIGAPHY_MODE_ADDR2, 31, 0);
}
#if defined (CONFIG_RALINK_MT7621)
//RGMII2=Normal mode
*(volatile u_long *)(RALINK_SYSCTL_BASE + 0x60) &= ~(0x1 << 15);
//GMAC2= RGMII mode
*(volatile u_long *)(SYSCFG1) &= ~(0x3 << 14);
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x20056300);//(P1, Auto mode)
#endif
#endif // CONFIG_GE2_RGMII_AN //
// Case3: RT305x/RT335x/RT6855/RT6855A/MT7620 + EmbeddedSW
#if defined (CONFIG_RT_3052_ESW) && !defined(CONFIG_RALINK_MT7621)
#if defined (CONFIG_RALINK_RT6855) || defined(CONFIG_RALINK_MT7620)
rt_gsw_init();
#elif defined(CONFIG_RALINK_RT6855A)
rt6855A_gsw_init();
#else
rt305x_esw_init();
#endif
#endif
// Case4: RT288x/RT388x/MT7621 GE1 + Internal GigaSW
#if defined (CONFIG_GE1_RGMII_FORCE_1000) || defined (CONFIG_GE1_TRGMII_FORCE_1200)
#if defined (CONFIG_RALINK_MT7621)
/*MT7530 Init*/
setup_internal_gsw();
#else
sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_1000_FD);
#endif
#endif
// Case5: RT388x/MT7621 GE2 + GigaSW
#if defined (CONFIG_GE2_RGMII_FORCE_1000)
#if defined (CONFIG_RALINK_MT7621)
setup_external_gsw();
#else
sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_1000_FD);
#endif
#endif
// Case6: RT288x GE1 /RT388x,MT7621 GE1/GE2 + (10/100 Switch or 100PHY)
#if defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY)
//set GMAC to MII or RvMII mode
#if defined (CONFIG_RALINK_RT3883)
regValue = sysRegRead(SYSCFG1);
#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE1_MII_AN)
regValue &= ~(0x3 << 12);
regValue |= 0x1 << 12; // GE1 MII Mode
#elif defined (CONFIG_GE1_RVMII_FORCE_100)
regValue &= ~(0x3 << 12);
regValue |= 0x2 << 12; // GE1 RvMII Mode
#endif
#if defined (CONFIG_GE2_MII_FORCE_100) || defined (CONFIG_GE2_MII_AN)
regValue &= ~(0x3 << 14);
regValue |= 0x1 << 14; // GE2 MII Mode
#elif defined (CONFIG_GE2_RVMII_FORCE_100)
regValue &= ~(0x3 << 14);
regValue |= 0x2 << 14; // GE2 RvMII Mode
#endif
sysRegWrite(SYSCFG1, regValue);
#endif // CONFIG_RALINK_RT3883 //
#elif defined (CONFIG_RALINK_MT7621)
#if defined (CONFIG_GE1_MII_FORCE_100)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x5e337);//(P0, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#endif
#if defined (CONFIG_GE2_MII_FORCE_100)
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x5e337);//(P1, Force mode, Link Up, 100Mbps, Full-Duplex, FC ON)
#endif
#if defined (CONFIG_GE1_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
enable_auto_negotiate(1);
#if defined (CONFIG_RALINK_MT7621)
sysRegWrite(RALINK_ETH_SW_BASE+0x100, 0x20056300);//(P0, Auto mode)
#endif
#endif
#if defined (CONFIG_GE2_MII_AN) || defined (CONFIG_GE1_RGMII_AN)
enable_auto_negotiate(2);
#if defined (CONFIG_RALINK_MT7621)
sysRegWrite(RALINK_ETH_SW_BASE+0x200, 0x20056300);//(P1, Auto mode)
#endif
#endif
#else
#if defined (CONFIG_GE1_MII_FORCE_100)
#if defined (CONFIG_RALINK_MT7621)
#else
sysRegWrite(MDIO_CFG, INIT_VALUE_OF_FORCE_100_FD);
#endif
#endif
#if defined (CONFIG_GE2_MII_FORCE_100)
#if defined (CONFIG_RALINK_MT7621)
#else
sysRegWrite(MDIO_CFG2, INIT_VALUE_OF_FORCE_100_FD);
#endif
#endif
//add switch configuration here for other switch chips.
#if defined (CONFIG_GE1_MII_FORCE_100) || defined (CONFIG_GE2_MII_FORCE_100)
// IC+ 175x: force IC+ switch cpu port is 100/FD
mii_mgr_write(29, 22, 0x8420);
#endif
#endif // defined (CONFIG_RAETH_ROUTER) || defined (CONFIG_100PHY) //
}
/**
* ra2882eth_cleanup_module - Module Exit code
*
* Cmd 'rmmod' will invode the routine to exit the module
*
*/
void ra2882eth_cleanup_module(void)
{
struct net_device *dev = dev_raether;
END_DEVICE *ei_local;
ei_local = netdev_priv(dev);
#ifdef CONFIG_PSEUDO_SUPPORT
unregister_netdev(ei_local->PseudoDev);
free_netdev(ei_local->PseudoDev);
#endif
unregister_netdev(dev);
RAETH_PRINT("Free ei_local and unregister netdev...\n");
free_netdev(dev);
debug_proc_exit();
#ifdef CONFIG_RAETH_NETLINK
csr_netlink_end();
#endif
}
EXPORT_SYMBOL(set_fe_dma_glo_cfg);
module_init(ra2882eth_init);
module_exit(ra2882eth_cleanup_module);
MODULE_LICENSE("GPL");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment