📄 uec.c
字号:
/* * Copyright (C) 2006 Freescale Semiconductor, Inc. * * Dave Liu <daveliu@freescale.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include "common.h"#include "net.h"#include "malloc.h"#include "asm/errno.h"#include "asm/io.h"#include "asm/immap_qe.h"#include "qe.h"#include "uccf.h"#include "uec.h"#include "uec_phy.h"#if defined(CONFIG_QE)#ifdef CONFIG_UEC_ETH1static uec_info_t eth1_uec_info = { .uf_info = { .ucc_num = CFG_UEC1_UCC_NUM, .rx_clock = CFG_UEC1_RX_CLK, .tx_clock = CFG_UEC1_TX_CLK, .eth_type = CFG_UEC1_ETH_TYPE, }, .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, .rx_bd_ring_len = 16, .phy_address = CFG_UEC1_PHY_ADDR, .enet_interface = CFG_UEC1_INTERFACE_MODE,};#endif#ifdef CONFIG_UEC_ETH2static uec_info_t eth2_uec_info = { .uf_info = { .ucc_num = CFG_UEC2_UCC_NUM, .rx_clock = CFG_UEC2_RX_CLK, .tx_clock = CFG_UEC2_TX_CLK, .eth_type = CFG_UEC2_ETH_TYPE, }, .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, .rx_bd_ring_len = 16, .phy_address = CFG_UEC2_PHY_ADDR, .enet_interface = CFG_UEC2_INTERFACE_MODE,};#endifstatic int uec_mac_enable(uec_private_t *uec, comm_dir_e mode){ uec_t *uec_regs; u32 maccfg1; if (!uec) { printf("%s: uec not initial\n", __FUNCTION__); return -EINVAL; } uec_regs = uec->uec_regs; maccfg1 = in_be32(&uec_regs->maccfg1); if (mode & COMM_DIR_TX) { maccfg1 |= MACCFG1_ENABLE_TX; out_be32(&uec_regs->maccfg1, maccfg1); uec->mac_tx_enabled = 1; } if (mode & COMM_DIR_RX) { maccfg1 |= MACCFG1_ENABLE_RX; out_be32(&uec_regs->maccfg1, maccfg1); uec->mac_rx_enabled = 1; } return 0;}static int uec_mac_disable(uec_private_t *uec, comm_dir_e mode){ uec_t *uec_regs; u32 maccfg1; if (!uec) { printf("%s: uec not initial\n", __FUNCTION__); return -EINVAL; } uec_regs = uec->uec_regs; maccfg1 = in_be32(&uec_regs->maccfg1); if (mode & COMM_DIR_TX) { maccfg1 &= ~MACCFG1_ENABLE_TX; out_be32(&uec_regs->maccfg1, maccfg1); uec->mac_tx_enabled = 0; } if (mode & COMM_DIR_RX) { maccfg1 &= ~MACCFG1_ENABLE_RX; out_be32(&uec_regs->maccfg1, maccfg1); uec->mac_rx_enabled = 0; } return 0;}static int uec_graceful_stop_tx(uec_private_t *uec){ ucc_fast_t *uf_regs; u32 cecr_subblock; u32 ucce; if (!uec || !uec->uccf) { printf("%s: No handle passed.\n", __FUNCTION__); return -EINVAL; } uf_regs = uec->uccf->uf_regs; /* Clear the grace stop event */ out_be32(&uf_regs->ucce, UCCE_GRA); /* Issue host command */ cecr_subblock = ucc_fast_get_qe_cr_subblock(uec->uec_info->uf_info.ucc_num); qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, (u8)QE_CR_PROTOCOL_ETHERNET, 0); /* Wait for command to complete */ do { ucce = in_be32(&uf_regs->ucce); } while (! (ucce & UCCE_GRA)); uec->grace_stopped_tx = 1; return 0;}static int uec_graceful_stop_rx(uec_private_t *uec){ u32 cecr_subblock; u8 ack; if (!uec) { printf("%s: No handle passed.\n", __FUNCTION__); return -EINVAL; } if (!uec->p_rx_glbl_pram) { printf("%s: No init rx global parameter\n", __FUNCTION__); return -EINVAL; } /* Clear acknowledge bit */ ack = uec->p_rx_glbl_pram->rxgstpack; ack &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; uec->p_rx_glbl_pram->rxgstpack = ack; /* Keep issuing cmd and checking ack bit until it is asserted */ do { /* Issue host command */ cecr_subblock = ucc_fast_get_qe_cr_subblock(uec->uec_info->uf_info.ucc_num); qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, (u8)QE_CR_PROTOCOL_ETHERNET, 0); ack = uec->p_rx_glbl_pram->rxgstpack; } while (! (ack & GRACEFUL_STOP_ACKNOWLEDGE_RX )); uec->grace_stopped_rx = 1; return 0;}static int uec_restart_tx(uec_private_t *uec){ u32 cecr_subblock; if (!uec || !uec->uec_info) { printf("%s: No handle passed.\n", __FUNCTION__); return -EINVAL; } cecr_subblock = ucc_fast_get_qe_cr_subblock(uec->uec_info->uf_info.ucc_num); qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8)QE_CR_PROTOCOL_ETHERNET, 0); uec->grace_stopped_tx = 0; return 0;}static int uec_restart_rx(uec_private_t *uec){ u32 cecr_subblock; if (!uec || !uec->uec_info) { printf("%s: No handle passed.\n", __FUNCTION__); return -EINVAL; } cecr_subblock = ucc_fast_get_qe_cr_subblock(uec->uec_info->uf_info.ucc_num); qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8)QE_CR_PROTOCOL_ETHERNET, 0); uec->grace_stopped_rx = 0; return 0;}static int uec_open(uec_private_t *uec, comm_dir_e mode){ ucc_fast_private_t *uccf; if (!uec || !uec->uccf) { printf("%s: No handle passed.\n", __FUNCTION__); return -EINVAL; } uccf = uec->uccf; /* check if the UCC number is in range. */ if (uec->uec_info->uf_info.ucc_num >= UCC_MAX_NUM) { printf("%s: ucc_num out of range.\n", __FUNCTION__); return -EINVAL; } /* Enable MAC */ uec_mac_enable(uec, mode); /* Enable UCC fast */ ucc_fast_enable(uccf, mode); /* RISC microcode start */ if ((mode & COMM_DIR_TX) && uec->grace_stopped_tx) { uec_restart_tx(uec); } if ((mode & COMM_DIR_RX) && uec->grace_stopped_rx) { uec_restart_rx(uec); } return 0;}static int uec_stop(uec_private_t *uec, comm_dir_e mode){ ucc_fast_private_t *uccf; if (!uec || !uec->uccf) { printf("%s: No handle passed.\n", __FUNCTION__); return -EINVAL; } uccf = uec->uccf; /* check if the UCC number is in range. */ if (uec->uec_info->uf_info.ucc_num >= UCC_MAX_NUM) { printf("%s: ucc_num out of range.\n", __FUNCTION__); return -EINVAL; } /* Stop any transmissions */ if ((mode & COMM_DIR_TX) && !uec->grace_stopped_tx) { uec_graceful_stop_tx(uec); } /* Stop any receptions */ if ((mode & COMM_DIR_RX) && !uec->grace_stopped_rx) { uec_graceful_stop_rx(uec); } /* Disable the UCC fast */ ucc_fast_disable(uec->uccf, mode); /* Disable the MAC */ uec_mac_disable(uec, mode); return 0;}static int uec_set_mac_duplex(uec_private_t *uec, int duplex){ uec_t *uec_regs; u32 maccfg2; if (!uec) { printf("%s: uec not initial\n", __FUNCTION__); return -EINVAL; } uec_regs = uec->uec_regs; if (duplex == DUPLEX_HALF) { maccfg2 = in_be32(&uec_regs->maccfg2); maccfg2 &= ~MACCFG2_FDX; out_be32(&uec_regs->maccfg2, maccfg2); } if (duplex == DUPLEX_FULL) { maccfg2 = in_be32(&uec_regs->maccfg2); maccfg2 |= MACCFG2_FDX; out_be32(&uec_regs->maccfg2, maccfg2); } return 0;}static int uec_set_mac_if_mode(uec_private_t *uec, enet_interface_e if_mode){ enet_interface_e enet_if_mode; uec_info_t *uec_info; uec_t *uec_regs; u32 upsmr; u32 maccfg2; if (!uec) { printf("%s: uec not initial\n", __FUNCTION__); return -EINVAL; } uec_info = uec->uec_info; uec_regs = uec->uec_regs; enet_if_mode = if_mode; maccfg2 = in_be32(&uec_regs->maccfg2); maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; upsmr = in_be32(&uec->uccf->uf_regs->upsmr); upsmr &= ~(UPSMR_RPM | UPSMR_TBIM | UPSMR_R10M | UPSMR_RMM); switch (enet_if_mode) { case ENET_100_MII: case ENET_10_MII: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; break; case ENET_1000_GMII: maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; break; case ENET_1000_TBI: maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; upsmr |= UPSMR_TBIM; break; case ENET_1000_RTBI: maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; upsmr |= (UPSMR_RPM | UPSMR_TBIM); break; case ENET_1000_RGMII: maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; upsmr |= UPSMR_RPM; break; case ENET_100_RGMII: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; upsmr |= UPSMR_RPM; break; case ENET_10_RGMII: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; upsmr |= (UPSMR_RPM | UPSMR_R10M); break; case ENET_100_RMII: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; upsmr |= UPSMR_RMM; break; case ENET_10_RMII: maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; upsmr |= (UPSMR_R10M | UPSMR_RMM); break; default: return -EINVAL; break; } out_be32(&uec_regs->maccfg2, maccfg2); out_be32(&uec->uccf->uf_regs->upsmr, upsmr); return 0;}static int init_mii_management_configuration(uec_mii_t *uec_mii_regs){ uint timeout = 0x1000; u32 miimcfg = 0; miimcfg = in_be32(&uec_mii_regs->miimcfg); miimcfg |= MIIMCFG_MNGMNT_CLC_DIV_INIT_VALUE; out_be32(&uec_mii_regs->miimcfg, miimcfg); /* Wait until the bus is free */ while ((in_be32(&uec_mii_regs->miimcfg) & MIIMIND_BUSY) && timeout--); if (timeout <= 0) { printf("%s: The MII Bus is stuck!", __FUNCTION__); return -ETIMEDOUT; } return 0;}static int init_phy(struct eth_device *dev){ uec_private_t *uec; uec_mii_t *umii_regs; struct uec_mii_info *mii_info; struct phy_info *curphy; int err; uec = (uec_private_t *)dev->priv; umii_regs = uec->uec_mii_regs; uec->oldlink = 0; uec->oldspeed = 0; uec->oldduplex = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -