Merge branch 'master' of git://www.denx.de/git/u-boot-arm
[platform/kernel/u-boot.git] / drivers / net / s3c4510b_eth.c
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>
28
29 #ifdef CONFIG_DRIVER_S3C4510_ETH
30
31 #include <command.h>
32 #include <net.h>
33 #include <asm/hardware.h>
34 #include "s3c4510b_eth.h"
35
36 static TX_FrameDescriptor    txFDbase[ETH_MaxTxFrames];
37 static MACFrame           txFrameBase[ETH_MaxTxFrames];
38 static RX_FrameDescriptor    rxFDbase[PKTBUFSRX];
39 static ETH                      m_eth;
40
41 static s32 TxFDinit( ETH *eth) {
42
43         s32 i;
44         MACFrame *txFrmBase;
45
46         /* disable cache for access to the TX buffers */
47         txFrmBase = (MACFrame *)( (u32)txFrameBase | CACHE_DISABLE_MASK);
48
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;
52
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                  = &eth->m_baseTX_FD[i+1];
59         }
60
61         /* make the list circular */
62         eth->m_baseTX_FD[i-1].m_nextFD          = &eth->m_baseTX_FD[0];
63
64         PUT_REG( REG_BDMATXPTR, (u32)eth->m_curTX_FD);
65
66         return 0;
67 }
68
69 static s32 RxFDinit( ETH *eth) {
70
71         s32 i;
72         /*  MACFrame *rxFrmBase; */
73
74         /* disable cache for access to the RX buffers */
75         /*  rxFrmBase = (MACFrame *)( (u32)rxFrameBase | CACHE_DISABLE_MASK); */
76
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                  = &eth->m_baseRX_FD[i+1];
86         }
87
88         /* make the list circular */
89         eth->m_baseRX_FD[i-1].m_nextFD                  = &eth->m_baseRX_FD[0];
90
91         PUT_REG( REG_BDMARXPTR, (u32)eth->m_curRX_FD);
92
93         return 0;
94 }
95
96 /*
97  * Public u-boot interface functions below
98  */
99
100 int eth_init(bd_t *bis)
101 {
102
103         ETH *eth = &m_eth;
104
105         /* store our MAC address */
106         eth->m_mac = bis->bi_enetaddr;
107
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 */
114
115         /* init frame descriptors */
116         TxFDinit( eth);
117         RxFDinit( eth);
118
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) |
123                 (eth->m_mac[3]));
124         PUT_REG( REG_CAM_BASE + 0x4, (eth->m_mac[4] << 24) |
125                 (eth->m_mac[5] << 16));
126
127         /* enable CAM address 1 -- the MAC we just loaded */
128         PUT_REG( REG_CAMEN, 0x1);
129
130         PUT_REG( REG_CAMCON,
131                 ETH_BroadAcc |  /* accept broadcast packetes */
132                 ETH_CompEn); /* enable compare mode (check against the CAM) */
133
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  */
140
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 */
145
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 */
156
157         /* configure the MAC Receiver control */
158         PUT_REG( REG_MACRXCON,
159                 ETH_RxEn);      /* MAC ETH_RxEn */
160
161         return 0;
162
163 }
164
165 /* Send a packet        */
166 s32 eth_send(volatile void *packet, s32 length)
167 {
168
169         u32 i;
170         ETH *eth = &m_eth;
171
172         if ( eth->m_curTX_FD->m_frameDataPtr.bf.owner) {
173                 printf("eth_send(): TX Frame.  CPU not owner.\n");
174                 return -1;
175         }
176
177         /* copy user data into frame data pointer */
178         memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)),
179                (void *)packet,
180                length);
181
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;
189
190         /* Set TX Frame length */
191         eth->m_curTX_FD->m_status.bf.len       = length;
192
193         /* Change ownership to BDMA */
194         eth->m_curTX_FD->m_frameDataPtr.bf.owner = 1;
195
196         /* Enable MAC and BDMA Tx control register */
197         SET_REG( REG_BDMATXCON, ETH_BTxEn);
198         SET_REG( REG_MACTXCON,  ETH_TxEn);
199
200         /* poll on TX completion status */
201         while ( !eth->m_curTX_FD->m_status.bf.complete) {
202                 /* sleep  */
203                 for ( i = 0; i < 0x10000; i ++);
204         }
205
206         /* Change the Tx frame descriptor for next use */
207         eth->m_curTX_FD = eth->m_curTX_FD->m_nextFD;
208
209         return 0;
210 }
211
212 /* Check for received packets   */
213 s32 eth_rx (void)
214 {
215         s32 nLen = 0;
216         ETH *eth = &m_eth;
217
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;
227                         /* clear status */
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);
233                 }
234         }
235
236         return nLen;
237 }
238
239 /* Halt ethernet engine */
240 void eth_halt(void)
241 {
242         /* disable MAC */
243         PUT_REG( REG_MACCON, ETH_HaltReg);
244 }
245
246 #endif