xref: /rk3399_rockchip-uboot/arch/powerpc/cpu/mpc85xx/ether_fcc.c (revision a47a12becf66f02a56da91c161e2edb625e9f20c)
1*a47a12beSStefan Roese /*
2*a47a12beSStefan Roese  * MPC8560 FCC Fast Ethernet
3*a47a12beSStefan Roese  * Copyright (c) 2003 Motorola,Inc.
4*a47a12beSStefan Roese  * Xianghua Xiao, (X.Xiao@motorola.com)
5*a47a12beSStefan Roese  *
6*a47a12beSStefan Roese  * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
7*a47a12beSStefan Roese  *
8*a47a12beSStefan Roese  * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
9*a47a12beSStefan Roese  * Marius Groeger <mgroeger@sysgo.de>
10*a47a12beSStefan Roese  *
11*a47a12beSStefan Roese  * See file CREDITS for list of people who contributed to this
12*a47a12beSStefan Roese  * project.
13*a47a12beSStefan Roese  *
14*a47a12beSStefan Roese  * This program is free software; you can redistribute it and/or
15*a47a12beSStefan Roese  * modify it under the terms of the GNU General Public License as
16*a47a12beSStefan Roese  * published by the Free Software Foundation; either version 2 of
17*a47a12beSStefan Roese  * the License, or (at your option) any later version.
18*a47a12beSStefan Roese  *
19*a47a12beSStefan Roese  * This program is distributed in the hope that it will be useful,
20*a47a12beSStefan Roese  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21*a47a12beSStefan Roese  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22*a47a12beSStefan Roese  * GNU General Public License for more details.
23*a47a12beSStefan Roese  *
24*a47a12beSStefan Roese  * You should have received a copy of the GNU General Public License
25*a47a12beSStefan Roese  * along with this program; if not, write to the Free Software
26*a47a12beSStefan Roese  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27*a47a12beSStefan Roese  * MA 02111-1307 USA
28*a47a12beSStefan Roese  */
29*a47a12beSStefan Roese 
30*a47a12beSStefan Roese /*
31*a47a12beSStefan Roese  * MPC8560 FCC Fast Ethernet
32*a47a12beSStefan Roese  * Basic ET HW initialization and packet RX/TX routines
33*a47a12beSStefan Roese  *
34*a47a12beSStefan Roese  * This code will not perform the IO port configuration. This should be
35*a47a12beSStefan Roese  * done in the iop_conf_t structure specific for the board.
36*a47a12beSStefan Roese  *
37*a47a12beSStefan Roese  * TODO:
38*a47a12beSStefan Roese  * add a PHY driver to do the negotiation
39*a47a12beSStefan Roese  * reflect negotiation results in FPSMR
40*a47a12beSStefan Roese  * look for ways to configure the board specific stuff elsewhere, eg.
41*a47a12beSStefan Roese  *    config_xxx.h or the board directory
42*a47a12beSStefan Roese  */
43*a47a12beSStefan Roese 
44*a47a12beSStefan Roese #include <common.h>
45*a47a12beSStefan Roese #include <malloc.h>
46*a47a12beSStefan Roese #include <asm/cpm_85xx.h>
47*a47a12beSStefan Roese #include <command.h>
48*a47a12beSStefan Roese #include <config.h>
49*a47a12beSStefan Roese #include <net.h>
50*a47a12beSStefan Roese 
51*a47a12beSStefan Roese #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
52*a47a12beSStefan Roese #include <miiphy.h>
53*a47a12beSStefan Roese #endif
54*a47a12beSStefan Roese 
55*a47a12beSStefan Roese #if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
56*a47a12beSStefan Roese 	defined(CONFIG_NET_MULTI)
57*a47a12beSStefan Roese 
58*a47a12beSStefan Roese static struct ether_fcc_info_s
59*a47a12beSStefan Roese {
60*a47a12beSStefan Roese 	int ether_index;
61*a47a12beSStefan Roese 	int proff_enet;
62*a47a12beSStefan Roese 	ulong cpm_cr_enet_sblock;
63*a47a12beSStefan Roese 	ulong cpm_cr_enet_page;
64*a47a12beSStefan Roese 	ulong cmxfcr_mask;
65*a47a12beSStefan Roese 	ulong cmxfcr_value;
66*a47a12beSStefan Roese }
67*a47a12beSStefan Roese 	ether_fcc_info[] =
68*a47a12beSStefan Roese {
69*a47a12beSStefan Roese #ifdef CONFIG_ETHER_ON_FCC1
70*a47a12beSStefan Roese {
71*a47a12beSStefan Roese 	0,
72*a47a12beSStefan Roese 	PROFF_FCC1,
73*a47a12beSStefan Roese 	CPM_CR_FCC1_SBLOCK,
74*a47a12beSStefan Roese 	CPM_CR_FCC1_PAGE,
75*a47a12beSStefan Roese 	CONFIG_SYS_CMXFCR_MASK1,
76*a47a12beSStefan Roese 	CONFIG_SYS_CMXFCR_VALUE1
77*a47a12beSStefan Roese },
78*a47a12beSStefan Roese #endif
79*a47a12beSStefan Roese 
80*a47a12beSStefan Roese #ifdef CONFIG_ETHER_ON_FCC2
81*a47a12beSStefan Roese {
82*a47a12beSStefan Roese 	1,
83*a47a12beSStefan Roese 	PROFF_FCC2,
84*a47a12beSStefan Roese 	CPM_CR_FCC2_SBLOCK,
85*a47a12beSStefan Roese 	CPM_CR_FCC2_PAGE,
86*a47a12beSStefan Roese 	CONFIG_SYS_CMXFCR_MASK2,
87*a47a12beSStefan Roese 	CONFIG_SYS_CMXFCR_VALUE2
88*a47a12beSStefan Roese },
89*a47a12beSStefan Roese #endif
90*a47a12beSStefan Roese 
91*a47a12beSStefan Roese #ifdef CONFIG_ETHER_ON_FCC3
92*a47a12beSStefan Roese {
93*a47a12beSStefan Roese 	2,
94*a47a12beSStefan Roese 	PROFF_FCC3,
95*a47a12beSStefan Roese 	CPM_CR_FCC3_SBLOCK,
96*a47a12beSStefan Roese 	CPM_CR_FCC3_PAGE,
97*a47a12beSStefan Roese 	CONFIG_SYS_CMXFCR_MASK3,
98*a47a12beSStefan Roese 	CONFIG_SYS_CMXFCR_VALUE3
99*a47a12beSStefan Roese },
100*a47a12beSStefan Roese #endif
101*a47a12beSStefan Roese };
102*a47a12beSStefan Roese 
103*a47a12beSStefan Roese /*---------------------------------------------------------------------*/
104*a47a12beSStefan Roese 
105*a47a12beSStefan Roese /* Maximum input DMA size.  Must be a should(?) be a multiple of 4. */
106*a47a12beSStefan Roese #define PKT_MAXDMA_SIZE         1520
107*a47a12beSStefan Roese 
108*a47a12beSStefan Roese /* The FCC stores dest/src/type, data, and checksum for receive packets. */
109*a47a12beSStefan Roese #define PKT_MAXBUF_SIZE         1518
110*a47a12beSStefan Roese #define PKT_MINBUF_SIZE         64
111*a47a12beSStefan Roese 
112*a47a12beSStefan Roese /* Maximum input buffer size.  Must be a multiple of 32. */
113*a47a12beSStefan Roese #define PKT_MAXBLR_SIZE         1536
114*a47a12beSStefan Roese 
115*a47a12beSStefan Roese #define TOUT_LOOP 1000000
116*a47a12beSStefan Roese 
117*a47a12beSStefan Roese #define TX_BUF_CNT 2
118*a47a12beSStefan Roese 
119*a47a12beSStefan Roese static uint rxIdx;	/* index of the current RX buffer */
120*a47a12beSStefan Roese static uint txIdx;	/* index of the current TX buffer */
121*a47a12beSStefan Roese 
122*a47a12beSStefan Roese /*
123*a47a12beSStefan Roese  * FCC Ethernet Tx and Rx buffer descriptors.
124*a47a12beSStefan Roese  * Provide for Double Buffering
125*a47a12beSStefan Roese  * Note: PKTBUFSRX is defined in net.h
126*a47a12beSStefan Roese  */
127*a47a12beSStefan Roese 
128*a47a12beSStefan Roese typedef volatile struct rtxbd {
129*a47a12beSStefan Roese     cbd_t rxbd[PKTBUFSRX];
130*a47a12beSStefan Roese     cbd_t txbd[TX_BUF_CNT];
131*a47a12beSStefan Roese } RTXBD;
132*a47a12beSStefan Roese 
133*a47a12beSStefan Roese /*  Good news: the FCC supports external BDs! */
134*a47a12beSStefan Roese #ifdef __GNUC__
135*a47a12beSStefan Roese static RTXBD rtx __attribute__ ((aligned(8)));
136*a47a12beSStefan Roese #else
137*a47a12beSStefan Roese #error "rtx must be 64-bit aligned"
138*a47a12beSStefan Roese #endif
139*a47a12beSStefan Roese 
140*a47a12beSStefan Roese #undef ET_DEBUG
141*a47a12beSStefan Roese 
142*a47a12beSStefan Roese static int fec_send(struct eth_device* dev, volatile void *packet, int length)
143*a47a12beSStefan Roese {
144*a47a12beSStefan Roese     int i = 0;
145*a47a12beSStefan Roese     int result = 0;
146*a47a12beSStefan Roese 
147*a47a12beSStefan Roese     if (length <= 0) {
148*a47a12beSStefan Roese 	printf("fec: bad packet size: %d\n", length);
149*a47a12beSStefan Roese 	goto out;
150*a47a12beSStefan Roese     }
151*a47a12beSStefan Roese 
152*a47a12beSStefan Roese     for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
153*a47a12beSStefan Roese 	if (i >= TOUT_LOOP) {
154*a47a12beSStefan Roese 	    printf("fec: tx buffer not ready\n");
155*a47a12beSStefan Roese 	    goto out;
156*a47a12beSStefan Roese 	}
157*a47a12beSStefan Roese     }
158*a47a12beSStefan Roese 
159*a47a12beSStefan Roese     rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
160*a47a12beSStefan Roese     rtx.txbd[txIdx].cbd_datlen = length;
161*a47a12beSStefan Roese     rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
162*a47a12beSStefan Roese 			       BD_ENET_TX_TC | BD_ENET_TX_PAD);
163*a47a12beSStefan Roese 
164*a47a12beSStefan Roese     for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
165*a47a12beSStefan Roese 	if (i >= TOUT_LOOP) {
166*a47a12beSStefan Roese 	    printf("fec: tx error\n");
167*a47a12beSStefan Roese 	    goto out;
168*a47a12beSStefan Roese 	}
169*a47a12beSStefan Roese     }
170*a47a12beSStefan Roese 
171*a47a12beSStefan Roese #ifdef ET_DEBUG
172*a47a12beSStefan Roese     printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
173*a47a12beSStefan Roese     printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
174*a47a12beSStefan Roese     for(i=0;i<(length/16 + 1);i++) {
175*a47a12beSStefan Roese 	 printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
176*a47a12beSStefan Roese     *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
177*a47a12beSStefan Roese     *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
178*a47a12beSStefan Roese     }
179*a47a12beSStefan Roese #endif
180*a47a12beSStefan Roese 
181*a47a12beSStefan Roese     /* return only status bits */
182*a47a12beSStefan Roese     result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
183*a47a12beSStefan Roese     txIdx = (txIdx + 1) % TX_BUF_CNT;
184*a47a12beSStefan Roese 
185*a47a12beSStefan Roese out:
186*a47a12beSStefan Roese     return result;
187*a47a12beSStefan Roese }
188*a47a12beSStefan Roese 
189*a47a12beSStefan Roese static int fec_recv(struct eth_device* dev)
190*a47a12beSStefan Roese {
191*a47a12beSStefan Roese     int length;
192*a47a12beSStefan Roese 
193*a47a12beSStefan Roese     for (;;)
194*a47a12beSStefan Roese     {
195*a47a12beSStefan Roese 	if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
196*a47a12beSStefan Roese 	    length = -1;
197*a47a12beSStefan Roese 	    break;     /* nothing received - leave for() loop */
198*a47a12beSStefan Roese 	}
199*a47a12beSStefan Roese 	length = rtx.rxbd[rxIdx].cbd_datlen;
200*a47a12beSStefan Roese 
201*a47a12beSStefan Roese 	if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
202*a47a12beSStefan Roese 	    printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
203*a47a12beSStefan Roese 	}
204*a47a12beSStefan Roese 	else {
205*a47a12beSStefan Roese 	    /* Pass the packet up to the protocol layers. */
206*a47a12beSStefan Roese 	    NetReceive(NetRxPackets[rxIdx], length - 4);
207*a47a12beSStefan Roese 	}
208*a47a12beSStefan Roese 
209*a47a12beSStefan Roese 
210*a47a12beSStefan Roese 	/* Give the buffer back to the FCC. */
211*a47a12beSStefan Roese 	rtx.rxbd[rxIdx].cbd_datlen = 0;
212*a47a12beSStefan Roese 
213*a47a12beSStefan Roese 	/* wrap around buffer index when necessary */
214*a47a12beSStefan Roese 	if ((rxIdx + 1) >= PKTBUFSRX) {
215*a47a12beSStefan Roese 	    rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
216*a47a12beSStefan Roese 	    rxIdx = 0;
217*a47a12beSStefan Roese 	}
218*a47a12beSStefan Roese 	else {
219*a47a12beSStefan Roese 	    rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
220*a47a12beSStefan Roese 	    rxIdx++;
221*a47a12beSStefan Roese 	}
222*a47a12beSStefan Roese     }
223*a47a12beSStefan Roese     return length;
224*a47a12beSStefan Roese }
225*a47a12beSStefan Roese 
226*a47a12beSStefan Roese 
227*a47a12beSStefan Roese static int fec_init(struct eth_device* dev, bd_t *bis)
228*a47a12beSStefan Roese {
229*a47a12beSStefan Roese     struct ether_fcc_info_s * info = dev->priv;
230*a47a12beSStefan Roese     int i;
231*a47a12beSStefan Roese     volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
232*a47a12beSStefan Roese     volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
233*a47a12beSStefan Roese     fcc_enet_t *pram_ptr;
234*a47a12beSStefan Roese     unsigned long mem_addr;
235*a47a12beSStefan Roese 
236*a47a12beSStefan Roese #if 0
237*a47a12beSStefan Roese     mii_discover_phy();
238*a47a12beSStefan Roese #endif
239*a47a12beSStefan Roese 
240*a47a12beSStefan Roese     /* 28.9 - (1-2): ioports have been set up already */
241*a47a12beSStefan Roese 
242*a47a12beSStefan Roese     /* 28.9 - (3): connect FCC's tx and rx clocks */
243*a47a12beSStefan Roese     cpm->im_cpm_mux.cmxuar = 0; /* ATM */
244*a47a12beSStefan Roese     cpm->im_cpm_mux.cmxfcr = (cpm->im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) |
245*a47a12beSStefan Roese 							info->cmxfcr_value;
246*a47a12beSStefan Roese 
247*a47a12beSStefan Roese     /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */
248*a47a12beSStefan Roese     if(info->ether_index == 0) {
249*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
250*a47a12beSStefan Roese     } else if (info->ether_index == 1) {
251*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
252*a47a12beSStefan Roese     } else if (info->ether_index == 2) {
253*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
254*a47a12beSStefan Roese     }
255*a47a12beSStefan Roese 
256*a47a12beSStefan Roese     /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */
257*a47a12beSStefan Roese     if(info->ether_index == 0) {
258*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
259*a47a12beSStefan Roese     } else if (info->ether_index == 1){
260*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
261*a47a12beSStefan Roese     } else if (info->ether_index == 2){
262*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
263*a47a12beSStefan Roese     }
264*a47a12beSStefan Roese 
265*a47a12beSStefan Roese     /* 28.9 - (6): FDSR: Ethernet Syn */
266*a47a12beSStefan Roese     if(info->ether_index == 0) {
267*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.fdsr = 0xD555;
268*a47a12beSStefan Roese     } else if (info->ether_index == 1) {
269*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.fdsr = 0xD555;
270*a47a12beSStefan Roese     } else if (info->ether_index == 2) {
271*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.fdsr = 0xD555;
272*a47a12beSStefan Roese     }
273*a47a12beSStefan Roese 
274*a47a12beSStefan Roese     /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
275*a47a12beSStefan Roese     rxIdx = 0;
276*a47a12beSStefan Roese     txIdx = 0;
277*a47a12beSStefan Roese 
278*a47a12beSStefan Roese     /* Setup Receiver Buffer Descriptors */
279*a47a12beSStefan Roese     for (i = 0; i < PKTBUFSRX; i++)
280*a47a12beSStefan Roese     {
281*a47a12beSStefan Roese       rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
282*a47a12beSStefan Roese       rtx.rxbd[i].cbd_datlen = 0;
283*a47a12beSStefan Roese       rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
284*a47a12beSStefan Roese     }
285*a47a12beSStefan Roese     rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
286*a47a12beSStefan Roese 
287*a47a12beSStefan Roese     /* Setup Ethernet Transmitter Buffer Descriptors */
288*a47a12beSStefan Roese     for (i = 0; i < TX_BUF_CNT; i++)
289*a47a12beSStefan Roese     {
290*a47a12beSStefan Roese       rtx.txbd[i].cbd_sc = 0;
291*a47a12beSStefan Roese       rtx.txbd[i].cbd_datlen = 0;
292*a47a12beSStefan Roese       rtx.txbd[i].cbd_bufaddr = 0;
293*a47a12beSStefan Roese     }
294*a47a12beSStefan Roese     rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
295*a47a12beSStefan Roese 
296*a47a12beSStefan Roese     /* 28.9 - (7): initialize parameter ram */
297*a47a12beSStefan Roese     pram_ptr = (fcc_enet_t *)&(cpm->im_dprambase[info->proff_enet]);
298*a47a12beSStefan Roese 
299*a47a12beSStefan Roese     /* clear whole structure to make sure all reserved fields are zero */
300*a47a12beSStefan Roese     memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
301*a47a12beSStefan Roese 
302*a47a12beSStefan Roese     /*
303*a47a12beSStefan Roese      * common Parameter RAM area
304*a47a12beSStefan Roese      *
305*a47a12beSStefan Roese      * Allocate space in the reserved FCC area of DPRAM for the
306*a47a12beSStefan Roese      * internal buffers.  No one uses this space (yet), so we
307*a47a12beSStefan Roese      * can do this.  Later, we will add resource management for
308*a47a12beSStefan Roese      * this area.
309*a47a12beSStefan Roese      * CPM_FCC_SPECIAL_BASE:	0xB000 for MPC8540, MPC8560
310*a47a12beSStefan Roese      *				0x9000 for MPC8541, MPC8555
311*a47a12beSStefan Roese      */
312*a47a12beSStefan Roese     mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
313*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
314*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
315*a47a12beSStefan Roese     /*
316*a47a12beSStefan Roese      * Set maximum bytes per receive buffer.
317*a47a12beSStefan Roese      * It must be a multiple of 32.
318*a47a12beSStefan Roese      */
319*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */
320*a47a12beSStefan Roese     /* localbus SDRAM should be preferred */
321*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
322*a47a12beSStefan Roese 				       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
323*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
324*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_rbdstat = 0;
325*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_rbdlen = 0;
326*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_rdptr = 0;
327*a47a12beSStefan Roese     /* localbus SDRAM should be preferred */
328*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
329*a47a12beSStefan Roese 				       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
330*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
331*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_tbdstat = 0;
332*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_tbdlen = 0;
333*a47a12beSStefan Roese     pram_ptr->fen_genfcc.fcc_tdptr = 0;
334*a47a12beSStefan Roese 
335*a47a12beSStefan Roese     /* protocol-specific area */
336*a47a12beSStefan Roese     pram_ptr->fen_statbuf = 0x0;
337*a47a12beSStefan Roese     pram_ptr->fen_cmask = 0xdebb20e3;	/* CRC mask */
338*a47a12beSStefan Roese     pram_ptr->fen_cpres = 0xffffffff;	/* CRC preset */
339*a47a12beSStefan Roese     pram_ptr->fen_crcec = 0;
340*a47a12beSStefan Roese     pram_ptr->fen_alec = 0;
341*a47a12beSStefan Roese     pram_ptr->fen_disfc = 0;
342*a47a12beSStefan Roese     pram_ptr->fen_retlim = 15;		/* Retry limit threshold */
343*a47a12beSStefan Roese     pram_ptr->fen_retcnt = 0;
344*a47a12beSStefan Roese     pram_ptr->fen_pper = 0;
345*a47a12beSStefan Roese     pram_ptr->fen_boffcnt = 0;
346*a47a12beSStefan Roese     pram_ptr->fen_gaddrh = 0;
347*a47a12beSStefan Roese     pram_ptr->fen_gaddrl = 0;
348*a47a12beSStefan Roese     pram_ptr->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
349*a47a12beSStefan Roese     /*
350*a47a12beSStefan Roese      * Set Ethernet station address.
351*a47a12beSStefan Roese      *
352*a47a12beSStefan Roese      * This is supplied in the board information structure, so we
353*a47a12beSStefan Roese      * copy that into the controller.
354*a47a12beSStefan Roese      * So far we have only been given one Ethernet address. We make
355*a47a12beSStefan Roese      * it unique by setting a few bits in the upper byte of the
356*a47a12beSStefan Roese      * non-static part of the address.
357*a47a12beSStefan Roese      */
358*a47a12beSStefan Roese #define ea eth_get_dev()->enetaddr
359*a47a12beSStefan Roese     pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
360*a47a12beSStefan Roese     pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
361*a47a12beSStefan Roese     pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
362*a47a12beSStefan Roese #undef ea
363*a47a12beSStefan Roese     pram_ptr->fen_ibdcount = 0;
364*a47a12beSStefan Roese     pram_ptr->fen_ibdstart = 0;
365*a47a12beSStefan Roese     pram_ptr->fen_ibdend = 0;
366*a47a12beSStefan Roese     pram_ptr->fen_txlen = 0;
367*a47a12beSStefan Roese     pram_ptr->fen_iaddrh = 0;  /* disable hash */
368*a47a12beSStefan Roese     pram_ptr->fen_iaddrl = 0;
369*a47a12beSStefan Roese     pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */
370*a47a12beSStefan Roese     /* pad pointer. use tiptr since we don't need a specific padding char */
371*a47a12beSStefan Roese     pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
372*a47a12beSStefan Roese     pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE;	/* maximum DMA1 length:1520 */
373*a47a12beSStefan Roese     pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE;	/* maximum DMA2 length:1520 */
374*a47a12beSStefan Roese 
375*a47a12beSStefan Roese #if defined(ET_DEBUG)
376*a47a12beSStefan Roese     printf("parm_ptr(0xff788500) = %p\n",pram_ptr);
377*a47a12beSStefan Roese     printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n",
378*a47a12beSStefan Roese 	pram_ptr->fen_genfcc.fcc_rbase);
379*a47a12beSStefan Roese     printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n",
380*a47a12beSStefan Roese 	pram_ptr->fen_genfcc.fcc_tbase);
381*a47a12beSStefan Roese #endif
382*a47a12beSStefan Roese 
383*a47a12beSStefan Roese     /* 28.9 - (8)(9): clear out events in FCCE */
384*a47a12beSStefan Roese     /* 28.9 - (9): FCCM: mask all events */
385*a47a12beSStefan Roese     if(info->ether_index == 0) {
386*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.fcce = ~0x0;
387*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.fccm = 0;
388*a47a12beSStefan Roese     } else if (info->ether_index == 1) {
389*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.fcce = ~0x0;
390*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.fccm = 0;
391*a47a12beSStefan Roese     } else if (info->ether_index == 2) {
392*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.fcce = ~0x0;
393*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.fccm = 0;
394*a47a12beSStefan Roese     }
395*a47a12beSStefan Roese 
396*a47a12beSStefan Roese     /* 28.9 - (10-12): we don't use ethernet interrupts */
397*a47a12beSStefan Roese 
398*a47a12beSStefan Roese     /* 28.9 - (13)
399*a47a12beSStefan Roese      *
400*a47a12beSStefan Roese      * Let's re-initialize the channel now.  We have to do it later
401*a47a12beSStefan Roese      * than the manual describes because we have just now finished
402*a47a12beSStefan Roese      * the BD initialization.
403*a47a12beSStefan Roese      */
404*a47a12beSStefan Roese     cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
405*a47a12beSStefan Roese 			    info->cpm_cr_enet_sblock,
406*a47a12beSStefan Roese 			    0x0c,
407*a47a12beSStefan Roese 			    CPM_CR_INIT_TRX) | CPM_CR_FLG;
408*a47a12beSStefan Roese     do {
409*a47a12beSStefan Roese 	__asm__ __volatile__ ("eieio");
410*a47a12beSStefan Roese     } while (cp->cpcr & CPM_CR_FLG);
411*a47a12beSStefan Roese 
412*a47a12beSStefan Roese     /* 28.9 - (14): enable tx/rx in gfmr */
413*a47a12beSStefan Roese     if(info->ether_index == 0) {
414*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
415*a47a12beSStefan Roese     } else if (info->ether_index == 1) {
416*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
417*a47a12beSStefan Roese     } else if (info->ether_index == 2) {
418*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
419*a47a12beSStefan Roese     }
420*a47a12beSStefan Roese 
421*a47a12beSStefan Roese     return 1;
422*a47a12beSStefan Roese }
423*a47a12beSStefan Roese 
424*a47a12beSStefan Roese static void fec_halt(struct eth_device* dev)
425*a47a12beSStefan Roese {
426*a47a12beSStefan Roese     struct ether_fcc_info_s * info = dev->priv;
427*a47a12beSStefan Roese     volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
428*a47a12beSStefan Roese 
429*a47a12beSStefan Roese     /* write GFMR: disable tx/rx */
430*a47a12beSStefan Roese     if(info->ether_index == 0) {
431*a47a12beSStefan Roese 	cpm->im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
432*a47a12beSStefan Roese     } else if(info->ether_index == 1) {
433*a47a12beSStefan Roese 	cpm->im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
434*a47a12beSStefan Roese     } else if(info->ether_index == 2) {
435*a47a12beSStefan Roese 	cpm->im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
436*a47a12beSStefan Roese     }
437*a47a12beSStefan Roese }
438*a47a12beSStefan Roese 
439*a47a12beSStefan Roese int fec_initialize(bd_t *bis)
440*a47a12beSStefan Roese {
441*a47a12beSStefan Roese 	struct eth_device* dev;
442*a47a12beSStefan Roese 	int i;
443*a47a12beSStefan Roese 
444*a47a12beSStefan Roese 	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
445*a47a12beSStefan Roese 	{
446*a47a12beSStefan Roese 		dev = (struct eth_device*) malloc(sizeof *dev);
447*a47a12beSStefan Roese 		memset(dev, 0, sizeof *dev);
448*a47a12beSStefan Roese 
449*a47a12beSStefan Roese 		sprintf(dev->name, "FCC%d ETHERNET",
450*a47a12beSStefan Roese 			ether_fcc_info[i].ether_index + 1);
451*a47a12beSStefan Roese 		dev->priv   = &ether_fcc_info[i];
452*a47a12beSStefan Roese 		dev->init   = fec_init;
453*a47a12beSStefan Roese 		dev->halt   = fec_halt;
454*a47a12beSStefan Roese 		dev->send   = fec_send;
455*a47a12beSStefan Roese 		dev->recv   = fec_recv;
456*a47a12beSStefan Roese 
457*a47a12beSStefan Roese 		eth_register(dev);
458*a47a12beSStefan Roese 
459*a47a12beSStefan Roese #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
460*a47a12beSStefan Roese 		&& defined(CONFIG_BITBANGMII)
461*a47a12beSStefan Roese 		miiphy_register(dev->name,
462*a47a12beSStefan Roese 				bb_miiphy_read,	bb_miiphy_write);
463*a47a12beSStefan Roese #endif
464*a47a12beSStefan Roese 	}
465*a47a12beSStefan Roese 
466*a47a12beSStefan Roese 	return 1;
467*a47a12beSStefan Roese }
468*a47a12beSStefan Roese 
469*a47a12beSStefan Roese #endif
470