blob: 4a5731e6ae022e5d018933098337aac966e50aba [file] [log] [blame]
wdenk42d1f032003-10-15 23:53:47 +00001/*
2 * tsec.c
3 * Motorola Three Speed Ethernet Controller driver
4 *
5 * This software may be used and distributed according to the
6 * terms of the GNU Public License, Version 2, incorporated
7 * herein by reference.
8 *
9 * (C) Copyright 2003, Motorola, Inc.
10 * maintained by Xianghua Xiao (x.xiao@motorola.com)
11 * author Andy Fleming
12 *
13 */
14
15#include <config.h>
16#include <mpc85xx.h>
17#include <common.h>
18#include <malloc.h>
19#include <net.h>
20#include <command.h>
21
22#if defined(CONFIG_TSEC_ENET)
23#include "tsec.h"
24
25#define TX_BUF_CNT 2
26
27#undef TSEC_DEBUG
28#ifdef TSEC_DEBUG
29#define DBGPRINT(x) printf(x)
30#else
31#define DBGPRINT(x)
32#endif
33
34static uint rxIdx; /* index of the current RX buffer */
35static uint txIdx; /* index of the current TX buffer */
36
37typedef volatile struct rtxbd {
38 txbd8_t txbd[TX_BUF_CNT];
39 rxbd8_t rxbd[PKTBUFSRX];
40} RTXBD;
41
42#ifdef __GNUC__
43static RTXBD rtx __attribute__ ((aligned(8)));
44#else
45#error "rtx must be 64-bit aligned"
46#endif
47
48static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
49static int tsec_recv(struct eth_device* dev);
50static int tsec_init(struct eth_device* dev, bd_t * bd);
51static void tsec_halt(struct eth_device* dev);
52static void init_registers(tsec_t *regs);
53static void startup_tsec(tsec_t *regs);
54static void init_phy(tsec_t *regs);
55
56/* Initialize device structure. returns 0 on failure, 1 on
57 * success */
58int tsec_initialize(bd_t *bis)
59{
60 struct eth_device* dev;
61 int i;
62
63 dev = (struct eth_device*) malloc(sizeof *dev);
64
65 if(dev == NULL)
66 return 0;
67
68 memset(dev, 0, sizeof *dev);
69
70 sprintf(dev->name, "MOTOROLA ETHERNET");
71 dev->iobase = 0;
72 dev->priv = 0;
73 dev->init = tsec_init;
74 dev->halt = tsec_halt;
75 dev->send = tsec_send;
76 dev->recv = tsec_recv;
77
78 /* Tell u-boot to get the addr from the env */
79 for(i=0;i<6;i++)
80 dev->enetaddr[i] = 0;
81
82 eth_register(dev);
83
84 return 1;
85}
86
87
88/* Initializes data structures and registers for the controller,
89 * and brings the interface up */
90int tsec_init(struct eth_device* dev, bd_t * bd)
91{
92 tsec_t *regs;
93 uint tempval;
94 char tmpbuf[MAC_ADDR_LEN];
95 int i;
96
97 regs = (tsec_t *)(TSEC_BASE_ADDR);
98
99 /* Make sure the controller is stopped */
100 tsec_halt(dev);
101
102 /* Reset the MAC */
103 regs->maccfg1 |= MACCFG1_SOFT_RESET;
104
105 /* Clear MACCFG1[Soft_Reset] */
106 regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
107
108 /* Init MACCFG2. Defaults to GMII/MII */
109 regs->maccfg2 = MACCFG2_INIT_SETTINGS;
110
111 /* Init ECNTRL */
112 regs->ecntrl = ECNTRL_INIT_SETTINGS;
113
114 /* Copy the station address into the address registers.
115 * Backwards, because little endian MACS are dumb */
116 for(i=0;i<MAC_ADDR_LEN;i++) {
117 tmpbuf[MAC_ADDR_LEN - 1 - i] = bd->bi_enetaddr[i];
118 }
119 (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
120
121 tempval = *((uint *)(tmpbuf +4));
122
123 (uint)(regs->macstnaddr2) = tempval;
124
125 /* Initialize the PHY */
126 init_phy(regs);
127
128 /* reset the indices to zero */
129 rxIdx = 0;
130 txIdx = 0;
131
132 /* Clear out (for the most part) the other registers */
133 init_registers(regs);
134
135 /* Ready the device for tx/rx */
136 startup_tsec(regs);
137
138 return 1;
139
140}
141
142
143/* Reads from the register at offset in the PHY at phyid, */
144/* using the register set defined in regbase. It waits until the */
145/* bits in the miimstat are valid (miimind notvalid bit cleared), */
146/* and then passes those bits on to the variable specified in */
147/* value */
148/* Before it does the read, it needs to clear the command field */
149uint read_phy_reg(tsec_t *regbase, uint phyid, uint offset)
150{
151 uint value;
152
153 /* Put the address of the phy, and the register number into
154 * MIIMADD
155 */
156 regbase->miimadd = (phyid << 8) | offset;
157
158 /* Clear the command register, and wait */
159 regbase->miimcom = 0;
160 asm("msync");
161
162 /* Initiate a read command, and wait */
163 regbase->miimcom = MIIM_READ_COMMAND;
164 asm("msync");
165
166 /* Wait for the the indication that the read is done */
167 while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
168
169 /* Grab the value read from the PHY */
170 value = regbase->miimstat;
171
172 return value;
173}
174
175/* Setup the PHY */
176static void init_phy(tsec_t *regs)
177{
178 uint testval;
179 unsigned int timeout = TSEC_TIMEOUT;
180
181 /* Assign a Physical address to the TBI */
182 regs->tbipa=TBIPA_VALUE;
183
184 /* reset the management interface */
185 regs->miimcfg=MIIMCFG_RESET;
186
187 regs->miimcfg=MIIMCFG_INIT_VALUE;
188
189 /* Wait until the bus is free */
190 while(regs->miimind & MIIMIND_BUSY);
191
192#ifdef CONFIG_PHY_CIS8201
193 /* override PHY config settings */
194 write_phy_reg(regs, 0, MIIM_AUX_CONSTAT, MIIM_AUXCONSTAT_INIT);
195
196 /* Set up interface mode */
197 write_phy_reg(regs, 0, MIIM_EXT_CON1, MIIM_EXTCON1_INIT);
198#endif
199
200 /* Set the PHY to gigabit, full duplex, Auto-negotiate */
201 write_phy_reg(regs, 0, MIIM_CONTROL, MIIM_CONTROL_INIT);
202
203 /* Wait until TBI_STATUS indicates AN is done */
204 DBGPRINT("Waiting for Auto-negotiation to complete\n");
205 testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
206
207 while((!(testval & MIIM_TBI_STATUS_AN_DONE))&& timeout--) {
208 testval=read_phy_reg(regs, 0, MIIM_TBI_STATUS);
209 }
210
211 if(testval & MIIM_TBI_STATUS_AN_DONE)
212 DBGPRINT("Auto-negotiation done\n");
213 else
214 DBGPRINT("Auto-negotiation timed-out.\n");
215
216#ifdef CONFIG_PHY_CIS8201
217 /* Find out what duplexity (duplicity?) we have */
218 /* Read it twice to make sure */
219 testval=read_phy_reg(regs, 0, MIIM_AUX_CONSTAT);
220
221 if(testval & MIIM_AUXCONSTAT_DUPLEX) {
222 DBGPRINT("Enet starting in full duplex\n");
223 regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
224 } else {
225 DBGPRINT("Enet starting in half duplex\n");
226 regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
227 }
228
229 /* Also, we look to see what speed we are at
230 * if Gigabit, MACCFG2 goes in GMII, otherwise,
231 * MII mode.
232 */
233 if((testval & MIIM_AUXCONSTAT_SPEED) != MIIM_AUXCONSTAT_GBIT) {
234 if((testval & MIIM_AUXCONSTAT_SPEED) == MIIM_AUXCONSTAT_100)
235 DBGPRINT("Enet starting in 100BT\n");
236 else
237 DBGPRINT("Enet starting in 10BT\n");
238
239 /* mark the mode in MACCFG2 */
240 regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
241 } else {
242 DBGPRINT("Enet starting in 1000BT\n");
243 }
244
245#endif
246
247#ifdef CONFIG_PHY_M88E1011
248 /* Read the PHY to see what speed and duplex we are */
249 testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
250
251 timeout = TSEC_TIMEOUT;
252 while((!(testval & MIIM_PHYSTAT_SPDDONE)) && timeout--) {
253 testval = read_phy_reg(regs,0,MIIM_PHY_STATUS);
254 }
255
256 if(!(testval & MIIM_PHYSTAT_SPDDONE))
257 DBGPRINT("Enet: Speed not resolved\n");
258
259 testval=read_phy_reg(regs, 0, MIIM_PHY_STATUS);
260 if(testval & MIIM_PHYSTAT_DUPLEX) {
261 DBGPRINT("Enet starting in Full Duplex\n");
262 regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
263 } else {
264 DBGPRINT("Enet starting in Half Duplex\n");
265 regs->maccfg2 &= ~MACCFG2_FULL_DUPLEX;
266 }
267
268 if(!((testval&MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_GBIT)) {
269 if((testval & MIIM_PHYSTAT_SPEED) == MIIM_PHYSTAT_100)
270 DBGPRINT("Enet starting in 100BT\n");
271 else
272 DBGPRINT("Enet starting in 10BT\n");
273
274 regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF)) | MACCFG2_MII);
275 } else {
276 DBGPRINT("Enet starting in 1000BT\n");
277 }
278#endif
279
280}
281
282
283static void init_registers(tsec_t *regs)
284{
285 /* Clear IEVENT */
286 regs->ievent = IEVENT_INIT_CLEAR;
287
288 regs->imask = IMASK_INIT_CLEAR;
289
290 regs->hash.iaddr0 = 0;
291 regs->hash.iaddr1 = 0;
292 regs->hash.iaddr2 = 0;
293 regs->hash.iaddr3 = 0;
294 regs->hash.iaddr4 = 0;
295 regs->hash.iaddr5 = 0;
296 regs->hash.iaddr6 = 0;
297 regs->hash.iaddr7 = 0;
298
299 regs->hash.gaddr0 = 0;
300 regs->hash.gaddr1 = 0;
301 regs->hash.gaddr2 = 0;
302 regs->hash.gaddr3 = 0;
303 regs->hash.gaddr4 = 0;
304 regs->hash.gaddr5 = 0;
305 regs->hash.gaddr6 = 0;
306 regs->hash.gaddr7 = 0;
307
308 regs->rctrl = 0x00000000;
309
310 /* Init RMON mib registers */
311 memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
312
313 regs->rmon.cam1 = 0xffffffff;
314 regs->rmon.cam2 = 0xffffffff;
315
316 regs->mrblr = MRBLR_INIT_SETTINGS;
317
318 regs->minflr = MINFLR_INIT_SETTINGS;
319
320 regs->attr = ATTR_INIT_SETTINGS;
321 regs->attreli = ATTRELI_INIT_SETTINGS;
322
323}
324
325static void startup_tsec(tsec_t *regs)
326{
327 int i;
328
329 /* Point to the buffer descriptors */
330 regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
331 regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
332
333 /* Initialize the Rx Buffer descriptors */
334 for (i = 0; i < PKTBUFSRX; i++) {
335 rtx.rxbd[i].status = RXBD_EMPTY;
336 rtx.rxbd[i].length = 0;
337 rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
338 }
339 rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
340
341 /* Initialize the TX Buffer Descriptors */
342 for(i=0; i<TX_BUF_CNT; i++) {
343 rtx.txbd[i].status = 0;
344 rtx.txbd[i].length = 0;
345 rtx.txbd[i].bufPtr = 0;
346 }
347 rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
348
349 /* Enable Transmit and Receive */
350 regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
351
352 /* Tell the DMA it is clear to go */
353 regs->dmactrl |= DMACTRL_INIT_SETTINGS;
354 regs->tstat = TSTAT_CLEAR_THALT;
355 regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
356}
357
358/* This returns the status bits of the device. The return value
359 * is never checked, and this is what the 8260 driver did, so we
360 * do the same. Presumably, this would be zero if there were no
361 * errors */
362static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
363{
364 int i;
365 int result = 0;
366 tsec_t * regs = (tsec_t *)(TSEC_BASE_ADDR);
367
368 /* Find an empty buffer descriptor */
369 for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
370 if (i >= TOUT_LOOP) {
371 DBGPRINT("tsec: tx buffers full\n");
372 return result;
373 }
374 }
375
376 rtx.txbd[txIdx].bufPtr = (uint)packet;
377 rtx.txbd[txIdx].length = length;
378 rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
379
380 /* Tell the DMA to go */
381 regs->tstat = TSTAT_CLEAR_THALT;
382
383 /* Wait for buffer to be transmitted */
384 for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
385 if (i >= TOUT_LOOP) {
386 DBGPRINT("tsec: tx error\n");
387 return result;
388 }
389 }
390
391 txIdx = (txIdx + 1) % TX_BUF_CNT;
392 result = rtx.txbd[txIdx].status & TXBD_STATS;
393
394 return result;
395}
396
397static int tsec_recv(struct eth_device* dev)
398{
399 int length;
400 tsec_t *regs = (tsec_t *)(TSEC_BASE_ADDR);
401
402 while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
403
404 length = rtx.rxbd[rxIdx].length;
405
406 /* Send the packet up if there were no errors */
407 if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
408 NetReceive(NetRxPackets[rxIdx], length - 4);
409 }
410
411 rtx.rxbd[rxIdx].length = 0;
412
413 /* Set the wrap bit if this is the last element in the list */
414 rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
415
416 rxIdx = (rxIdx + 1) % PKTBUFSRX;
417 }
418
419 if(regs->ievent&IEVENT_BSY) {
420 regs->ievent = IEVENT_BSY;
421 regs->rstat = RSTAT_CLEAR_RHALT;
422 }
423
424 return -1;
425
426}
427
428
429static void tsec_halt(struct eth_device* dev)
430{
431 tsec_t *regs = (tsec_t *)(TSEC_BASE_ADDR);
432
433 regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
434 regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
435
436 while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
437
438 regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
439
440}
441#endif /* CONFIG_TSEC_ENET */