OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [boot-loader-ethmac/] [ethmac.c] - Blame information for rev 80

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 61 csantifort
/*----------------------------------------------------------------
2
//                                                              //
3
//  boot-loader-ethmac.c                                        //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  The main functions for the boot loader application. This    //
10 78 csantifort
//  application is embedded in the FPGA's SRAM and is used      //
11 61 csantifort
//  to load larger applications into the DDR3 memory on         //
12
//  the development board.                                      //
13
//                                                              //
14
//  Author(s):                                                  //
15
//      - Conor Santifort, csantifort.amber@gmail.com           //
16
//                                                              //
17
//////////////////////////////////////////////////////////////////
18
//                                                              //
19
// Copyright (C) 2011 Authors and OPENCORES.ORG                 //
20
//                                                              //
21
// This source file may be used and distributed without         //
22
// restriction provided that this copyright statement is not    //
23
// removed from the file and that any derivative work contains  //
24
// the original copyright notice and the associated disclaimer. //
25
//                                                              //
26
// This source file is free software; you can redistribute it   //
27
// and/or modify it under the terms of the GNU Lesser General   //
28
// Public License as published by the Free Software Foundation; //
29
// either version 2.1 of the License, or (at your option) any   //
30
// later version.                                               //
31
//                                                              //
32
// This source is distributed in the hope that it will be       //
33
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
34
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
35
// PURPOSE.  See the GNU Lesser General Public License for more //
36
// details.                                                     //
37
//                                                              //
38
// You should have received a copy of the GNU Lesser General    //
39
// Public License along with this source; if not, download it   //
40
// from http://www.opencores.org/lgpl.shtml                     //
41
//                                                              //
42
----------------------------------------------------------------*/
43
 
44
 
45
#include "amber_registers.h"
46
#include "address_map.h"
47
#include "timer.h"
48
#include "utilities.h"
49
#include "line-buffer.h"
50
#include "packet.h"
51
#include "ethmac.h"
52
 
53
 
54 80 csantifort
/* open a link */
55
void init_ethmac()
56 61 csantifort
{
57 80 csantifort
    /* initialize the packet rx buffer */
58
    init_packet();
59 78 csantifort
 
60 80 csantifort
    /* open ethernet port and wait for connection requests
61
       keep trying forever */
62
    while (!open_link());
63
}
64 78 csantifort
 
65
 
66 61 csantifort
 
67
/* return 1 if link comes up */
68
int open_link (void)
69
{
70
    int packet;
71
    int n;
72
    unsigned int d32;
73 78 csantifort
 
74 61 csantifort
    /* Disable Ethmac interrupt in interrupt controller */
75
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
76
 
77
    /* Set my MAC address */
78
    d32 = self_g.mac[2]<<24|self_g.mac[3]<<16|self_g.mac[4]<<8|self_g.mac[5];
79
    *(unsigned int *) ( ADR_ETHMAC_MAC_ADDR0 ) = d32;
80 78 csantifort
 
81 61 csantifort
    d32 = self_g.mac[0]<<8|self_g.mac[1];
82
    *(unsigned int *) ( ADR_ETHMAC_MAC_ADDR1 ) = d32;
83 78 csantifort
 
84 80 csantifort
    if (!init_phy())
85
        return 0;
86 61 csantifort
 
87
    /* Write the Receive Packet Buffer Descriptor */
88
    /* Buffer Pointer */
89
    for (packet=0; packet<ETHMAC_RX_BUFFERS; packet++) {
90
        *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x204 + packet*8 ) = ETHMAC_RX_BUFFER + packet * 0x1000;
91 78 csantifort
        /* Ready Rx buffer
92
           [31:16] = length in bytes,
93 61 csantifort
           [15] = empty
94
           [14] = Enable IRQ
95
           [13] = wrap bit */
96
        /* set empty flag again */
97
        if (packet == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
98 78 csantifort
            /* Set wrap bit is last buffer */
99 61 csantifort
            *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + packet*8 ) = 0x0000e000;
100
        else
101
            *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + packet*8 ) = 0x0000c000;
102
        }
103
 
104 78 csantifort
 
105 61 csantifort
    /* Enable EthMac interrupts in Ethmac core */
106
    /* Receive frame and receive error botgh enabled */
107
    /* When a bad frame is received is still gets written to a buffer
108
       so needs to be dealt with */
