void rt_hw_eth_init(void) { u64 base_addr = Gmac_base; struct synopGMACNetworkAdapter * synopGMACadapter; static u8 mac_addr0[6] = DEFAULT_MAC_ADDRESS; rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO); rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO); memset(ð_dev, 0, sizeof(eth_dev)); synopGMACadapter = (struct synopGMACNetworkAdapter * )plat_alloc_memory(sizeof (struct synopGMACNetworkAdapter)); if(!synopGMACadapter){ rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); } memset((char *)synopGMACadapter ,0, sizeof (struct synopGMACNetworkAdapter)); synopGMACadapter->synopGMACdev = NULL; synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof (synopGMACdevice)); if(!synopGMACadapter->synopGMACdev){ rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); } memset((char *)synopGMACadapter->synopGMACdev ,0, sizeof (synopGMACdevice)); /* * Attach the device to MAC struct This will configure all the required base addresses * such as Mac base, configuration base, phy base address(out of 32 possible phys) * */ synopGMAC_attach(synopGMACadapter->synopGMACdev,(regbase + MACBASE), regbase + DMABASE, DEFAULT_PHY_BASE, mac_addr0); init_phy(synopGMACadapter->synopGMACdev); synopGMAC_reset(synopGMACadapter->synopGMACdev); /* MII setup */ synopGMACadapter->mii.phy_id_mask = 0x1F; synopGMACadapter->mii.reg_num_mask = 0x1F; synopGMACadapter->mii.dev = synopGMACadapter; synopGMACadapter->mii.mdio_read = mdio_read; synopGMACadapter->mii.mdio_write = mdio_write; synopGMACadapter->mii.phy_id = synopGMACadapter->synopGMACdev->PhyBase; synopGMACadapter->mii.supports_gmii = mii_check_gmii_support(&synopGMACadapter->mii); eth_dev.iobase = base_addr; eth_dev.name = "e0"; eth_dev.priv = synopGMACadapter; eth_dev.dev_addr[0] = mac_addr0[0]; eth_dev.dev_addr[1] = mac_addr0[1]; eth_dev.dev_addr[2] = mac_addr0[2]; eth_dev.dev_addr[3] = mac_addr0[3]; eth_dev.dev_addr[4] = mac_addr0[4]; eth_dev.dev_addr[5] = mac_addr0[5]; eth_dev.parent.parent.type = RT_Device_Class_NetIf; eth_dev.parent.parent.init = eth_init; eth_dev.parent.parent.open = eth_open; eth_dev.parent.parent.close = eth_close; eth_dev.parent.parent.read = eth_read; eth_dev.parent.parent.write = eth_write; eth_dev.parent.parent.control = eth_control; eth_dev.parent.parent.user_data = RT_NULL; eth_dev.parent.eth_tx = rt_eth_tx; eth_dev.parent.eth_rx = rt_eth_rx; eth_device_init(&(eth_dev.parent), "e0"); }
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; }
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; }
int rt_hw_eth_init(void) { u64 base_addr = Gmac_base; struct synopGMACNetworkAdapter *synopGMACadapter; static u8 mac_addr0[6] = DEFAULT_MAC_ADDRESS; int index; rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO); rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO); for (index = 21; index <= 30; index++) { pin_set_purpose(index, PIN_PURPOSE_OTHER); pin_set_remap(index, PIN_REMAP_DEFAULT); } pin_set_purpose(35, PIN_PURPOSE_OTHER); pin_set_remap(35, PIN_REMAP_DEFAULT); *((volatile unsigned int *)0xbfd00424) &= ~(7 << 28); *((volatile unsigned int *)0xbfd00424) |= (1 << 30); //wl rmii memset(ð_dev, 0, sizeof(eth_dev)); synopGMACadapter = (struct synopGMACNetworkAdapter *)plat_alloc_memory(sizeof(struct synopGMACNetworkAdapter)); if (!synopGMACadapter) { rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); } memset((char *)synopGMACadapter, 0, sizeof(struct synopGMACNetworkAdapter)); synopGMACadapter->synopGMACdev = NULL; synopGMACadapter->synopGMACdev = (synopGMACdevice *) plat_alloc_memory(sizeof(synopGMACdevice)); if (!synopGMACadapter->synopGMACdev) { rt_kprintf("Error in Memory Allocataion, Founction : %s \n", __FUNCTION__); } memset((char *)synopGMACadapter->synopGMACdev, 0, sizeof(synopGMACdevice)); /* * Attach the device to MAC struct This will configure all the required base addresses * such as Mac base, configuration base, phy base address(out of 32 possible phys) * */ synopGMAC_attach(synopGMACadapter->synopGMACdev, (regbase + MACBASE), regbase + DMABASE, DEFAULT_PHY_BASE, mac_addr0); init_phy(synopGMACadapter->synopGMACdev); synopGMAC_reset(synopGMACadapter->synopGMACdev); /* MII setup */ synopGMACadapter->mii.phy_id_mask = 0x1F; synopGMACadapter->mii.reg_num_mask = 0x1F; synopGMACadapter->mii.dev = synopGMACadapter; synopGMACadapter->mii.mdio_read = mdio_read; synopGMACadapter->mii.mdio_write = mdio_write; synopGMACadapter->mii.phy_id = synopGMACadapter->synopGMACdev->PhyBase; synopGMACadapter->mii.supports_gmii = mii_check_gmii_support(&synopGMACadapter->mii); eth_dev.iobase = base_addr; eth_dev.name = "e0"; eth_dev.priv = synopGMACadapter; eth_dev.dev_addr[0] = mac_addr0[0]; eth_dev.dev_addr[1] = mac_addr0[1]; eth_dev.dev_addr[2] = mac_addr0[2]; eth_dev.dev_addr[3] = mac_addr0[3]; eth_dev.dev_addr[4] = mac_addr0[4]; eth_dev.dev_addr[5] = mac_addr0[5]; eth_dev.parent.parent.type = RT_Device_Class_NetIf; eth_dev.parent.parent.init = eth_init; eth_dev.parent.parent.open = eth_open; eth_dev.parent.parent.close = eth_close; eth_dev.parent.parent.read = eth_read; eth_dev.parent.parent.write = eth_write; eth_dev.parent.parent.control = eth_control; eth_dev.parent.parent.user_data = RT_NULL; eth_dev.parent.eth_tx = rt_eth_tx; eth_dev.parent.eth_rx = rt_eth_rx; eth_device_init(&(eth_dev.parent), "e0"); eth_device_linkchange(ð_dev.parent, RT_TRUE); //linkup the e0 for lwip to check return 0; }