]>
Commit | Line | Data |
---|---|---|
39539887 WD |
1 | /*********************************************************************** |
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> | |
39539887 WD |
28 | #include <command.h> |
29 | #include <net.h> | |
30 | #include <asm/hardware.h> | |
31 | #include "s3c4510b_eth.h" | |
32 | ||
33 | static TX_FrameDescriptor txFDbase[ETH_MaxTxFrames]; | |
34 | static MACFrame txFrameBase[ETH_MaxTxFrames]; | |
35 | static RX_FrameDescriptor rxFDbase[PKTBUFSRX]; | |
36 | static ETH m_eth; | |
37 | ||
38 | static 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 = ð->m_baseTX_FD[i+1]; | |
56 | } | |
57 | ||
58 | /* make the list circular */ | |
59 | eth->m_baseTX_FD[i-1].m_nextFD = ð->m_baseTX_FD[0]; | |
60 | ||
61 | PUT_REG( REG_BDMATXPTR, (u32)eth->m_curTX_FD); | |
62 | ||
63 | return 0; | |
64 | } | |
65 | ||
66 | static 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 = ð->m_baseRX_FD[i+1]; | |
83 | } | |
84 | ||
85 | /* make the list circular */ | |
86 | eth->m_baseRX_FD[i-1].m_nextFD = ð->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 | ||
97 | int eth_init(bd_t *bis) | |
98 | { | |
99 | ||
100 | ETH *eth = &m_eth; | |
101 | ||
102 | /* store our MAC address */ | |
d3f87148 | 103 | eth_getenv_enetaddr("ethaddr", eth->m_mac); |
39539887 WD |
104 | |
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 */ | |
163 | s32 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) { | |
e86e5a07 | 170 | printf("eth_send(): TX Frame. CPU not owner.\n"); |
39539887 WD |
171 | return -1; |
172 | } | |
173 | ||
174 | /* copy user data into frame data pointer */ | |
8412d814 | 175 | memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)), |
39539887 WD |
176 | (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 */ | |
210 | s32 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 */ | |
237 | void eth_halt(void) | |
238 | { | |
239 | /* disable MAC */ | |
240 | PUT_REG( REG_MACCON, ETH_HaltReg); | |
241 | } |