summaryrefslogtreecommitdiff
path: root/drivers/s3c4510b_eth.c
diff options
context:
space:
mode:
authorwdenk <wdenk>2004-07-01 16:30:44 +0000
committerwdenk <wdenk>2004-07-01 16:30:44 +0000
commit39539887ea7dc298c98ac1fddd38551dfa335120 (patch)
tree31e3bc0bd93cead0c977b8fd26ede7d06f70e0a1 /drivers/s3c4510b_eth.c
parente94d2cd9d1dc0f58b18e7c31fc9345129b1a44fb (diff)
* Code cleanup (ARM mostly)
* Patch by Curt Brune, 17 May 2004: - Add support for Samsung S3C4510B CPU (ARM7tdmi based SoC) - Add support for ESPD-Inc. EVB4510 Board
Diffstat (limited to 'drivers/s3c4510b_eth.c')
-rw-r--r--drivers/s3c4510b_eth.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/drivers/s3c4510b_eth.c b/drivers/s3c4510b_eth.c
new file mode 100644
index 00000000000..694703c423b
--- /dev/null
+++ b/drivers/s3c4510b_eth.c
@@ -0,0 +1,246 @@
+/***********************************************************************
+ *
+ * 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>
+
+#ifdef CONFIG_DRIVER_S3C4510_ETH
+
+#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 = &eth->m_baseTX_FD[i+1];
+ }
+
+ /* make the list circular */
+ eth->m_baseTX_FD[i-1].m_nextFD = &eth->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 = &eth->m_baseRX_FD[i+1];
+ }
+
+ /* make the list circular */
+ eth->m_baseRX_FD[i-1].m_nextFD = &eth->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->m_mac = bis->bi_enetaddr;
+
+ /* 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(__FUNCTION__"(): TX Frame. CPU not owner.\n");
+ return -1;
+ }
+
+ /* copy user data into frame data pointer */
+ memcpy((void *)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);
+}
+
+#endif