109
    *(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0xc;
110 78 csantifort
 
111 61 csantifort
    /* Enable Ethmac interrupt in interrupt controller */
112
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
113 78 csantifort
 
114 61 csantifort
    /* Set transmit packet buffer location */
115
    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 4 ) = ETHMAC_TX_BUFFER;
116 78 csantifort
 
117 61 csantifort
    /* Set the ready bit, bit 15, low */
118
    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0 ) = 0x7800;
119
 
120
    /* Enable Rx & Tx - MODER Register
121
     [15] = Add pads to short frames
122
     [13] = CRCEN
123
     [10] = Enable full duplex
124
     [7]  = loopback
125
     [5]  = 1 for promiscuous, 0 rx only frames that match mac address
126
     [1]  = txen
127
     [0]  = rxen  */
128
    *(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa423;
129 78 csantifort
 
130 61 csantifort
    return 1;
131
}
132
 
133
 
134 80 csantifort
 
135
void close_link (void)
136
{
137
    /* Disable EthMac interrupts in Ethmac core */
138
    *(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0x0;
139
 
140
    /* Disable Ethmac interrupt in interrupt controller */
141
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
142
 
143
    /* Disable Rx & Tx - MODER Register
144
     [15] = Add pads to short frames
145
     [13] = CRCEN
146
     [10] = Enable full duplex
147
     [7]  = loopback
148
     [5]  = 1 for promiscuous, 0 rx only frames that match mac address
149
     [1]  = txen
150
     [0]  = rxen  */
151
    *(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa420;
152
 
153
    /* Put the PHY into reset */
154
    phy_rst(0);  /* reset is active low */
155
 
156
}
157
 
158
 
159 61 csantifort
void tx_packet(int len)
160
{
161
    unsigned int status = 0;
162 78 csantifort
 
163
 
164 61 csantifort
    /* Poll the ready bit.
165
       Wait until the ready bit is cleared by the ethmac hardware
166
       This holds everything up while the packet is being transmitted, but
167
       it keeps things simple. */
168
    status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0 );
169
    while ((status & 0x8000) != 0) {
170
        udelay20();
171
        status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0 );
172
        }
173
 
174
 
175
    /* Enable packet tx
176 78 csantifort
       [31:16] = length in bytes,
177 61 csantifort
       [15] = ready
178
       [14] = tx int
179 78 csantifort
       [13] = wrap bit
180 61 csantifort
       [12] = pad enable for short packets
181
       [11] = crc en
182
    */
183
    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0 ) = len<<16 | 0xf800;
184
}
185
 
186
 
187
/* returns 1 if link comes up */
188 80 csantifort
int init_phy (void)
189 61 csantifort
{
190
    int addr;
191
    int bmcr;
192
    int stat;
193
    int phy_id;
194
    int link_up = 1;
195 78 csantifort
    time_t* link_timer;
196 61 csantifort
 
197 80 csantifort
    link_timer = new_timer();
198 78 csantifort
 
199 61 csantifort
    /* Bring PHY out of reset */
200
    phy_rst(1);  /* reset is active low */
201 78 csantifort
 
202 61 csantifort
    /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
203
    for(addr = 0; addr < 32; addr++) {
204
            phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
205
            bmcr = mdio_read(phy_id, MII_BMCR);  /* Basic Mode Control Register */
206
            stat = mdio_read(phy_id, MII_BMSR);
207
            stat = mdio_read(phy_id, MII_BMSR);
208
            if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
209 78 csantifort
                break;
210 61 csantifort
    }
211 78 csantifort
    /* Failed to find a PHY on the md bus */
212
    if (addr == 32)
213
        return 0;
214
 
215 61 csantifort
    /* Reset PHY */
216
    bmcr = mdio_read(phy_id, MII_BMCR);
217
    mdio_write(phy_id, MII_BMCR, bmcr | BMCR_RESET);
218
 
219
    /* Advertise that PHY is NOT B1000-T capable */
220
    /* Set bits 9.8, 9.9 to 0 */
221
    bmcr = mdio_read(phy_id, MII_CTRL1000);
222
    mdio_write(phy_id, MII_CTRL1000, bmcr & 0xfcff );
223 78 csantifort
 
224 61 csantifort
    /* Restart autoneg */
225
    bmcr = mdio_read(phy_id, MII_BMCR);
226
    mdio_write(phy_id, MII_BMCR, bmcr | BMCR_ANRESTART);
227 78 csantifort
 
228 61 csantifort
    /* Wait for link up */
229
    /* Print PHY status MII_BMSR = Basic Mode Status Register*/
230 78 csantifort
    /* allow a few seconds for the link to come up before giving up */
231
    set_timer(link_timer, 5000);
232
 
233 61 csantifort
    while (!((stat = mdio_read(phy_id, MII_BMSR)) & BMSR_LSTATUS)) {
234
        if (timer_expired(link_timer)) {
235 78 csantifort
            link_up = 0;
236
            break;
237 61 csantifort
            }
238
        }
239 78 csantifort
 
240 61 csantifort
    return link_up;
241
}
242
 
