/** * Function to reset the GMAC core. * This reests the DMA and GMAC core. After reset all the registers holds their respective reset value * @param[in] pointer to synopGMACdevice. * \return 0 on success else return the error status. */ s32 synopGMAC_reset(synopGMACdevice *gmacdev) { u32 data = 0; int cnt = 0; synopGMACWriteReg(gmacdev->DmaBase, DmaBusMode ,DmaResetOn); plat_delay(DEFAULT_LOOP_VARIABLE); while (1) { data = synopGMACReadReg(gmacdev->DmaBase, DmaBusMode); TR("DATA after Reset = %08x\n",data); if (data & DmaResetOn) { if(cnt > 10) printf("Bus Mode Reg after reset: 0x%08x\n", data); // udelay(1); cnt ++; } else break; } return 0; }
void eth_rx_irq(int irqno,void *param) { struct rt_eth_dev *dev = ð_dev; struct synopGMACNetworkAdapter *adapter = dev->priv; //DEBUG_MES("in irq!!\n"); #ifdef RT_USING_GMAC_INT_MODE int i ; for(i = 0; i < 7200; i++) ; #endif /*RT_USING_GMAC_INT_MODE*/ synopGMACdevice * gmacdev = (synopGMACdevice *)adapter->synopGMACdev; u32 interrupt,dma_status_reg; s32 status; u32 dma_addr; //rt_kprintf("irq i = %d\n", i++); dma_status_reg = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); if(dma_status_reg == 0) { rt_kprintf("dma_status ==0 \n"); return; } //rt_kprintf("dma_status_reg is 0x%x\n", dma_status_reg); u32 gmacstatus; synopGMAC_disable_interrupt_all(gmacdev); gmacstatus = synopGMACReadReg(gmacdev->MacBase,GmacStatus); if(dma_status_reg & GmacPmtIntr){ rt_kprintf("%s:: Interrupt due to PMT module\n",__FUNCTION__); //synopGMAC_linux_powerup_mac(gmacdev); } if(dma_status_reg & GmacMmcIntr){ rt_kprintf("%s:: Interrupt due to MMC module\n",__FUNCTION__); DEBUG_MES("%s:: synopGMAC_rx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_rx_int_status(gmacdev)); DEBUG_MES("%s:: synopGMAC_tx_int_status = %08x\n",__FUNCTION__,synopGMAC_read_mmc_tx_int_status(gmacdev)); } if(dma_status_reg & GmacLineIntfIntr){ rt_kprintf("%s:: Interrupt due to GMAC LINE module\n",__FUNCTION__); } interrupt = synopGMAC_get_interrupt_type(gmacdev); //rt_kprintf("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt); if(interrupt & synopGMACDmaError){ u8 mac_addr0[6]; rt_kprintf("%s::Fatal Bus Error Inetrrupt Seen\n",__FUNCTION__); memcpy(mac_addr0,dev->dev_addr,6); synopGMAC_disable_dma_tx(gmacdev); synopGMAC_disable_dma_rx(gmacdev); synopGMAC_take_desc_ownership_tx(gmacdev); synopGMAC_take_desc_ownership_rx(gmacdev); synopGMAC_init_tx_rx_desc_queue(gmacdev); synopGMAC_reset(gmacdev); synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, mac_addr0); synopGMAC_dma_bus_mode_init(gmacdev,DmaFixedBurstEnable| DmaBurstLength8 | DmaDescriptorSkip2 ); synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward); synopGMAC_init_rx_desc_base(gmacdev); synopGMAC_init_tx_desc_base(gmacdev); synopGMAC_mac_init(gmacdev); synopGMAC_enable_dma_rx(gmacdev); synopGMAC_enable_dma_tx(gmacdev); } if(interrupt & synopGMACDmaRxNormal){ //DEBUG_MES("%s:: Rx Normal \n", __FUNCTION__); //synop_handle_received_data(netdev); eth_device_ready(ð_dev.parent); } if(interrupt & synopGMACDmaRxAbnormal){ //rt_kprintf("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__); if(GMAC_Power_down == 0){ adapter->synopGMACNetStats.rx_over_errors++; synopGMACWriteReg(gmacdev->DmaBase, DmaStatus ,0x80); synopGMAC_resume_dma_rx(gmacdev); } } if(interrupt & synopGMACDmaRxStopped){ rt_kprintf("%s::Receiver stopped seeing Rx interrupts\n",__FUNCTION__); //Receiver gone in to stopped state } if(interrupt & synopGMACDmaTxNormal){ DEBUG_MES("%s::Finished Normal Transmission \n",__FUNCTION__); // synop_handle_transmit_over(netdev); } if(interrupt & synopGMACDmaTxAbnormal){ rt_kprintf("%s::Abnormal Tx Interrupt Seen\n",__FUNCTION__); } if(interrupt & synopGMACDmaTxStopped){ TR("%s::Transmitter stopped sending the packets\n",__FUNCTION__); if(GMAC_Power_down == 0){ // If Mac is not in powerdown synopGMAC_disable_dma_tx(gmacdev); synopGMAC_take_desc_ownership_tx(gmacdev); synopGMAC_enable_dma_tx(gmacdev); // netif_wake_queue(netdev); TR("%s::Transmission Resumed\n",__FUNCTION__); } } /* Enable the interrrupt before returning from ISR*/ synopGMAC_enable_interrupt(gmacdev,DmaIntEnable); return; }
rt_err_t rt_eth_tx(rt_device_t device, struct pbuf* p) { /* lock eth device */ rt_sem_take(&sem_lock, RT_WAITING_FOREVER); DEBUG_MES("in %s\n", __FUNCTION__); s32 status; u32 pbuf; u64 dma_addr; u32 offload_needed = 0; u32 index; DmaDesc * dpr; struct rt_eth_dev *dev = (struct rt_eth_dev *) device; struct synopGMACNetworkAdapter *adapter; synopGMACdevice * gmacdev; adapter = (struct synopGMACNetworkAdapter *) dev->priv; if(adapter == NULL) return -1; gmacdev = (synopGMACdevice *) adapter->synopGMACdev; if(gmacdev == NULL) return -1; if(!synopGMAC_is_desc_owned_by_dma(gmacdev->TxNextDesc)) { pbuf = (u32)plat_alloc_memory(p->len); //pbuf = (u32)pbuf_alloc(PBUF_LINK, p->len, PBUF_RAM); if(pbuf == 0) { rt_kprintf("===error in alloc bf1\n"); return -1; } DEBUG_MES("p->len = %d\n", p->len); memcpy((void *)pbuf, p->payload, p->len); dma_addr = plat_dma_map_single(gmacdev,(void*)pbuf,p->len); status = synopGMAC_set_tx_qptr(gmacdev,dma_addr,p->len,pbuf,0,0,0,offload_needed,&index,dpr); if(status < 0){ rt_kprintf("%s No More Free Tx Descriptors\n",__FUNCTION__); plat_free_memory((void *)pbuf); return -16; } } synopGMAC_resume_dma_tx(gmacdev); s32 desc_index; u32 data1, data2; u32 dma_addr1, dma_addr2; u32 length1, length2; #ifdef ENH_DESC_8W u32 ext_status; u16 time_stamp_higher; u32 time_stamp_high; u32 time_stamp_low; #endif do { #ifdef ENH_DESC_8W desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2,&ext_status,&time_stamp_high,&time_stamp_low); synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher); #else desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1, &dma_addr2, &length2, &data2); #endif if(desc_index >= 0 && data1 != 0){ #ifdef IPC_OFFLOAD if(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)){ rt_kprintf("Harware Failed to Insert IPV4 Header Checksum\n"); } if(synopGMAC_is_tx_payload_checksum_error(gmacdev, status)){ rt_kprintf("Harware Failed to Insert Payload Checksum\n"); } #endif plat_free_memory((void *)(data1)); //sw: data1 = buffer1 if(synopGMAC_is_desc_valid(status)){ adapter->synopGMACNetStats.tx_bytes += length1; adapter->synopGMACNetStats.tx_packets++; } else { adapter->synopGMACNetStats.tx_errors++; adapter->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status); adapter->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status); } } adapter->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status); } while(desc_index >= 0); /* unlock eth device */ rt_sem_release(&sem_lock); // rt_kprintf("output %d bytes\n", p->len); u32 test_data; test_data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); return RT_EOK; }
static rt_err_t eth_init(rt_device_t device ) { struct eth_device *eth_device = (struct eth_device *)device; RT_ASSERT(eth_device != RT_NULL); s32 ijk; s32 status = 0; u64 dma_addr; u32 Mac_changed = 0; struct pbuf *pbuf; u8 macaddr[6] = DEFAULT_MAC_ADDRESS; struct rt_eth_dev *dev = ð_dev; struct synopGMACNetworkAdapter *adapter = dev->priv; synopGMACdevice * gmacdev = (synopGMACdevice *)adapter->synopGMACdev; synopGMAC_reset(gmacdev); synopGMAC_attach(gmacdev,(regbase + MACBASE),(regbase + DMABASE), DEFAULT_PHY_BASE, macaddr); synopGMAC_read_version(gmacdev); synopGMAC_set_mdc_clk_div(gmacdev,GmiiCsrClk3); gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev); init_phy(adapter->synopGMACdev); rt_kprintf("tx desc_queue\n"); synopGMAC_setup_tx_desc_queue(gmacdev,TRANSMIT_DESC_SIZE, RINGMODE); synopGMAC_init_tx_desc_base(gmacdev); rt_kprintf("rx desc_queue\n"); synopGMAC_setup_rx_desc_queue(gmacdev,RECEIVE_DESC_SIZE, RINGMODE); synopGMAC_init_rx_desc_base(gmacdev); DEBUG_MES("DmaRxBaseAddr = %08x\n",synopGMACReadReg(gmacdev->DmaBase,DmaRxBaseAddr)); // u32 dmaRx_Base_addr = synopGMACReadReg(gmacdev->DmaBase,DmaRxBaseAddr); // rt_kprintf("first_desc_addr = 0x%x\n", dmaRx_Base_addr); #ifdef ENH_DESC_8W synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip2 | DmaDescriptor8Words ); #else //synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip1); synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength4 | DmaDescriptorSkip2); #endif synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward |DmaTxSecondFrame|DmaRxThreshCtrl128); status = synopGMAC_check_phy_init(adapter); synopGMAC_mac_init(gmacdev); synopGMAC_pause_control(gmacdev); #ifdef IPC_OFFLOAD synopGMAC_enable_rx_chksum_offload(gmacdev); synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); #endif u32 skb; do{ skb = (u32)plat_alloc_memory(RX_BUF_SIZE); //should skb aligned here? if(skb == RT_NULL){ rt_kprintf("ERROR in skb buffer allocation\n"); break; } dma_addr = plat_dma_map_single(gmacdev,(void *)skb,RX_BUF_SIZE); //获取 skb 的 dma 地址 status = synopGMAC_set_rx_qptr(gmacdev,dma_addr,RX_BUF_SIZE,(u32)skb,0,0,0); if(status < 0) { rt_kprintf("status < 0!!\n"); plat_free_memory((void *)skb); } }while(status >= 0 && (status < (RECEIVE_DESC_SIZE - 1))); synopGMAC_clear_interrupt(gmacdev); synopGMAC_disable_mmc_tx_interrupt(gmacdev, 0xFFFFFFFF); synopGMAC_disable_mmc_rx_interrupt(gmacdev, 0xFFFFFFFF); synopGMAC_disable_mmc_ipc_rx_interrupt(gmacdev, 0xFFFFFFFF); // synopGMAC_disable_interrupt_all(gmacdev); synopGMAC_enable_interrupt(gmacdev, DmaIntEnable); synopGMAC_enable_dma_rx(gmacdev); synopGMAC_enable_dma_tx(gmacdev); plat_delay(DEFAULT_LOOP_VARIABLE); synopGMAC_check_phy_init(adapter); synopGMAC_mac_init(gmacdev); rt_timer_init(&dev->link_timer, "link_timer", synopGMAC_linux_cable_unplug_function, (void *)adapter, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC); rt_timer_start(&dev->link_timer); #ifdef RT_USING_GMAC_INT_MODE /* installl isr */ DEBUG_MES("%s\n", __FUNCTION__); rt_hw_interrupt_install(LS1C_MAC_IRQ, eth_rx_irq, RT_NULL, "e0_isr"); rt_hw_interrupt_umask(LS1C_MAC_IRQ); #else rt_timer_init(&dev->rx_poll_timer, "rx_poll_timer", eth_rx_irq, (void *)adapter, 1, RT_TIMER_FLAG_PERIODIC); rt_timer_start(&dev->rx_poll_timer); #endif /*RT_USING_GMAC_INT_MODE*/ rt_kprintf("eth_inited!\n"); return RT_EOK; }