1 /***********************************************************************
3 * Copyright (c) 2004 Cucy Systems (http://www.cucy.com)
4 * Curt Brune <curt@cucy.com>
6 * See file CREDITS for list of people who contributed to this
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.
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.
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,
24 * Description: Ethernet interface for Samsung S3C4510B SoC
29 #ifdef CONFIG_DRIVER_S3C4510_ETH
33 #include <asm/hardware.h>
34 #include "s3c4510b_eth.h"
36 static TX_FrameDescriptor txFDbase
[ETH_MaxTxFrames
];
37 static MACFrame txFrameBase
[ETH_MaxTxFrames
];
38 static RX_FrameDescriptor rxFDbase
[PKTBUFSRX
];
41 static s32
TxFDinit( ETH
*eth
) {
46 /* disable cache for access to the TX buffers */
47 txFrmBase
= (MACFrame
*)( (u32
)txFrameBase
| CACHE_DISABLE_MASK
);
49 /* store start of Tx descriptors and set current */
50 eth
->m_curTX_FD
= (TX_FrameDescriptor
*) ((u32
)txFDbase
| CACHE_DISABLE_MASK
);
51 eth
->m_baseTX_FD
= eth
->m_curTX_FD
;
53 for ( i
= 0; i
< ETH_MaxTxFrames
; i
++) {
54 eth
->m_baseTX_FD
[i
].m_frameDataPtr
.bf
.dataPtr
= (u32
)&txFrmBase
[i
];
55 eth
->m_baseTX_FD
[i
].m_frameDataPtr
.bf
.owner
= 0x0; /* CPU owner */
56 eth
->m_baseTX_FD
[i
].m_opt
.ui
= 0x0;
57 eth
->m_baseTX_FD
[i
].m_status
.ui
= 0x0;
58 eth
->m_baseTX_FD
[i
].m_nextFD
= ð
->m_baseTX_FD
[i
+1];
61 /* make the list circular */
62 eth
->m_baseTX_FD
[i
-1].m_nextFD
= ð
->m_baseTX_FD
[0];
64 PUT_REG( REG_BDMATXPTR
, (u32
)eth
->m_curTX_FD
);
69 static s32
RxFDinit( ETH
*eth
) {
72 /* MACFrame *rxFrmBase; */
74 /* disable cache for access to the RX buffers */
75 /* rxFrmBase = (MACFrame *)( (u32)rxFrameBase | CACHE_DISABLE_MASK); */
77 /* store start of Rx descriptors and set current */
78 eth
->m_curRX_FD
= (RX_FrameDescriptor
*)((u32
)rxFDbase
| CACHE_DISABLE_MASK
);
79 eth
->m_baseRX_FD
= eth
->m_curRX_FD
;
80 for ( i
= 0; i
< PKTBUFSRX
; i
++) {
81 eth
->m_baseRX_FD
[i
].m_frameDataPtr
.bf
.dataPtr
= (u32
)NetRxPackets
[i
] | CACHE_DISABLE_MASK
;
82 eth
->m_baseRX_FD
[i
].m_frameDataPtr
.bf
.owner
= 0x1; /* BDMA owner */
83 eth
->m_baseRX_FD
[i
].m_reserved
= 0x0;
84 eth
->m_baseRX_FD
[i
].m_status
.ui
= 0x0;
85 eth
->m_baseRX_FD
[i
].m_nextFD
= ð
->m_baseRX_FD
[i
+1];
88 /* make the list circular */
89 eth
->m_baseRX_FD
[i
-1].m_nextFD
= ð
->m_baseRX_FD
[0];
91 PUT_REG( REG_BDMARXPTR
, (u32
)eth
->m_curRX_FD
);
97 * Public u-boot interface functions below
100 int eth_init(bd_t
*bis
)
105 /* store our MAC address */
106 eth
->m_mac
= bis
->bi_enetaddr
;
108 /* setup DBMA and MAC */
109 PUT_REG( REG_BDMARXCON
, ETH_BRxRS
); /* reset BDMA RX machine */
110 PUT_REG( REG_BDMATXCON
, ETH_BTxRS
); /* reset BDMA TX machine */
111 PUT_REG( REG_MACCON
, ETH_SwReset
); /* reset MAC machine */
112 PUT_REG( REG_BDMARXLSZ
, sizeof(MACFrame
));
113 PUT_REG( REG_MACCON
, 0); /* reset MAC machine */
115 /* init frame descriptors */
119 /* init the CAM with our MAC address */
120 PUT_REG( REG_CAM_BASE
, (eth
->m_mac
[0] << 24) |
121 (eth
->m_mac
[1] << 16) |
122 (eth
->m_mac
[2] << 8) |
124 PUT_REG( REG_CAM_BASE
+ 0x4, (eth
->m_mac
[4] << 24) |
125 (eth
->m_mac
[5] << 16));
127 /* enable CAM address 1 -- the MAC we just loaded */
128 PUT_REG( REG_CAMEN
, 0x1);
131 ETH_BroadAcc
| /* accept broadcast packetes */
132 ETH_CompEn
); /* enable compare mode (check against the CAM) */
134 /* configure the BDMA Transmitter control */
135 PUT_REG( REG_BDMATXCON
,
136 ETH_BTxBRST
| /* BDMA Tx burst size 16 words */
137 ETH_BTxMSL110
| /* BDMA Tx wait to fill 6/8 of the BDMA */
138 ETH_BTxSTSKO
| /* BDMA Tx interrupt(Stop) on non-owner TX FD */
139 ETH_BTxEn
); /* BDMA Tx Enable */
141 /* configure the MAC Transmitter control */
142 PUT_REG( REG_MACTXCON
,
143 ETH_EnComp
| /* interrupt when the MAC transmits or discards packet */
144 ETH_TxEn
); /* MAC transmit enable */
146 /* configure the BDMA Receiver control */
147 PUT_REG( REG_BDMARXCON
,
148 ETH_BRxBRST
| /* BDMA Rx Burst Size 16 words */
149 ETH_BRxSTSKO
| /* BDMA Rx interrupt(Stop) on non-owner RX FD */
150 ETH_BRxMAINC
| /* BDMA Rx Memory Address increment */
151 ETH_BRxDIE
| /* BDMA Rx Every Received Frame Interrupt Enable */
152 ETH_BRxNLIE
| /* BDMA Rx NULL List Interrupt Enable */
153 ETH_BRxNOIE
| /* BDMA Rx Not Owner Interrupt Enable */
154 ETH_BRxLittle
| /* BDMA Rx Little endian */
155 ETH_BRxEn
); /* BDMA Rx Enable */
157 /* configure the MAC Receiver control */
158 PUT_REG( REG_MACRXCON
,
159 ETH_RxEn
); /* MAC ETH_RxEn */
166 s32
eth_send(volatile void *packet
, s32 length
)
172 if ( eth
->m_curTX_FD
->m_frameDataPtr
.bf
.owner
) {
173 printf("eth_send(): TX Frame. CPU not owner.\n");
177 /* copy user data into frame data pointer */
178 memcpy((void *)(eth
->m_curTX_FD
->m_frameDataPtr
.bf
.dataPtr
),
182 /* Set TX Frame flags */
183 eth
->m_curTX_FD
->m_opt
.bf
.widgetAlign
= 0;
184 eth
->m_curTX_FD
->m_opt
.bf
.frameDataDir
= 1;
185 eth
->m_curTX_FD
->m_opt
.bf
.littleEndian
= 1;
186 eth
->m_curTX_FD
->m_opt
.bf
.macTxIrqEnbl
= 1;
187 eth
->m_curTX_FD
->m_opt
.bf
.no_crc
= 0;
188 eth
->m_curTX_FD
->m_opt
.bf
.no_padding
= 0;
190 /* Set TX Frame length */
191 eth
->m_curTX_FD
->m_status
.bf
.len
= length
;
193 /* Change ownership to BDMA */
194 eth
->m_curTX_FD
->m_frameDataPtr
.bf
.owner
= 1;
196 /* Enable MAC and BDMA Tx control register */
197 SET_REG( REG_BDMATXCON
, ETH_BTxEn
);
198 SET_REG( REG_MACTXCON
, ETH_TxEn
);
200 /* poll on TX completion status */
201 while ( !eth
->m_curTX_FD
->m_status
.bf
.complete
) {
203 for ( i
= 0; i
< 0x10000; i
++);
206 /* Change the Tx frame descriptor for next use */
207 eth
->m_curTX_FD
= eth
->m_curTX_FD
->m_nextFD
;
212 /* Check for received packets */
218 /* check if packet ready */
219 if ( (GET_REG( REG_BDMASTAT
)) & ETH_S_BRxRDF
) {
220 /* process all waiting packets */
221 while ( !eth
->m_curRX_FD
->m_frameDataPtr
.bf
.owner
) {
222 nLen
= eth
->m_curRX_FD
->m_status
.bf
.len
;
223 /* call back u-boot -- may call eth_send() */
224 NetReceive ((u8
*)eth
->m_curRX_FD
->m_frameDataPtr
.ui
, nLen
);
225 /* set owner back to CPU */
226 eth
->m_curRX_FD
->m_frameDataPtr
.bf
.owner
= 1;
228 eth
->m_curRX_FD
->m_status
.ui
= 0x0;
229 /* advance to next descriptor */
230 eth
->m_curRX_FD
= eth
->m_curRX_FD
->m_nextFD
;
231 /* clear received frame bit */
232 PUT_REG( REG_BDMASTAT
, ETH_S_BRxRDF
);
239 /* Halt ethernet engine */
243 PUT_REG( REG_MACCON
, ETH_HaltReg
);