📄 uec.c
字号:
} if (i==0) { init_enet_offset = 0; } else { init_enet_offset = qe_muram_alloc( sizeof(uec_thread_rx_pram_t), UEC_THREAD_RX_PRAM_ALIGNMENT); } entry_val = ((u32)snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset | (u32)uec_info->riscRx; p_init_enet_param->rxthread[i] = entry_val; } /* Init Tx global parameter pointer */ p_init_enet_param->txglobal = uec->tx_glbl_pram_offset | (u32)uec_info->riscTx; /* Init Tx threads */ for (i = 0; i < thread_tx; i++) { if ((snum = qe_get_snum()) < 0) { printf("%s can not get snum\n", __FUNCTION__); return -ENOMEM; } init_enet_offset = qe_muram_alloc(sizeof(uec_thread_tx_pram_t), UEC_THREAD_TX_PRAM_ALIGNMENT); entry_val = ((u32)snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset | (u32)uec_info->riscTx; p_init_enet_param->txthread[i] = entry_val; } __asm__ __volatile__("sync"); /* Issue QE command */ command = QE_INIT_TX_RX; cecr_subblock = ucc_fast_get_qe_cr_subblock( uec->uec_info->uf_info.ucc_num); qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, init_enet_param_offset); return 0;}static int uec_startup(uec_private_t *uec){ uec_info_t *uec_info; ucc_fast_info_t *uf_info; ucc_fast_private_t *uccf; ucc_fast_t *uf_regs; uec_t *uec_regs; int num_threads_tx; int num_threads_rx; u32 utbipar; enet_interface_e enet_interface; u32 length; u32 align; qe_bd_t *bd; u8 *buf; int i; if (!uec || !uec->uec_info) { printf("%s: uec or uec_info not initial\n", __FUNCTION__); return -EINVAL; } uec_info = uec->uec_info; uf_info = &(uec_info->uf_info); /* Check if Rx BD ring len is illegal */ if ((uec_info->rx_bd_ring_len < UEC_RX_BD_RING_SIZE_MIN) || \ (uec_info->rx_bd_ring_len % UEC_RX_BD_RING_SIZE_ALIGNMENT)) { printf("%s: Rx BD ring len must be multiple of 4, and > 8.\n", __FUNCTION__); return -EINVAL; } /* Check if Tx BD ring len is illegal */ if (uec_info->tx_bd_ring_len < UEC_TX_BD_RING_SIZE_MIN) { printf("%s: Tx BD ring length must not be smaller than 2.\n", __FUNCTION__); return -EINVAL; } /* Check if MRBLR is illegal */ if ((MAX_RXBUF_LEN == 0) || (MAX_RXBUF_LEN % UEC_MRBLR_ALIGNMENT)) { printf("%s: max rx buffer length must be mutliple of 128.\n", __FUNCTION__); return -EINVAL; } /* Both Rx and Tx are stopped */ uec->grace_stopped_rx = 1; uec->grace_stopped_tx = 1; /* Init UCC fast */ if (ucc_fast_init(uf_info, &uccf)) { printf("%s: failed to init ucc fast\n", __FUNCTION__); return -ENOMEM; } /* Save uccf */ uec->uccf = uccf; /* Convert the Tx threads number */ if (uec_convert_threads_num(uec_info->num_threads_tx, &num_threads_tx)) { return -EINVAL; } /* Convert the Rx threads number */ if (uec_convert_threads_num(uec_info->num_threads_rx, &num_threads_rx)) { return -EINVAL; } uf_regs = uccf->uf_regs; /* UEC register is following UCC fast registers */ uec_regs = (uec_t *)(&uf_regs->ucc_eth); /* Save the UEC register pointer to UEC private struct */ uec->uec_regs = uec_regs; /* Init UPSMR, enable hardware statistics (UCC) */ out_be32(&uec->uccf->uf_regs->upsmr, UPSMR_INIT_VALUE); /* Init MACCFG1, flow control disable, disable Tx and Rx */ out_be32(&uec_regs->maccfg1, MACCFG1_INIT_VALUE); /* Init MACCFG2, length check, MAC PAD and CRC enable */ out_be32(&uec_regs->maccfg2, MACCFG2_INIT_VALUE); /* Setup MAC interface mode */ uec_set_mac_if_mode(uec, uec_info->enet_interface); /* Setup MII master clock source */ qe_set_mii_clk_src(uec_info->uf_info.ucc_num); /* Setup UTBIPAR */ utbipar = in_be32(&uec_regs->utbipar); utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK; enet_interface = uec->uec_info->enet_interface; if (enet_interface == ENET_1000_TBI || enet_interface == ENET_1000_RTBI) { utbipar |= (uec_info->phy_address + uec_info->uf_info.ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; } else { utbipar |= (0x10 + uec_info->uf_info.ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; } out_be32(&uec_regs->utbipar, utbipar); /* Allocate Tx BDs */ length = ((uec_info->tx_bd_ring_len * SIZEOFBD) / UEC_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) * UEC_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; if ((uec_info->tx_bd_ring_len * SIZEOFBD) % UEC_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) { length += UEC_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; } align = UEC_TX_BD_RING_ALIGNMENT; uec->tx_bd_ring_offset = (u32)malloc((u32)(length + align)); if (uec->tx_bd_ring_offset != 0) { uec->p_tx_bd_ring = (u8 *)((uec->tx_bd_ring_offset + align) & ~(align - 1)); } /* Zero all of Tx BDs */ memset((void *)(uec->tx_bd_ring_offset), 0, length + align); /* Allocate Rx BDs */ length = uec_info->rx_bd_ring_len * SIZEOFBD; align = UEC_RX_BD_RING_ALIGNMENT; uec->rx_bd_ring_offset = (u32)(malloc((u32)(length + align))); if (uec->rx_bd_ring_offset != 0) { uec->p_rx_bd_ring = (u8 *)((uec->rx_bd_ring_offset + align) & ~(align - 1)); } /* Zero all of Rx BDs */ memset((void *)(uec->rx_bd_ring_offset), 0, length + align); /* Allocate Rx buffer */ length = uec_info->rx_bd_ring_len * MAX_RXBUF_LEN; align = UEC_RX_DATA_BUF_ALIGNMENT; uec->rx_buf_offset = (u32)malloc(length + align); if (uec->rx_buf_offset != 0) { uec->p_rx_buf = (u8 *)((uec->rx_buf_offset + align) & ~(align - 1)); } /* Zero all of the Rx buffer */ memset((void *)(uec->rx_buf_offset), 0, length + align); /* Init TxBD ring */ bd = (qe_bd_t *)uec->p_tx_bd_ring; uec->txBd = bd; for (i = 0; i < uec_info->tx_bd_ring_len; i++) { BD_DATA_CLEAR(bd); BD_STATUS_SET(bd, 0); BD_LENGTH_SET(bd, 0); bd ++; } BD_STATUS_SET((--bd), TxBD_WRAP); /* Init RxBD ring */ bd = (qe_bd_t *)uec->p_rx_bd_ring; uec->rxBd = bd; buf = uec->p_rx_buf; for (i = 0; i < uec_info->rx_bd_ring_len; i++) { BD_DATA_SET(bd, buf); BD_LENGTH_SET(bd, 0); BD_STATUS_SET(bd, RxBD_EMPTY); buf += MAX_RXBUF_LEN; bd ++; } BD_STATUS_SET((--bd), RxBD_WRAP | RxBD_EMPTY); /* Init global Tx parameter RAM */ uec_init_tx_parameter(uec, num_threads_tx); /* Init global Rx parameter RAM */ uec_init_rx_parameter(uec, num_threads_rx); /* Init ethernet Tx and Rx parameter command */ if (uec_issue_init_enet_rxtx_cmd(uec, num_threads_tx, num_threads_rx)) { printf("%s issue init enet cmd failed\n", __FUNCTION__); return -ENOMEM; } return 0;}static int uec_init(struct eth_device* dev, bd_t *bd){ uec_private_t *uec; int err; uec = (uec_private_t *)dev->priv; if (uec->the_first_run == 0) { /* Set up the MAC address */ if (dev->enetaddr[0] & 0x01) { printf("%s: MacAddress is multcast address\n", __FUNCTION__); return -EINVAL; } uec_set_mac_address(uec, dev->enetaddr); uec->the_first_run = 1; } err = uec_open(uec, COMM_DIR_RX_AND_TX); if (err) { printf("%s: cannot enable UEC device\n", dev->name); return err; } return 0;}static void uec_halt(struct eth_device* dev){ uec_private_t *uec = (uec_private_t *)dev->priv; uec_stop(uec, COMM_DIR_RX_AND_TX);}static int uec_send(struct eth_device* dev, volatile void *buf, int len){ uec_private_t *uec; ucc_fast_private_t *uccf; volatile qe_bd_t *bd; volatile u16 status; int i; int result = 0; uec = (uec_private_t *)dev->priv; uccf = uec->uccf; bd = uec->txBd; /* Find an empty TxBD */ for (i = 0; BD_STATUS(bd) & TxBD_READY; i++) { if (i > 0x100000) { printf("%s: tx buffer not ready\n", dev->name); return result; } } /* Init TxBD */ BD_DATA_SET(bd, buf); BD_LENGTH_SET(bd, len); status = BD_STATUS(bd); status &= BD_WRAP; status |= (TxBD_READY | TxBD_LAST); BD_STATUS_SET(bd, status); /* Tell UCC to transmit the buffer */ ucc_fast_transmit_on_demand(uccf); /* Wait for buffer to be transmitted */ status = BD_STATUS(bd); for (i = 0; status & TxBD_READY; i++) { if (i > 0x100000) { printf("%s: tx error\n", dev->name); return result; } status = BD_STATUS(bd); } /* Ok, the buffer be transimitted */ BD_ADVANCE(bd, status, uec->p_tx_bd_ring); uec->txBd = bd; result = 1; return result;}static int uec_recv(struct eth_device* dev){ uec_private_t *uec = dev->priv; volatile qe_bd_t *bd; volatile u16 status; u16 len; u8 *data; bd = uec->rxBd; status = BD_STATUS(bd); while (!(status & RxBD_EMPTY)) { if (!(status & RxBD_ERROR)) { data = BD_DATA(bd); len = BD_LENGTH(bd); NetReceive(data, len); } else { printf("%s: Rx error\n", dev->name); } status &= BD_CLEAN; BD_LENGTH_SET(bd, 0); BD_STATUS_SET(bd, status | RxBD_EMPTY); BD_ADVANCE(bd, status, uec->p_rx_bd_ring); status = BD_STATUS(bd); } uec->rxBd = bd; return 1;}int uec_initialize(int index){ struct eth_device *dev; int i; uec_private_t *uec; uec_info_t *uec_info; int err; dev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!dev) return 0; memset(dev, 0, sizeof(struct eth_device)); /* Allocate the UEC private struct */ uec = (uec_private_t *)malloc(sizeof(uec_private_t)); if (!uec) { return -ENOMEM; } memset(uec, 0, sizeof(uec_private_t)); /* Init UEC private struct, they come from board.h */ if (index == 0) {#ifdef CONFIG_UEC_ETH1 uec_info = ð1_uec_info;#endif } else if (index == 1) {#ifdef CONFIG_UEC_ETH2 uec_info = ð2_uec_info;#endif } else { printf("%s: index is illegal.\n", __FUNCTION__); return -EINVAL; } uec->uec_info = uec_info; sprintf(dev->name, "FSL UEC%d", index); dev->iobase = 0; dev->priv = (void *)uec; dev->init = uec_init; dev->halt = uec_halt; dev->send = uec_send; dev->recv = uec_recv; /* Clear the ethnet address */ for (i = 0; i < 6; i++) dev->enetaddr[i] = 0; eth_register(dev); err = uec_startup(uec); if (err) { printf("%s: Cannot configure net device, aborting.",dev->name); return err; } err = init_phy(dev); if (err) { printf("%s: Cannot initialize PHY, aborting.\n", dev->name); return err; } phy_change(dev); return 1;}#endif /* CONFIG_QE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -