source: trunk/package/uboot-ifxmips/files/drivers/ifx_sw.c @ 11601

Last change on this file since 11601 was 11601, checked in by nbd, 8 years ago

move ifxmips uboot to package/

File size: 10.5 KB
Line 
1/*
2 * DANUBE internal switch ethernet driver.
3 *
4 * (C) Copyright 2003
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26
27#include <common.h>
28
29#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
30    && defined(CONFIG_DANUBE_SWITCH)
31
32#include <malloc.h>
33#include <net.h>
34#include <asm/danube.h>
35#include <asm/addrspace.h>
36#include <asm/pinstrap.h>
37
38#define MII_MODE 1
39#define REV_MII_MODE 2
40
41#define TX_CHAN_NO   7
42#define RX_CHAN_NO   6
43
44#define NUM_RX_DESC     PKTBUFSRX                 
45#define NUM_TX_DESC     8
46#define MAX_PACKET_SIZE         1536
47#define TOUT_LOOP       100
48#define PHY0_ADDR       1 /*fixme: set the correct value here*/ 
49
50#define DMA_WRITE_REG(reg, value) *((volatile u32 *)reg) = (u32)value
51#define DMA_READ_REG(reg, value)    value = (u32)*((volatile u32*)reg)
52
53#define SW_WRITE_REG(reg, value)  *((volatile u32*)reg) = (u32)value   
54#define SW_READ_REG(reg, value)   value = (u32)*((volatile u32*)reg)
55
56typedef struct
57{
58        union
59        {
60                struct
61                {
62                        volatile u32 OWN                 :1;
63                        volatile u32 C                   :1;
64                        volatile u32 Sop                 :1;
65                        volatile u32 Eop                 :1;
66                        volatile u32 reserved            :3;
67                        volatile u32 Byteoffset          :2; 
68                        volatile u32 reserve             :7;
69                        volatile u32 DataLen             :16;
70                }field;
71
72                volatile u32 word;
73        }status;
74       
75        volatile u32 DataPtr;
76} danube_rx_descriptor_t;
77
78typedef struct
79{
80        union
81        {
82                struct
83                {
84                        volatile u32 OWN                 :1;
85                        volatile u32 C                   :1;
86                        volatile u32 Sop                 :1;
87                        volatile u32 Eop                 :1;
88                        volatile u32 Byteoffset          :5; 
89                        volatile u32 reserved            :7;
90                        volatile u32 DataLen             :16;
91                }field;
92
93                volatile u32 word;
94        }status;
95       
96        volatile u32 DataPtr;
97} danube_tx_descriptor_t;
98
99
100
101
102static danube_rx_descriptor_t rx_des_ring[NUM_RX_DESC] __attribute__ ((aligned(8)));
103static danube_tx_descriptor_t tx_des_ring[NUM_TX_DESC] __attribute__ ((aligned(8)));
104static int tx_num, rx_num;
105
106int danube_switch_init(struct eth_device *dev, bd_t * bis);
107int danube_switch_send(struct eth_device *dev, volatile void *packet,int length);
108int danube_switch_recv(struct eth_device *dev);
109void danube_switch_halt(struct eth_device *dev);
110static void danube_init_switch_chip(int mode);
111static void danube_dma_init(void);
112
113
114
115int danube_switch_initialize(bd_t * bis)
116{
117        struct eth_device *dev;
118     
119#if 0
120        printf("Entered danube_switch_initialize()\n");
121#endif
122
123        if (!(dev = (struct eth_device *) malloc (sizeof *dev)))
124        {
125                printf("Failed to allocate memory\n");
126                return 0;
127        }
128        memset(dev, 0, sizeof(*dev));
129
130        danube_dma_init();
131        danube_init_switch_chip(REV_MII_MODE);
132       
133#ifdef CLK_OUT2_25MHZ
134       *DANUBE_GPIO_P0_DIR=0x0000ae78;
135       *DANUBE_GPIO_P0_ALTSEL0=0x00008078; 
136       //joelin for Mii-1       *DANUBE_GPIO_P0_ALTSEL1=0x80000080;
137       *DANUBE_GPIO_P0_ALTSEL1=0x80000000; //joelin for Mii-1
138       *DANUBE_CGU_IFCCR=0x00400010;
139       *DANUBE_GPIO_P0_OD=0x0000ae78;
140#endif       
141       
142        /*patch for 6996*/
143       
144        *DANUBE_RCU_RST_REQ |=1;
145        mdelay(200);
146        *DANUBE_RCU_RST_REQ &=(unsigned long)~1; 
147        mdelay(1);
148        /*while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
149        *DANUBE_PPE_ETOP_MDIO_ACC =0x80123602;
150        */
151        /*while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
152        *DANUBE_PPE_ETOP_MDIO_ACC =0x80123602;
153        */
154        /***************/
155        sprintf(dev->name, "danube Switch");
156        dev->init = danube_switch_init;
157        dev->halt = danube_switch_halt;
158        dev->send = danube_switch_send;
159        dev->recv = danube_switch_recv;
160
161        eth_register(dev);
162
163#if 0
164        printf("Leaving danube_switch_initialize()\n");
165#endif
166        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
167        *DANUBE_PPE_ETOP_MDIO_ACC =0x8001840F;
168        while((*DANUBE_PPE_ETOP_MDIO_ACC)&0x80000000);
169        *DANUBE_PPE_ETOP_MDIO_ACC =0x8003840F;
170        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
171        *DANUBE_PPE_ETOP_MDIO_ACC =0x8005840F;
172        //while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
173        //*DANUBE_PPE_ETOP_MDIO_ACC =0x8006840F;
174        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
175        *DANUBE_PPE_ETOP_MDIO_ACC =0x8007840F;
176        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
177        *DANUBE_PPE_ETOP_MDIO_ACC =0x8008840F;
178        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
179        *DANUBE_PPE_ETOP_MDIO_ACC =0x8001840F;
180        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
181        *DANUBE_PPE_ETOP_MDIO_ACC =0x80123602; 
182#ifdef CLK_OUT2_25MHZ         
183        while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000);
184        *DANUBE_PPE_ETOP_MDIO_ACC =0x80334000;
185#endif
186
187        return 1;
188}
189
190int danube_switch_init(struct eth_device *dev, bd_t * bis)
191{
192        int i;
193
194        tx_num=0;
195        rx_num=0;
196       
197                /* Reset DMA
198                 */
199//      serial_puts("i \n\0");
200
201       *DANUBE_DMA_CS=RX_CHAN_NO;
202       *DANUBE_DMA_CCTRL=0x2;/*fix me, need to reset this channel first?*/
203       *DANUBE_DMA_CPOLL= 0x80000040;
204       /*set descriptor base*/
205       *DANUBE_DMA_CDBA=(u32)rx_des_ring;
206       *DANUBE_DMA_CDLEN=NUM_RX_DESC;
207       *DANUBE_DMA_CIE = 0;
208       *DANUBE_DMA_CCTRL=0x30000;
209               
210       *DANUBE_DMA_CS=TX_CHAN_NO;
211       *DANUBE_DMA_CCTRL=0x2;/*fix me, need to reset this channel first?*/
212       *DANUBE_DMA_CPOLL= 0x80000040;
213       *DANUBE_DMA_CDBA=(u32)tx_des_ring;
214       *DANUBE_DMA_CDLEN=NUM_TX_DESC; 
215       *DANUBE_DMA_CIE = 0;
216       *DANUBE_DMA_CCTRL=0x30100;
217       
218        for(i=0;i < NUM_RX_DESC; i++)
219        {
220                danube_rx_descriptor_t * rx_desc = KSEG1ADDR(&rx_des_ring[i]);
221                rx_desc->status.word=0; 
222                rx_desc->status.field.OWN=1;
223                rx_desc->status.field.DataLen=PKTSIZE_ALIGN;   /* 1536  */     
224                rx_desc->DataPtr=(u32)KSEG1ADDR(NetRxPackets[i]);
225        }
226
227        for(i=0;i < NUM_TX_DESC; i++)
228        {
229                danube_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_des_ring[i]);
230                memset(tx_desc, 0, sizeof(tx_des_ring[0]));
231        }
232                /* turn on DMA rx & tx channel
233                 */
234         *DANUBE_DMA_CS=RX_CHAN_NO;
235         *DANUBE_DMA_CCTRL|=1;/*reset and turn on the channel*/
236       
237        return 0;
238}
239
240void danube_switch_halt(struct eth_device *dev)
241{
242        int i; 
243                for(i=0;i<8;i++)
244        {
245           *DANUBE_DMA_CS=i;
246           *DANUBE_DMA_CCTRL&=~1;/*stop the dma channel*/
247        }
248//      udelay(1000000);
249}
250
251int danube_switch_send(struct eth_device *dev, volatile void *packet,int length)
252{
253
254        int                     i;
255        int                     res = -1;
256
257        danube_tx_descriptor_t * tx_desc= KSEG1ADDR(&tx_des_ring[tx_num]);
258       
259        if (length <= 0)
260        {
261                printf ("%s: bad packet size: %d\n", dev->name, length);
262                goto Done;
263        }
264       
265        for(i=0; tx_desc->status.field.OWN==1; i++)
266        {
267                if(i>=TOUT_LOOP)
268                {
269                        printf("NO Tx Descriptor...");
270                        goto Done;
271                }
272        }
273
274        //serial_putc('s');
275
276        tx_desc->status.field.Sop=1;
277        tx_desc->status.field.Eop=1;
278        tx_desc->status.field.C=0;
279        tx_desc->DataPtr = (u32)KSEG1ADDR(packet);
280        if(length<60)
281                tx_desc->status.field.DataLen = 60;
282        else
283                tx_desc->status.field.DataLen = (u32)length;   
284       
285        asm("SYNC");
286        tx_desc->status.field.OWN=1;
287                               
288        res=length;
289        tx_num++;
290        if(tx_num==NUM_TX_DESC) tx_num=0;
291        *DANUBE_DMA_CS=TX_CHAN_NO;
292         
293        if(!(*DANUBE_DMA_CCTRL & 1))
294        *DANUBE_DMA_CCTRL|=1;
295       
296Done:
297        return res;
298}
299
300int danube_switch_recv(struct eth_device *dev)
301{
302
303        int                    length  = 0;
304
305        danube_rx_descriptor_t * rx_desc;
306        int anchor_num=0;
307        int i;
308        for (;;)
309        {
310                rx_desc = KSEG1ADDR(&rx_des_ring[rx_num]);
311
312                if ((rx_desc->status.field.C == 0) || (rx_desc->status.field.OWN == 1))
313                {
314                   break;
315                }
316                 
317               
318                length = rx_desc->status.field.DataLen;
319                if (length)
320                {               
321                        NetReceive((void*)KSEG1ADDR(NetRxPackets[rx_num]), length - 4);
322                //      serial_putc('*');
323                }
324                else
325                {
326                        printf("Zero length!!!\n");
327                }
328
329                rx_desc->status.field.Sop=0;
330                rx_desc->status.field.Eop=0;
331                rx_desc->status.field.C=0;
332                rx_desc->status.field.DataLen=PKTSIZE_ALIGN;
333                rx_desc->status.field.OWN=1;
334                rx_num++;
335                if(rx_num==NUM_RX_DESC) rx_num=0;
336
337        }
338
339        return length;
340}
341
342
343static void danube_init_switch_chip(int mode)
344{
345        int i;
346        /*get and set mac address for MAC*/
347        static unsigned char addr[6];
348        char *tmp,*end; 
349        tmp = getenv ("ethaddr");
350        if (NULL == tmp) {
351                printf("Can't get environment ethaddr!!!\n");
352        //      return NULL;
353        } else {
354                printf("ethaddr=%s\n", tmp);
355        }
356        *DANUBE_PMU_PWDCR = *DANUBE_PMU_PWDCR & 0xFFFFEFDF;
357        *DANUBE_PPE32_ETOP_MDIO_CFG &= ~0x6;
358        *DANUBE_PPE32_ENET_MAC_CFG = 0x187;
359 
360  // turn on port0, set to rmii and turn off port1.
361        if(mode==REV_MII_MODE)
362                {
363                 *DANUBE_PPE32_ETOP_CFG = (*DANUBE_PPE32_ETOP_CFG & 0xfffffffc) | 0x0000000a;
364                } 
365        else if (mode == MII_MODE)
366                {
367                *DANUBE_PPE32_ETOP_CFG = (*DANUBE_PPE32_ETOP_CFG & 0xfffffffc) | 0x00000008;
368                }         
369
370        *DANUBE_PPE32_ETOP_IG_PLEN_CTRL = 0x4005ee; // set packetlen.
371        *ENET_MAC_CFG|=1<<11;/*enable the crc*/
372        return;
373}
374
375
376static void danube_dma_init(void)
377{
378        int i;
379//      serial_puts("d \n\0");
380
381        *DANUBE_PMU_PWDCR &=~(1<<DANUBE_PMU_DMA_SHIFT);/*enable DMA from PMU*/
382                /* Reset DMA
383                 */
384        *DANUBE_DMA_CTRL|=1; 
385        *DANUBE_DMA_IRNEN=0;/*disable all the interrupts first*/
386
387        /* Clear Interrupt Status Register               
388        */
389        *DANUBE_DMA_IRNCR=0xfffff;
390        /*disable all the dma interrupts*/
391        *DANUBE_DMA_IRNEN=0;
392        /*disable channel 0 and channel 1 interrupts*/
393       
394          *DANUBE_DMA_CS=RX_CHAN_NO;
395          *DANUBE_DMA_CCTRL=0x2;/*fix me, need to reset this channel first?*/
396          *DANUBE_DMA_CPOLL= 0x80000040;
397          /*set descriptor base*/
398          *DANUBE_DMA_CDBA=(u32)rx_des_ring;
399          *DANUBE_DMA_CDLEN=NUM_RX_DESC;
400          *DANUBE_DMA_CIE = 0;
401          *DANUBE_DMA_CCTRL=0x30000;
402               
403        *DANUBE_DMA_CS=TX_CHAN_NO;
404        *DANUBE_DMA_CCTRL=0x2;/*fix me, need to reset this channel first?*/
405        *DANUBE_DMA_CPOLL= 0x80000040;
406        *DANUBE_DMA_CDBA=(u32)tx_des_ring;
407        *DANUBE_DMA_CDLEN=NUM_TX_DESC; 
408        *DANUBE_DMA_CIE = 0;
409        *DANUBE_DMA_CCTRL=0x30100;
410        /*enable the poll function and set the poll counter*/
411        //*DANUBE_DMA_CPOLL=DANUBE_DMA_POLL_EN | (DANUBE_DMA_POLL_COUNT<<4);
412        /*set port properties, enable endian conversion for switch*/
413        *DANUBE_DMA_PS=0;
414        *DANUBE_DMA_PCTRL|=0xf<<8;/*enable 32 bit endian conversion*/
415
416        return;
417}
418
419
420
421
422
423#endif
Note: See TracBrowser for help on using the repository browser.