243
 
244
int mdio_read(int addr, int reg)
245
{
246
    return mdio_ctrl(addr, mdi_read, reg, 0);
247
}
248
 
249
 
250
void mdio_write(int addr, int reg, int data)
251
{
252
    mdio_ctrl(addr, mdi_write, reg, data);
253
}
254
 
255
 
256
/*
257
 addr = PHY address
258 78 csantifort
 reg  = register address within PHY
259 61 csantifort
 */
260
unsigned short mdio_ctrl(unsigned int addr, unsigned int dir, unsigned int reg, unsigned short data)
261
{
262
    unsigned int data_out = 0;
263
    unsigned int i;
264
    unsigned long flags;
265
 
266 78 csantifort
    mdio_ready();
267
 
268 61 csantifort
    *(volatile unsigned int *)(ADR_ETHMAC_MIIADDRESS) = (reg << 8) | (addr & 0x1f);
269
 
270 78 csantifort
    if (dir == mdi_write) {
271
        *(volatile unsigned int *)(ADR_ETHMAC_MIITXDATA) = data;
272
        /* Execute Write ! */
273
        *(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x4;
274
    }
275
    else {
276
        /* Execute Read ! */
277
        *(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x2;
278
        mdio_ready();
279
        data_out = *(volatile unsigned int *)(ADR_ETHMAC_MIIRXDATA);
280
    }
281
 
282 61 csantifort
    return (unsigned short) data_out;
283
}
284
 
285
 
286
/* Wait until its ready */
287
void mdio_ready()
288 78 csantifort
{
289 61 csantifort
    int i;
290
    for (;;) {
291 78 csantifort
        /* Bit 1 is high when the MD i/f is busy */
292
        if ((*(volatile unsigned int *)(ADR_ETHMAC_MIISTATUS) & 0x2) == 0x0)
293 61 csantifort
            break;
294 78 csantifort
 
295 61 csantifort
        i++;
296
        if (i==10000000) {
297
            i=0;
298
            }
299
        }
300
}
301
 
302
 
303
 
304
void ethmac_interrupt(void)
305 78 csantifort
{
306 61 csantifort
    int buffer;
307
    unsigned int int_src;
308
    unsigned int rx_buf_status;
309 78 csantifort
 
310 61 csantifort
    /* Mask ethmac interrupts */
311
    *(volatile unsigned int *) ( ADR_ETHMAC_INT_MASK   ) = 0;
312 78 csantifort
 
313 61 csantifort
    int_src = *(volatile unsigned int *) ( ADR_ETHMAC_INT_SOURCE );
314 78 csantifort
 
315
    if (int_src) {
316
        for (buffer=0; buffer<ETHMAC_RX_BUFFERS; buffer++) {
317
 
318
           rx_buf_status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 );
319
 
320
           if ((rx_buf_status & 0x8000) == 0) {
321
                parse_rx_packet((char*)(ETHMAC_RX_BUFFER+buffer*0x1000), rx_packet_g);
322
 
323
                /* set empty flag again */
324
                if (buffer == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
325
                    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000e000;
326
                else
327
                    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000c000;
328
                }
329 61 csantifort
            }
330
        }
331
 
332
    /* Clear all ethmac interrupts */
333
    *(volatile unsigned int *) ( ADR_ETHMAC_INT_SOURCE ) = int_src;
334
 
335
    /* UnMask ethmac interrupts */
336
    *(volatile unsigned int *) ( ADR_ETHMAC_INT_MASK   ) = 0xc;
337
}
338
 
339
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.