|
|
|
/***********************************************************************
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Cucy Systems (http://www.cucy.com)
|
|
|
|
* Curt Brune <curt@cucy.com>
|
|
|
|
*
|
|
|
|
* See file CREDITS for list of people who contributed to this
|
|
|
|
* project.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* Description: Ethernet interface for Samsung S3C4510B SoC
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <command.h>
|
|
|
|
#include <net.h>
|
|
|
|
#include <asm/hardware.h>
|
|
|
|
#include "s3c4510b_eth.h"
|
|
|
|
|
|
|
|
static TX_FrameDescriptor txFDbase[ETH_MaxTxFrames];
|
|
|
|
static MACFrame txFrameBase[ETH_MaxTxFrames];
|
|
|
|
static RX_FrameDescriptor rxFDbase[PKTBUFSRX];
|
|
|
|
static ETH m_eth;
|
|
|
|
|
|
|
|
static s32 TxFDinit( ETH *eth) {
|
|
|
|
|
|
|
|
s32 i;
|
|
|
|
MACFrame *txFrmBase;
|
|
|
|
|
|
|
|
/* disable cache for access to the TX buffers */
|
|
|
|
txFrmBase = (MACFrame *)( (u32)txFrameBase | CACHE_DISABLE_MASK);
|
|
|
|
|
|
|
|
/* store start of Tx descriptors and set current */
|
|
|
|
eth->m_curTX_FD = (TX_FrameDescriptor *) ((u32)txFDbase | CACHE_DISABLE_MASK);
|
|
|
|
eth->m_baseTX_FD = eth->m_curTX_FD;
|
|
|
|
|
|
|
|
for ( i = 0; i < ETH_MaxTxFrames; i++) {
|
|
|
|
eth->m_baseTX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)&txFrmBase[i];
|
|
|
|
eth->m_baseTX_FD[i].m_frameDataPtr.bf.owner = 0x0; /* CPU owner */
|
|
|
|
eth->m_baseTX_FD[i].m_opt.ui = 0x0;
|
|
|
|
eth->m_baseTX_FD[i].m_status.ui = 0x0;
|
|
|
|
eth->m_baseTX_FD[i].m_nextFD = ð->m_baseTX_FD[i+1];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make the list circular */
|
|
|
|
eth->m_baseTX_FD[i-1].m_nextFD = ð->m_baseTX_FD[0];
|
|
|
|
|
|
|
|
PUT_REG( REG_BDMATXPTR, (u32)eth->m_curTX_FD);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static s32 RxFDinit( ETH *eth) {
|
|
|
|
|
|
|
|
s32 i;
|
|
|
|
/* MACFrame *rxFrmBase; */
|
|
|
|
|
|
|
|
/* disable cache for access to the RX buffers */
|
|
|
|
/* rxFrmBase = (MACFrame *)( (u32)rxFrameBase | CACHE_DISABLE_MASK); */
|
|
|
|
|
|
|
|
/* store start of Rx descriptors and set current */
|
|
|
|
eth->m_curRX_FD = (RX_FrameDescriptor *)((u32)rxFDbase | CACHE_DISABLE_MASK);
|
|
|
|
eth->m_baseRX_FD = eth->m_curRX_FD;
|
|
|
|
for ( i = 0; i < PKTBUFSRX; i++) {
|
|
|
|
eth->m_baseRX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)NetRxPackets[i] | CACHE_DISABLE_MASK;
|
|
|
|
eth->m_baseRX_FD[i].m_frameDataPtr.bf.owner = 0x1; /* BDMA owner */
|
|
|
|
eth->m_baseRX_FD[i].m_reserved = 0x0;
|
|
|
|
eth->m_baseRX_FD[i].m_status.ui = 0x0;
|
|
|
|
eth->m_baseRX_FD[i].m_nextFD = ð->m_baseRX_FD[i+1];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* make the list circular */
|
|
|
|
eth->m_baseRX_FD[i-1].m_nextFD = ð->m_baseRX_FD[0];
|
|
|
|
|
|
|
|
PUT_REG( REG_BDMARXPTR, (u32)eth->m_curRX_FD);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Public u-boot interface functions below
|
|
|
|
*/
|
|
|
|
|
|
|
|
int eth_init(bd_t *bis)
|
|
|
|
{
|
|
|
|
|
|
|
|
ETH *eth = &m_eth;
|
|
|
|
|
|
|
|
/* store our MAC address */
|
|
|
|
eth_getenv_enetaddr("ethaddr", eth->m_mac);
|
|
|
|
|
|
|
|
/* setup DBMA and MAC */
|
|
|
|
PUT_REG( REG_BDMARXCON, ETH_BRxRS); /* reset BDMA RX machine */
|
|
|
|
PUT_REG( REG_BDMATXCON, ETH_BTxRS); /* reset BDMA TX machine */
|
|
|
|
PUT_REG( REG_MACCON , ETH_SwReset); /* reset MAC machine */
|
|
|
|
PUT_REG( REG_BDMARXLSZ, sizeof(MACFrame));
|
|
|
|
PUT_REG( REG_MACCON , 0); /* reset MAC machine */
|
|
|
|
|
|
|
|
/* init frame descriptors */
|
|
|
|
TxFDinit( eth);
|
|
|
|
RxFDinit( eth);
|
|
|
|
|
|
|
|
/* init the CAM with our MAC address */
|
|
|
|
PUT_REG( REG_CAM_BASE, (eth->m_mac[0] << 24) |
|
|
|
|
(eth->m_mac[1] << 16) |
|
|
|
|
(eth->m_mac[2] << 8) |
|
|
|
|
(eth->m_mac[3]));
|
|
|
|
PUT_REG( REG_CAM_BASE + 0x4, (eth->m_mac[4] << 24) |
|
|
|
|
(eth->m_mac[5] << 16));
|
|
|
|
|
|
|
|
/* enable CAM address 1 -- the MAC we just loaded */
|
|
|
|
PUT_REG( REG_CAMEN, 0x1);
|
|
|
|
|
|
|
|
PUT_REG( REG_CAMCON,
|
|
|
|
ETH_BroadAcc | /* accept broadcast packetes */
|
|
|
|
ETH_CompEn); /* enable compare mode (check against the CAM) */
|
|
|
|
|
|
|
|
/* configure the BDMA Transmitter control */
|
|
|
|
PUT_REG( REG_BDMATXCON,
|
|
|
|
ETH_BTxBRST | /* BDMA Tx burst size 16 words */
|
|
|
|
ETH_BTxMSL110 | /* BDMA Tx wait to fill 6/8 of the BDMA */
|
|
|
|
ETH_BTxSTSKO | /* BDMA Tx interrupt(Stop) on non-owner TX FD */
|
|
|
|
ETH_BTxEn); /* BDMA Tx Enable */
|
|
|
|
|
|
|
|
/* configure the MAC Transmitter control */
|
|
|
|
PUT_REG( REG_MACTXCON,
|
|
|
|
ETH_EnComp | /* interrupt when the MAC transmits or discards packet */
|
|
|
|
ETH_TxEn); /* MAC transmit enable */
|
|
|
|
|
|
|
|
/* configure the BDMA Receiver control */
|
|
|
|
PUT_REG( REG_BDMARXCON,
|
|
|
|
ETH_BRxBRST | /* BDMA Rx Burst Size 16 words */
|
|
|
|
ETH_BRxSTSKO | /* BDMA Rx interrupt(Stop) on non-owner RX FD */
|
|
|
|
ETH_BRxMAINC | /* BDMA Rx Memory Address increment */
|
|
|
|
ETH_BRxDIE | /* BDMA Rx Every Received Frame Interrupt Enable */
|
|
|
|
ETH_BRxNLIE | /* BDMA Rx NULL List Interrupt Enable */
|
|
|
|
ETH_BRxNOIE | /* BDMA Rx Not Owner Interrupt Enable */
|
|
|
|
ETH_BRxLittle | /* BDMA Rx Little endian */
|
|
|
|
ETH_BRxEn); /* BDMA Rx Enable */
|
|
|
|
|
|
|
|
/* configure the MAC Receiver control */
|
|
|
|
PUT_REG( REG_MACRXCON,
|
|
|
|
ETH_RxEn); /* MAC ETH_RxEn */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send a packet */
|
|
|
|
s32 eth_send(volatile void *packet, s32 length)
|
|
|
|
{
|
|
|
|
|
|
|
|
u32 i;
|
|
|
|
ETH *eth = &m_eth;
|
|
|
|
|
|
|
|
if ( eth->m_curTX_FD->m_frameDataPtr.bf.owner) {
|
|
|
|
printf("eth_send(): TX Frame. CPU not owner.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy user data into frame data pointer */
|
|
|
|
memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)),
|
|
|
|
(void *)packet,
|
|
|
|
length);
|
|
|
|
|
|
|
|
/* Set TX Frame flags */
|
|
|
|
eth->m_curTX_FD->m_opt.bf.widgetAlign = 0;
|
|
|
|
eth->m_curTX_FD->m_opt.bf.frameDataDir = 1;
|
|
|
|
eth->m_curTX_FD->m_opt.bf.littleEndian = 1;
|
|
|
|
eth->m_curTX_FD->m_opt.bf.macTxIrqEnbl = 1;
|
|
|
|
eth->m_curTX_FD->m_opt.bf.no_crc = 0;
|
|
|
|
eth->m_curTX_FD->m_opt.bf.no_padding = 0;
|
|
|
|
|
|
|
|
/* Set TX Frame length */
|
|
|
|
eth->m_curTX_FD->m_status.bf.len = length;
|
|
|
|
|
|
|
|
/* Change ownership to BDMA */
|
|
|
|
eth->m_curTX_FD->m_frameDataPtr.bf.owner = 1;
|
|
|
|
|
|
|
|
/* Enable MAC and BDMA Tx control register */
|
|
|
|
SET_REG( REG_BDMATXCON, ETH_BTxEn);
|
|
|
|
SET_REG( REG_MACTXCON, ETH_TxEn);
|
|
|
|
|
|
|
|
/* poll on TX completion status */
|
|
|
|
while ( !eth->m_curTX_FD->m_status.bf.complete) {
|
|
|
|
/* sleep */
|
|
|
|
for ( i = 0; i < 0x10000; i ++);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Change the Tx frame descriptor for next use */
|
|
|
|
eth->m_curTX_FD = eth->m_curTX_FD->m_nextFD;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for received packets */
|
|
|
|
s32 eth_rx (void)
|
|
|
|
{
|
|
|
|
s32 nLen = 0;
|
|
|
|
ETH *eth = &m_eth;
|
|
|
|
|
|
|
|
/* check if packet ready */
|
|
|
|
if ( (GET_REG( REG_BDMASTAT)) & ETH_S_BRxRDF) {
|
|
|
|
/* process all waiting packets */
|
|
|
|
while ( !eth->m_curRX_FD->m_frameDataPtr.bf.owner) {
|
|
|
|
nLen = eth->m_curRX_FD->m_status.bf.len;
|
|
|
|
/* call back u-boot -- may call eth_send() */
|
|
|
|
NetReceive ((u8 *)eth->m_curRX_FD->m_frameDataPtr.ui, nLen);
|
|
|
|
/* set owner back to CPU */
|
|
|
|
eth->m_curRX_FD->m_frameDataPtr.bf.owner = 1;
|
|
|
|
/* clear status */
|
|
|
|
eth->m_curRX_FD->m_status.ui = 0x0;
|
|
|
|
/* advance to next descriptor */
|
|
|
|
eth->m_curRX_FD = eth->m_curRX_FD->m_nextFD;
|
|
|
|
/* clear received frame bit */
|
|
|
|
PUT_REG( REG_BDMASTAT, ETH_S_BRxRDF);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Halt ethernet engine */
|
|
|
|
void eth_halt(void)
|
|
|
|
{
|
|
|
|
/* disable MAC */
|
|
|
|
PUT_REG( REG_MACCON, ETH_HaltReg);
|
|
|
|
}
|