📄 sl_lepus_gmac.c
字号:
/***************************************************************************** Copyright Storlink Corp 2005. All rights reserved. *--------------------------------------------------------------------------* Name : emac_sl2312.c* Description : * Ethernet device driver for Storlink SL2312 Chip** History** Date Writer Description* ----------- ----------- -------------------------------------------------* 04/25/2005 Gary Chen Create and implement from Jason's Redboot code*****************************************************************************/#include <define.h>#include <board_config.h>#include <sl2312.h>#if defined(LEPUS_FPGA) || defined(LEPUS_ASIC)#include "sl_lepus_gmac.h"#define SKB_RESERVE_BYTES 16 // to reserve SKB header pointer#define RX_INSERT_BYTES RX_INSERT_2_BYTE#define GMAC_TXQ_NUM 6#define hal_cache_consistent_sync#define GMAC_EXISTED_FLAG 0x5566abcd/************************************************************* * Global Variable *************************************************************/static int gmac_initialized = 0;static TOE_INFO_T toe_private_data;//unsigned int FLAG_SWITCH;extern char broadcast_mac[6];int mac_dump_rxpkt;int mac_dump_txpkt;int mac_status_error;int txbuf_ptr[TOE_SW_TXQ_NUM*TOE_GMAC1_SWTXQ_DESC_NUM];static UINT32 gmac_poll_phy_ticks;#define toe_gmac_enable_interrupt(irq) REG32(SL2312_INTERRUPT_BASE + SL2312_IRQ_MASK) &= ~(1<<SL2312_INTERRUPT_GMAC0)#define toe_gmac_disable_interrupt(irq) REG32(SL2312_INTERRUPT_BASE + SL2312_IRQ_MASK) |= (1<<SL2312_INTERRUPT_GMAC0)void toe_gmac_enable_tx_rx(void);void toe_gmac_disable_tx_rx(void);void gmac_set_mac_address(GMAC_INFO_T *tp, unsigned char *mac1, unsigned char *mac2);unsigned int gmac_num;/*----------------------------------------------------------------------* gmac_read_reg*----------------------------------------------------------------------*/// static inline unsigned int gmac_read_reg(unsigned int base, unsigned int offset)unsigned int gmac_read_reg(unsigned int base, unsigned int offset){ volatile unsigned int reg_val; reg_val = readl(base + offset); return (reg_val);}/*----------------------------------------------------------------------* gmac_write_reg*----------------------------------------------------------------------*/// static inline void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask)void gmac_write_reg(unsigned int base, unsigned int offset,unsigned int data,unsigned int bit_mask){ volatile unsigned int reg_val; unsigned int *addr; reg_val = ( gmac_read_reg(base, offset) & (~bit_mask) ) | (data & bit_mask); addr = (unsigned int *)(base + offset); writel(reg_val,addr); return;}/*----------------------------------------------------------------------* dm_byte*----------------------------------------------------------------------*/void dm_byte(UINT32 location, int length){ UINT8 *start_p, *end_p, *curr_p; int in_flash_range = 0; char *datap, *cp, data, *bufp; int i; //if (length > 1024) // length = 1024; start_p = (UINT8 *)location; end_p = start_p + length; bufp = datap = (char *)malloc(length+128); if (datap == NULL) { dbg_printf(("No free memory!\n")); return; } if (location >= (UINT32)SL2312_FLASH_SHADOW && location <= (UINT32)((UINT32)SL2312_FLASH_SHADOW + 0x10000000)) in_flash_range = 1; // read data if (in_flash_range) hal_flash_enable(); curr_p=(UINT8 *)(location & 0xfffffff0); cp = datap; for (; curr_p<end_p;) *cp++ = *curr_p++; if (in_flash_range) hal_flash_disable(); curr_p=(UINT8 *)(location & 0xfffffff0); while (curr_p < end_p) { UINT8 *p1, *p2; printf("0x%08x: ",(UINT32)curr_p & 0xfffffff0); p1 = curr_p; p2 = datap; // dump data for (i=0; i<16; i++) { if (curr_p < start_p || curr_p >= end_p) printf(" "); else { data = *datap; printf("%02X ", data); } if (i==7) printf("- "); curr_p++; datap++; } // dump ascii curr_p = p1; datap = p2; for (i=0; i<16; i++) { if (curr_p < start_p || curr_p >= end_p) printf("."); else { data = *datap ; if (data<0x20 || data>0x7f || data==0x25) printf("."); else printf("%c", data);; } curr_p++; datap++; } printf("\n"); } free(bufp);}/*----------------------------------------------------------------------* toe_gmac_disable_tx_rx*----------------------------------------------------------------------*/void toe_gmac_disable_tx_rx(void){ TOE_INFO_T *toe; GMAC_INFO_T *tp; GMAC_CONFIG0_T config0,config0_mask; toe = (TOE_INFO_T *)&toe_private_data; tp = (GMAC_INFO_T *)&toe->gmac; //GMAC_INFO_T *tp = sc->driver_private; /* enable TX/RX */ config0.bits32 = 0; config0_mask.bits32 = 0; config0.bits.dis_rx = 1; /* disable rx */ config0.bits.dis_tx = 1; /* disable tx */ config0_mask.bits.dis_rx = 1; config0_mask.bits.dis_tx = 1; gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32); //printf("toe_gmac_disable_tx_rx tp->base_addr %x gmac_read_reg(tp->base_addr, GMAC_CONFIG0) : %x\n",tp->base_addr,gmac_read_reg(tp->base_addr, GMAC_CONFIG0)); //printf("toe->gmac.port_id : %x\n",toe->gmac.port_id);} /*----------------------------------------------------------------------* toe_gmac_sw_reset*----------------------------------------------------------------------*/static void toe_gmac_sw_reset(void){ //REG32(GMAC_GLOBAL_BASE_ADDR + GLOBAL_RESET) |= 0x00000060; unsigned int reg_val; reg_val = REG32(GMAC_GLOBAL_BASE_ADDR+GLOBAL_RESET) | 0x00000060; /* GMAC0 S/W reset */ REG32(GMAC_GLOBAL_BASE_ADDR+GLOBAL_RESET) = reg_val; hal_delay_us(100); return; return;}/*----------------------------------------------------------------------* toe_gmac_init_chip*----------------------------------------------------------------------*/static int toe_gmac_init_chip(GMAC_INFO_T *tp){ GMAC_CONFIG0_T config0,config0_mask; GMAC_CONFIG1_T config1; GMAC_CONFIG2_T config2_val; GMAC_CONFIG3_T config3_val; unsigned int status; GMAC_TX_WCR0_T hw_weigh; GMAC_TX_WCR1_T sw_weigh; /* set PHY operation mode */ status = tp->phy_mode<<5 | 0x11; if (tp->auto_nego_cfg) status |= (tp->full_duplex_status<<3) | (tp->speed_status<<1); else status |= (tp->full_duplex_cfg<<3) | (tp->speed_cfg<<1); if(gmac_num) status = 0x7d; gmac_write_reg(tp->base_addr, GMAC_STATUS,status, 0x0000007f); gmac_set_mac_address(tp, tp->mac_addr1, tp->mac_addr2); /* set RX_FLTR register to receive all multicast packet */ // gmac_write_reg(tp->base_addr, GMAC_RX_FLTR, 0x0000001F,0x0000001f); //gmac_write_reg(tp->base_addr, GMAC_RX_FLTR, 0x000001f,0x0000001f); gmac_write_reg(tp->base_addr, GMAC_RX_FLTR,0x000000005,0x00000005); /* set flow control threshold */ config1.bits32 = 0; config1.bits.set_threshold = 8; config1.bits.rel_threshold = 32; gmac_write_reg(tp->base_addr, GMAC_CONFIG1, config1.bits32,0xffffffff); /* set SW free queue flow control threshold */ config2_val.bits32 = 0; config2_val.bits.set_threshold = TOE_SW_FREEQ_DESC_NUM/4; config2_val.bits.rel_threshold = TOE_SW_FREEQ_DESC_NUM*3/4; gmac_write_reg(tp->base_addr, GMAC_CONFIG2, config2_val.bits32,0xffffffff); /* set HW free queue flow control threshold */ config3_val.bits32 = 0; config3_val.bits.set_threshold = TOE_HW_FREEQ_DESC_NUM/4; config3_val.bits.rel_threshold = TOE_HW_FREEQ_DESC_NUM*3/4; gmac_write_reg(tp->base_addr, GMAC_CONFIG3, config3_val.bits32,0xffffffff); /* disable TX/RX and disable internal loop back */ config0.bits32 = 0; config0_mask.bits32 = 0; config0.bits.max_len = 2; if (tp->flow_control_enable==1) { config0.bits.tx_fc_en = 1; /* enable tx flow control */ config0.bits.rx_fc_en = 1; /* enable rx flow control */ //printk("Enable MAC Flow Control...\n"); } else { config0.bits.tx_fc_en = 0; /* disable tx flow control */ config0.bits.rx_fc_en = 0; /* disable rx flow control */ //printk("Disable MAC Flow Control...\n"); } config0.bits.dis_rx = 1; /* disable rx */ config0.bits.dis_tx = 1; /* disable tx */ config0.bits.loop_back = 0; /* enable/disable GMAC loopback */ config0.bits.rgmii_en = 0;#ifdef LEPUS_ASIC config0.bits.rgmm_edge = 1; config0.bits.rxc_inv = 0;#else config0.bits.rgmm_edge =0 ; config0.bits.rxc_inv = 0;#endif config0.bits.ipv4_rx_chksum = 1; /* enable H/W to check ip checksum */ config0.bits.ipv6_rx_chksum = 1; /* enable H/W to check ip checksum */ config0.bits.port0_chk_hwq = 1; config0.bits.port1_chk_hwq = 1; config0.bits.port0_chk_toeq = 1; config0.bits.port1_chk_toeq = 1; config0.bits.port0_chk_classq = 1; config0.bits.port1_chk_classq = 1; config0.bits.rx_err_detect = 1; config0_mask.bits.max_len = 7; config0_mask.bits.tx_fc_en = 1; config0_mask.bits.rx_fc_en = 1; config0_mask.bits.dis_rx = 1; config0_mask.bits.dis_tx = 1; config0_mask.bits.loop_back = 1; config0_mask.bits.rgmii_en = 1; config0_mask.bits.rgmm_edge = 1; config0_mask.bits.rxc_inv = 1; config0_mask.bits.ipv4_rx_chksum = 1; config0_mask.bits.ipv6_rx_chksum = 1; config0_mask.bits.port0_chk_hwq = 1; config0_mask.bits.port1_chk_hwq = 1; config0_mask.bits.port0_chk_toeq = 1; config0_mask.bits.port1_chk_toeq = 1; config0_mask.bits.port0_chk_classq = 1; config0_mask.bits.port1_chk_classq = 1; config0_mask.bits.rx_err_detect = 1; gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32, config0_mask.bits32); if(gmac_num) { status = 0x796c200; gmac_write_reg(tp->base_addr, GMAC_CONFIG0, status, 0xffffffff); }#if 0 hw_weigh.bits32 = 0; hw_weigh.bits.hw_tq3 = 1; hw_weigh.bits.hw_tq2 = 1; hw_weigh.bits.hw_tq1 = 1; hw_weigh.bits.hw_tq0 = 1; gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_0_REG, hw_weigh.bits32, 0xffffffff); sw_weigh.bits32 = 0; sw_weigh.bits.sw_tq5 = 1; sw_weigh.bits.sw_tq4 = 1; sw_weigh.bits.sw_tq3 = 1; sw_weigh.bits.sw_tq2 = 1; sw_weigh.bits.sw_tq1 = 1; sw_weigh.bits.sw_tq0 = 1; gmac_write_reg(tp->dma_base_addr, GMAC_TX_WEIGHTING_CTRL_1_REG, sw_weigh.bits32, 0xffffffff);#endif if(gmac_num) { tp->pre_phy_status == LINK_UP; toe_gmac_enable_tx_rx(); } return (0);}/*----------------------------------------------------------------------* gmac_set_mac_address* set mac address*----------------------------------------------------------------------*/void gmac_set_mac_address(GMAC_INFO_T *tp, unsigned char *mac1, unsigned char *mac2){ UINT32 data; memcpy(tp->mac_addr1, mac1, ETHER_ADDR_LEN); memcpy(tp->mac_addr2, mac2, ETHER_ADDR_LEN); data = mac1[0] + (mac1[1]<<8) + (mac1[2]<<16) + (mac1[3]<<24); gmac_write_reg(tp->base_addr, GMAC_STA_ADD0, data, 0xffffffff); data = mac1[4] + (mac1[5]<<8) + (mac2[0]<<16) + (mac2[1]<<24); gmac_write_reg(tp->base_addr, GMAC_STA_ADD1, data, 0xffffffff); data = mac2[2] + (mac2[3]<<8) + (mac2[4]<<16) + (mac2[5]<<24); gmac_write_reg(tp->base_addr, GMAC_STA_ADD2, data, 0xffffffff);}/*----------------------------------------------------------------------* toe_gmac_enable_tx_rx*----------------------------------------------------------------------*/void toe_gmac_enable_tx_rx(void){ int tmp; TOE_INFO_T *toe; GMAC_INFO_T *tp; GMAC_CONFIG0_T config0,config0_mask; toe = (TOE_INFO_T *)&toe_private_data; tp = (GMAC_INFO_T *)&toe->gmac; //printf("toe_gmac_disable_tx_rx tp->base_addr %x\n",tp->base_addr); /* enable TX/RX */ config0.bits32 = 0; config0_mask.bits32 = 0; config0.bits.dis_rx = 0; /* enable rx */ config0.bits.dis_tx = 0; /* enable tx */ config0_mask.bits.dis_rx = 1; config0_mask.bits.dis_tx = 1; gmac_write_reg(tp->base_addr, GMAC_CONFIG0, config0.bits32,config0_mask.bits32); //printf("toe_gmac_enable_tx_rx tp->base_addr %x gmac_read_reg(tp->base_addr, GMAC_CONFIG0) : %x\n",tp->base_addr,gmac_read_reg(tp->base_addr, GMAC_CONFIG0)); //printf("toe->gmac.port_id : %x\n",toe->gmac.port_id); //if(gmac_num)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -