tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.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 #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                  = &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
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                  = &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
97 int eth_init(bd_t *bis)
98 {
99
100         ETH *eth = &m_eth;
101
102         /* store our MAC address */
103         eth_getenv_enetaddr("ethaddr", eth->m_mac);
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) {
170                 printf("eth_send(): TX Frame.  CPU not owner.\n");
171                 return -1;
172         }
173
174         /* copy user data into frame data pointer */
175         memcpy((void *)((u32)(eth->m_curTX_FD->m_frameDataPtr.bf.dataPtr)),
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 }