📄 gmac_sl2312.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>#ifdef MIDWAY#include "gmac_sl2312.h"#define diag_printf printf /************************************************************* * Global Variable *************************************************************/unsigned int FLAG_SWITCH = 0; /* if 1-->switch chip presented. if 0-->switch chip unpresented */int vlan_enabled;GMAC_INFO_T gmac_private_data;//static unsigned int tx_free_desc = TX_DESC_NUM;static unsigned int flow_control_enable = 0;//static unsigned int tx_desc_virtual_base = 0;//static unsigned int rx_desc_virtual_base = 0;//static unsigned int tx_buf_virtual_base = 0;//static unsigned int rx_buf_virtual_base = 0;unsigned int full_duplex = 1;unsigned int chip_id=0;void gmac_disable_tx_rx(void);void gmac_enable_tx_rx(void);#ifdef BOARD_DCACHE_ON typedef struct { unsigned char tx_desc_array[TX_DESC_NUM * sizeof(GMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); unsigned char rx_desc_array[RX_DESC_NUM * sizeof(GMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); unsigned char tx_buf_array[TX_BUF_TOT_LEN] __attribute__((aligned(32))); unsigned char rx_buf_array[RX_BUF_TOT_LEN] __attribute__((aligned(32))); unsigned long last_word; } GMAC_NONCACHE_MEM_T; GMAC_NONCACHE_MEM_T *gmac_noncache_mem = (GMAC_NONCACHE_MEM_T *)BOARD_DRAM_NONCACHE_BASE; static unsigned char *tx_desc_array; static unsigned char *rx_desc_array; static unsigned char *rx_buf_array; static unsigned char *tx_buf_array;#else static unsigned char tx_desc_array[TX_DESC_NUM * sizeof(GMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); static unsigned char rx_desc_array[RX_DESC_NUM * sizeof(GMAC_DESCRIPTOR_T)] __attribute__((aligned(32))); static unsigned char tx_buf_array[TX_BUF_TOT_LEN] __attribute__((aligned(32))); static unsigned char rx_buf_array[RX_BUF_TOT_LEN] __attribute__((aligned(32)));#endif/************************************************//* function declare *//************************************************/void gmac_set_mac_addr(unsigned char *mac1, unsigned char *mac2);extern void gmac_set_phy_status(void);extern void gmac_get_phy_status(void);extern char *sys_get_mac_addr(int index);static void gmac_sl2312_start(void);void sl2312_gmac_deliver(void);void sl2312_gmac_diag_poll(void);void gmac_sl2312_send(char *bufp, int total_len);inline void gmac_sl2312_send_diag(GMAC_INFO_T *tp, char *bufp, int total_len);#define sl2312_eth_enable_interrupt() REG32(SL2312_INTERRUPT_BASE + SL2312_IRQ_MASK) &= ~(1<<SL2312_INTERRUPT_GMAC0)#define sl2312_eth_disable_interrupt() REG32(SL2312_INTERRUPT_BASE + SL2312_IRQ_MASK) |= (1<<SL2312_INTERRUPT_GMAC0)/****************************************//* SPI Function Declare *//****************************************/extern void SPI_default(int vlan_enabled);extern unsigned int SPI_get_identifier(void);extern void enet_get_mac_addr(unsigned char* mac);/****************************************//* VLAN Function Declare *//****************************************//************************************************//* function body *//************************************************/#define gmac_read_reg(offset) REG32(GMAC_BASE_ADDR + offset)#define gmac_write_reg(offset, data, mask) REG32(GMAC_BASE_ADDR + offset) = \ (gmac_read_reg(offset) & (~mask)) | \ (data & mask)//static int __init gmac_init_module(void)int gmac_sl2312_init(void){ chip_id = REG32(SL2312_GLOBAL_BASE + GLOBAL_ID) & 0xff; FLAG_SWITCH = 0 ; FLAG_SWITCH = SPI_get_identifier(); if(FLAG_SWITCH) { diag_printf("\nConfig ADM699X...\n"); SPI_default(vlan_enabled); //Add by jason for ADM6996 config }#ifdef GEMINI_ASIC /* set GMAC global register */ REG32(SL2312_GLOBAL_BASE+0x10)=0x00520000; REG32(SL2312_GLOBAL_BASE+0x1c)=0x077707f0; REG32(SL2312_GLOBAL_BASE+0x20)=0x77770000;#endif gmac_sl2312_start(); return TRUE;} /*----------------------------------------------------------------------* gmac_set_mac_addr* set mac address*----------------------------------------------------------------------*/void gmac_set_mac_addr(unsigned char *mac1, unsigned char *mac2){ UINT32 data; data = mac1[0] + (mac1[1]<<8) + (mac1[2]<<16) + (mac1[3]<<24); gmac_write_reg(GMAC_STA_ADD0, data, 0xffffffff); data = mac1[4] + (mac1[5]<<8) + (mac2[0]<<16) + (mac2[1]<<24); gmac_write_reg(GMAC_STA_ADD1, data, 0xffffffff); data = mac2[2] + (mac2[3]<<8) + (mac2[4]<<16) + (mac2[5]<<24); gmac_write_reg(GMAC_STA_ADD2, data, 0xffffffff);} /*----------------------------------------------------------------------* gmac_init_chip*----------------------------------------------------------------------*/static int gmac_init_chip(void){ GMAC_RBNR_T rbnr_val,rbnr_mask; GMAC_CONFIG2_T config2_val; GMAC_CONFIG0_T config0,config0_mask; GMAC_CONFIG1_T config1; UINT32 data; /* chip reset */ /* set RMII mode for testing */ if (full_duplex == 1) { gmac_write_reg(GMAC_STATUS,0x0000001b,0x0000001f); /* 100M full duplex */ } else { gmac_write_reg(GMAC_STATUS,0x00000013,0x0000001f); /* 100M half duplex */ } gmac_get_phy_status(); gmac_set_mac_addr(sys_get_mac_addr(0), sys_get_mac_addr(1)); /* set RX_FLTR register to receive all multicast packet */ gmac_write_reg(GMAC_RX_FLTR,0x0000000f,0x0000001f);// gmac_write_reg(GMAC_RX_FLTR,0x00000001,0x0000001f); /* set per packet buffer size */ config1.bits32 = 0; config1.bits.buf_size = 11; /* buffer size = 2048-byte */ gmac_write_reg(GMAC_CONFIG1,config1.bits32,0x0000000f); /* set flow control threshold */ config2_val.bits32 = 0; config2_val.bits.set_threshold = RX_DESC_NUM/4; config2_val.bits.rel_threshold = RX_DESC_NUM*3/4; gmac_write_reg(GMAC_CONFIG2,config2_val.bits32,0xffffffff); /* init remaining buffer number register */ rbnr_val.bits32 = 0; rbnr_val.bits.buf_remain = RX_DESC_NUM; rbnr_mask.bits32 = 0; rbnr_mask.bits.buf_remain = 0xffff; gmac_write_reg(GMAC_RBNR,rbnr_val.bits32,rbnr_mask.bits32); /* disable TX/RX and disable internal loop back */ config0.bits32 = 0; config0_mask.bits32 = 0; config0.bits.max_len = 2; config0.bits.tx_fc_en = 1; /* enable tx flow control */ config0.bits.rx_fc_en = 1; /* enable rx flow control */ 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.inv_rx_clk = 0; config0.bits.rising_latch = 1; config0_mask.bits.max_len = 3; 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.inv_rx_clk = 1; config0_mask.bits.rising_latch = 1; gmac_write_reg(GMAC_CONFIG0,config0.bits32,config0_mask.bits32); flow_control_enable = 1; /* enable flow control flag */ //flow_control_enable = 0; /* enable flow control flag */ return (0);}/*----------------------------------------------------------------------* gmac_enable_tx_rx*----------------------------------------------------------------------*/void gmac_enable_tx_rx(void){ GMAC_CONFIG0_T config0,config0_mask; /* 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(GMAC_CONFIG0,config0.bits32,config0_mask.bits32); }/*----------------------------------------------------------------------* gmac_disable_tx_rx*----------------------------------------------------------------------*/void gmac_disable_tx_rx(void){ GMAC_CONFIG0_T config0,config0_mask; /* 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(GMAC_CONFIG0,config0.bits32,config0_mask.bits32); } /*----------------------------------------------------------------------* gmac_hw_start*----------------------------------------------------------------------*/static void gmac_hw_start(void){ GMAC_INFO_T *tp = (GMAC_INFO_T *)&gmac_private_data; GMAC_TXDMA_CURR_DESC_T tx_desc; GMAC_RXDMA_CURR_DESC_T rx_desc; GMAC_TXDMA_CTRL_T txdma_ctrl,txdma_ctrl_mask; GMAC_RXDMA_CTRL_T rxdma_ctrl,rxdma_ctrl_mask; GMAC_DMA_STATUS_T dma_status,dma_status_mask; /* program TxDMA Current Descriptor Address register for first descriptor */ tx_desc.bits32 = (unsigned int)(tp->tx_desc_dma); tx_desc.bits.eofie = 1;// tx_desc.bits.dec = 0; tx_desc.bits.sof_eof = 0x03; gmac_write_reg(GMAC_TXDMA_CURR_DESC,tx_desc.bits32,0xffffffff); gmac_write_reg(0xff2c,tx_desc.bits32,0xffffffff); /* tx next descriptor address */ /* program RxDMA Current Descriptor Address register for first descriptor */ rx_desc.bits32 = (unsigned int)(tp->rx_desc_dma); rx_desc.bits.eofie = 1;// rx_desc.bits.dec = 0; rx_desc.bits.sof_eof = 0x03; gmac_write_reg(GMAC_RXDMA_CURR_DESC,rx_desc.bits32,0xffffffff); gmac_write_reg(0xff3c,rx_desc.bits32,0xffffffff); /* rx next descriptor address */ /* enable GMAC interrupt & disable loopback */ dma_status.bits32 = 0; dma_status.bits.loop_back = 0; /* disable DMA loop-back mode */ dma_status.bits.m_cnt_full = 1; dma_status.bits.m_rx_pause_on = 1; dma_status.bits.m_tx_pause_on = 1; dma_status.bits.m_rx_pause_off = 1; dma_status.bits.m_tx_pause_off = 1; dma_status.bits.m_rx_overrun = 1; dma_status_mask.bits32 = 0; dma_status_mask.bits.loop_back = 1; dma_status_mask.bits.m_cnt_full = 1; dma_status_mask.bits.m_rx_pause_on = 1; dma_status_mask.bits.m_tx_pause_on = 1; dma_status_mask.bits.m_rx_pause_off = 1; dma_status_mask.bits.m_tx_pause_off = 1; dma_status_mask.bits.m_rx_overrun = 1; gmac_write_reg(GMAC_DMA_STATUS,dma_status.bits32,dma_status_mask.bits32); /* program tx dma control register */ txdma_ctrl.bits32 = 0; txdma_ctrl.bits.td_start = 0; txdma_ctrl.bits.td_continue = 0; txdma_ctrl.bits.td_chain_mode = 1; /* chain mode */ txdma_ctrl.bits.td_prot = 0; txdma_ctrl.bits.td_burst_size = 2; txdma_ctrl.bits.td_bus = 0; txdma_ctrl.bits.td_endian = 0; txdma_ctrl.bits.td_finish_en = 1; txdma_ctrl.bits.td_fail_en = 1; txdma_ctrl.bits.td_perr_en = 1; txdma_ctrl.bits.td_eod_en = 0; /* disable Tx End of Descriptor Interrupt */ txdma_ctrl.bits.td_eof_en = 1; txdma_ctrl_mask.bits32 = 0; txdma_ctrl_mask.bits.td_start = 1; txdma_ctrl_mask.bits.td_continue = 1; txdma_ctrl_mask.bits.td_chain_mode = 1; txdma_ctrl_mask.bits.td_prot = 15; txdma_ctrl_mask.bits.td_burst_size = 3; txdma_ctrl_mask.bits.td_bus = 1; txdma_ctrl_mask.bits.td_endian = 1; txdma_ctrl_mask.bits.td_finish_en = 1; txdma_ctrl_mask.bits.td_fail_en = 1; txdma_ctrl_mask.bits.td_perr_en = 1; txdma_ctrl_mask.bits.td_eod_en = 1; txdma_ctrl_mask.bits.td_eof_en = 1; gmac_write_reg(GMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32); /* program rx dma control register */ rxdma_ctrl.bits32 = 0; rxdma_ctrl.bits.rd_start = 1; /* start RX DMA transfer */ rxdma_ctrl.bits.rd_continue = 1; /* continue RX DMA operation */ rxdma_ctrl.bits.rd_chain_mode = 1; /* chain mode */ rxdma_ctrl.bits.rd_prot = 0; rxdma_ctrl.bits.rd_burst_size = 2; rxdma_ctrl.bits.rd_bus = 0; rxdma_ctrl.bits.rd_endian = 0; rxdma_ctrl.bits.rd_finish_en = 1; rxdma_ctrl.bits.rd_fail_en = 1; rxdma_ctrl.bits.rd_perr_en = 1; rxdma_ctrl.bits.rd_eod_en = 0; /* disable Rx End of Descriptor Interrupt */ rxdma_ctrl.bits.rd_eof_en = 1; rxdma_ctrl_mask.bits32 = 0; rxdma_ctrl_mask.bits.rd_start = 1; rxdma_ctrl_mask.bits.rd_continue = 1; rxdma_ctrl_mask.bits.rd_chain_mode = 1; rxdma_ctrl_mask.bits.rd_prot = 15; rxdma_ctrl_mask.bits.rd_burst_size = 3; rxdma_ctrl_mask.bits.rd_bus = 1; rxdma_ctrl_mask.bits.rd_endian = 1; rxdma_ctrl_mask.bits.rd_finish_en = 1; rxdma_ctrl_mask.bits.rd_fail_en = 1; rxdma_ctrl_mask.bits.rd_perr_en = 1; rxdma_ctrl_mask.bits.rd_eod_en = 1; rxdma_ctrl_mask.bits.rd_eof_en = 1; gmac_write_reg(GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32); return; } /*----------------------------------------------------------------------* gmac_hw_stop*----------------------------------------------------------------------*/static void gmac_hw_stop(void){ GMAC_TXDMA_CTRL_T txdma_ctrl,txdma_ctrl_mask; GMAC_RXDMA_CTRL_T rxdma_ctrl,rxdma_ctrl_mask; /* program tx dma control register */ txdma_ctrl.bits32 = 0; txdma_ctrl.bits.td_start = 0; txdma_ctrl.bits.td_continue = 0; txdma_ctrl_mask.bits32 = 0; txdma_ctrl_mask.bits.td_start = 1; txdma_ctrl_mask.bits.td_continue = 1; gmac_write_reg(GMAC_TXDMA_CTRL,txdma_ctrl.bits32,txdma_ctrl_mask.bits32); /* program rx dma control register */ rxdma_ctrl.bits32 = 0; rxdma_ctrl.bits.rd_start = 0; /* stop RX DMA transfer */ rxdma_ctrl.bits.rd_continue = 0; /* stop continue RX DMA operation */ rxdma_ctrl_mask.bits32 = 0; rxdma_ctrl_mask.bits.rd_start = 1; rxdma_ctrl_mask.bits.rd_continue = 1; gmac_write_reg(GMAC_RXDMA_CTRL,rxdma_ctrl.bits32,rxdma_ctrl_mask.bits32);}/*----------------------------------------------------------------------* gmac_init_desc_buf*----------------------------------------------------------------------*/static int gmac_init_desc_buf(void){ GMAC_INFO_T *tp = (GMAC_INFO_T *)&gmac_private_data; dma_addr_t tx_first_desc_dma; dma_addr_t rx_first_desc_dma; dma_addr_t tx_first_buf_dma; dma_addr_t rx_first_buf_dma; int i;#ifdef BOARD_DCACHE_ON tx_desc_array = (unsigned char *)&gmac_noncache_mem->tx_desc_array[0]; rx_desc_array = (unsigned char *)&gmac_noncache_mem->rx_desc_array[0]; tx_buf_array = (unsigned char *)&gmac_noncache_mem->tx_buf_array[0]; rx_buf_array = (unsigned char *)&gmac_noncache_mem->rx_buf_array[0];#endif /* allocates TX/RX DMA packet buffer */ tp->tx_bufs = (unsigned char *)tx_buf_array; // memset(tp->tx_bufs,0x00,TX_BUF_TOT_LEN); tp->rx_bufs = (unsigned char *)rx_buf_array; // memset(tp->rx_bufs,0x00,RX_BUF_TOT_LEN); tp->tx_bufs_dma = (unsigned int)tp->tx_bufs; tp->rx_bufs_dma = (unsigned int)tp->rx_bufs;// diag_printf("tx_bufs = %08x\n",(unsigned int)tp->tx_bufs);// diag_printf("rx_bufs = %08x\n",(unsigned int)tp->rx_bufs); /* allocates TX/RX descriptors */ tp->tx_desc = (GMAC_DESCRIPTOR_T *)tx_desc_array; memset(tp->tx_desc,0x00,TX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T)); tp->rx_desc = (GMAC_DESCRIPTOR_T *)rx_desc_array; memset(tp->rx_desc,0x00,RX_DESC_NUM*sizeof(GMAC_DESCRIPTOR_T)); // diag_printf("tx_desc = %08x\n",(unsigned int)tp->tx_desc); // diag_printf("rx_desc = %08x\n",(unsigned int)tp->rx_desc); /* TX descriptors initial */ tp->tx_cur_desc = tp->tx_desc; /* virtual address */ tp->tx_finished_desc = tp->tx_desc; /* virtual address */ tp->tx_desc_dma = (unsigned int)tp->tx_desc; tx_first_desc_dma = tp->tx_desc_dma; /* physical address */ tx_first_buf_dma = tp->tx_bufs_dma; for (i = 1; i < TX_DESC_NUM; i++) { tp->tx_desc->frame_ctrl.bits_tx_out.own = CPU; /* set owner to CPU */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -