blob: 818ed3d34f6413b158a8cccd811040797570f6b0 [file] [log] [blame]
wdenkf2140d52004-07-01 16:30:44 +00001/***********************************************************************
2 *
3 * Copyright (c) 2004 Cucy Systems (http://www.cucy.com)
4 * Curt Brune <curt@cucy.com>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 * Description: Ethernet interface for Samsung S3C4510B SoC
25 */
26
27#include <common.h>
wdenkf2140d52004-07-01 16:30:44 +000028#include <command.h>
29#include <net.h>
30#include <asm/hardware.h>
31#include "s3c4510b_eth.h"
32
33static TX_FrameDescriptor txFDbase[ETH_MaxTxFrames];
34static MACFrame txFrameBase[ETH_MaxTxFrames];
35static RX_FrameDescriptor rxFDbase[PKTBUFSRX];
36static ETH m_eth;
37
38static s32 TxFDinit( ETH *eth) {
39
40 s32 i;
41 MACFrame *txFrmBase;
42
43 /* disable cache for access to the TX buffers */
44 txFrmBase = (MACFrame *)( (u32)txFrameBase | CACHE_DISABLE_MASK);
45
46 /* store start of Tx descriptors and set current */
47 eth->m_curTX_FD = (TX_FrameDescriptor *) ((u32)txFDbase | CACHE_DISABLE_MASK);
48 eth->m_baseTX_FD = eth->m_curTX_FD;
49
50 for ( i = 0; i < ETH_MaxTxFrames; i++) {
51 eth->m_baseTX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)&txFrmBase[i];
52 eth->m_baseTX_FD[i].m_frameDataPtr.bf.owner = 0x0; /* CPU owner */
53 eth->m_baseTX_FD[i].m_opt.ui = 0x0;
54 eth->m_baseTX_FD[i].m_status.ui = 0x0;
55 eth->m_baseTX_FD[i].m_nextFD = &eth->m_baseTX_FD[i+1];
56 }
57
58 /* make the list circular */
59 eth->m_baseTX_FD[i-1].m_nextFD = &eth->m_baseTX_FD[0];
60
61 PUT_REG( REG_BDMATXPTR, (u32)eth->m_curTX_FD);
62
63 return 0;
64}
65
66static s32 RxFDinit( ETH *eth) {
67
68 s32 i;
69 /* MACFrame *rxFrmBase; */
70
71 /* disable cache for access to the RX buffers */
72 /* rxFrmBase = (MACFrame *)( (u32)rxFrameBase | CACHE_DISABLE_MASK); */
73
74 /* store start of Rx descriptors and set current */
75 eth->m_curRX_FD = (RX_FrameDescriptor *)((u32)rxFDbase | CACHE_DISABLE_MASK);
76 eth->m_baseRX_FD = eth->m_curRX_FD;
77 for ( i = 0; i < PKTBUFSRX; i++) {
78 eth->m_baseRX_FD[i].m_frameDataPtr.bf.dataPtr = (u32)NetRxPackets[i] | CACHE_DISABLE_MASK;
79 eth->m_baseRX_FD[i].m_frameDataPtr.bf.owner = 0x1; /* BDMA owner */
80 eth->m_baseRX_FD[i].m_reserved = 0x0;
81 eth->m_baseRX_FD[i].m_status.ui = 0x0;
82 eth->m_baseRX_FD[i].m_nextFD = &eth->m_baseRX_FD[i+1];
83 }
84
85 /* make the list circular */
86 eth->m_baseRX_FD[i-1].m_nextFD = &eth->m_baseRX_FD[0];
87
88 PUT_REG( REG_BDMARXPTR, (u32)eth->m_curRX_FD);
89
90 return 0;
91}
92
93/*
94 * Public u-boot interface functions below
95 */
96
97int eth_init(bd_t *bis)
98{
99
100 ETH *eth = &m_eth;
101
102 /* store our MAC address */
Mike Frysingerb2039652009-02-11 19:01:26 -0500103 eth_getenv_enetaddr("ethaddr", eth->m_mac);
wdenkf2140d52004-07-01 16:30:44 +0000104
105 /* setup DBMA and MAC */
106 PUT_REG( REG_BDMARXCON, ETH_BRxRS); /* reset BDMA RX machine */
107 PUT_REG( REG_BDMATXCON, ETH_BTxRS); /* reset BDMA TX machine */
108 PUT_REG( REG_MACCON , ETH_SwReset); /* reset MAC machine */
109 PUT_REG( REG_BDMARXLSZ, sizeof(MACFrame));
110 PUT_REG( REG_MACCON , 0); /* reset MAC machine */
111
112 /* init frame descriptors */
113 TxFDinit( eth);
114 RxFDinit( eth);
115
116 /* init the CAM with our MAC address */
117 PUT_REG( REG_CAM_BASE, (eth->m_mac[0] << 24) |
118 (eth->m_mac[1] << 16) |
119 (eth->m_mac[2] << 8) |
120 (eth->m_mac[3]));
121 PUT_REG( REG_CAM_BASE + 0x4, (eth->m_mac[4] << 24) |
122 (eth->m_mac[5] << 16));
123
124 /* enable CAM address 1 -- the MAC we just loaded */
125 PUT_REG( REG_CAMEN, 0x1);
126
127 PUT_REG( REG_CAMCON,
128 ETH_BroadAcc | /* accept broadcast packetes */
129 ETH_CompEn); /* enable compare mode (check against the CAM) */
130
131 /* configure the BDMA Transmitter control */
132 PUT_REG( REG_BDMATXCON,
133 ETH_BTxBRST | /* BDMA Tx burst size 16 words */
134 ETH_BTxMSL110 | /* BDMA Tx wait to fill 6/8 of the BDMA */
135 ETH_BTxSTSKO | /* BDMA Tx interrupt(Stop) on non-owner TX FD */
136 ETH_BTxEn); /* BDMA Tx Enable */
137
138 /* configure the MAC Transmitter control */
139 PUT_REG( REG_MACTXCON,
140 ETH_EnComp | /* interrupt when the MAC transmits or discards packet */
141 ETH_TxEn); /* MAC transmit enable */
142
143 /* configure the BDMA Receiver control */
144 PUT_REG( REG_BDMARXCON,
145 ETH_BRxBRST | /* BDMA Rx Burst Size 16 words */
146 ETH_BRxSTSKO | /* BDMA Rx interrupt(Stop) on non-owner RX FD */
147 ETH_BRxMAINC | /* BDMA Rx Memory Address increment */
148 ETH_BRxDIE | /* BDMA Rx Every Received Frame Interrupt Enable */
149 ETH_BRxNLIE | /* BDMA Rx NULL List Interrupt Enable */
150 ETH_BRxNOIE | /* BDMA Rx Not Owner Interrupt Enable */
151 ETH_BRxLittle | /* BDMA Rx Little endian */
152 ETH_BRxEn); /* BDMA Rx Enable */
153
154 /* configure the MAC Receiver control */
155 PUT_REG( REG_MACRXCON,
156 ETH_RxEn); /* MAC ETH_RxEn */
157
158 return 0;
159
160}
161
162/* Send a packet */
163s32 eth_send(volatile void *packet, s32 length)
164{
165
166 u32 i;
167 ETH *eth = &m_eth;
168
169 if ( eth->m_curTX_FD->m_frameDataPtr.bf.owner) {
wdenkce4832c2004-10-17 21:12:06 +0000170 printf("eth_send(): TX Frame. CPU not owner.\n");
wdenkf2140d52004-07-01 16:30:44 +0000171 return -1;
172 }
173
174 /* copy user data into frame data pointer */
Wolfgang Denka923f112007-11-18 17:11:09 +0100175 memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)),
wdenkf2140d52004-07-01 16:30:44 +0000176 (void *)packet,
177 length);
178
179 /* Set TX Frame flags */
180 eth->m_curTX_FD->m_opt.bf.widgetAlign = 0;
181 eth->m_curTX_FD->m_opt.bf.frameDataDir = 1;
182 eth->m_curTX_FD->m_opt.bf.littleEndian = 1;
183 eth->m_curTX_FD->m_opt.bf.macTxIrqEnbl = 1;
184 eth->m_curTX_FD->m_opt.bf.no_crc = 0;
185 eth->m_curTX_FD->m_opt.bf.no_padding = 0;
186
187 /* Set TX Frame length */
188 eth->m_curTX_FD->m_status.bf.len = length;
189
190 /* Change ownership to BDMA */
191 eth->m_curTX_FD->m_frameDataPtr.bf.owner = 1;
192
193 /* Enable MAC and BDMA Tx control register */
194 SET_REG( REG_BDMATXCON, ETH_BTxEn);
195 SET_REG( REG_MACTXCON, ETH_TxEn);
196
197 /* poll on TX completion status */
198 while ( !eth->m_curTX_FD->m_status.bf.complete) {
199 /* sleep */
200 for ( i = 0; i < 0x10000; i ++);
201 }
202
203 /* Change the Tx frame descriptor for next use */
204 eth->m_curTX_FD = eth->m_curTX_FD->m_nextFD;
205
206 return 0;
207}
208
209/* Check for received packets */
210s32 eth_rx (void)
211{
212 s32 nLen = 0;
213 ETH *eth = &m_eth;
214
215 /* check if packet ready */
216 if ( (GET_REG( REG_BDMASTAT)) & ETH_S_BRxRDF) {
217 /* process all waiting packets */
218 while ( !eth->m_curRX_FD->m_frameDataPtr.bf.owner) {
219 nLen = eth->m_curRX_FD->m_status.bf.len;
220 /* call back u-boot -- may call eth_send() */
221 NetReceive ((u8 *)eth->m_curRX_FD->m_frameDataPtr.ui, nLen);
222 /* set owner back to CPU */
223 eth->m_curRX_FD->m_frameDataPtr.bf.owner = 1;
224 /* clear status */
225 eth->m_curRX_FD->m_status.ui = 0x0;
226 /* advance to next descriptor */
227 eth->m_curRX_FD = eth->m_curRX_FD->m_nextFD;
228 /* clear received frame bit */
229 PUT_REG( REG_BDMASTAT, ETH_S_BRxRDF);
230 }
231 }
232
233 return nLen;
234}
235
236/* Halt ethernet engine */
237void eth_halt(void)
238{
239 /* disable MAC */
240 PUT_REG( REG_MACCON, ETH_HaltReg);
241}