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

Subversion Repositories amber

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

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
//  application is embedded in the FPGA's SRAM and is used      //
11
//  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
void close_link (void)
55
{
56
    /* Disable EthMac interrupts in Ethmac core */
57
    *(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0x0;
58
 
59
    /* Disable Ethmac interrupt in interrupt controller */
60
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
61
 
62
    /* Disable Rx & Tx - MODER Register
63
     [15] = Add pads to short frames
64
     [13] = CRCEN
65
     [10] = Enable full duplex
66
     [7]  = loopback
67
     [5]  = 1 for promiscuous, 0 rx only frames that match mac address
68
     [1]  = txen
69
     [0]  = rxen  */
70
    *(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa420;
71
 
72
    /* Put the PHY into reset */
73
    phy_rst(0);  /* reset is active low */
74
 
75
}
76
 
77
 
78
/* return 1 if link comes up */
79
int open_link (void)
80
{
81
    int packet;
82
    int n;
83
    unsigned int d32;
84
 
85
    /* Disable Ethmac interrupt in interrupt controller */
86
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
87
 
88
    /* Set my MAC address */
89
    d32 = self_g.mac[2]<<24|self_g.mac[3]<<16|self_g.mac[4]<<8|self_g.mac[5];
90
    *(unsigned int *) ( ADR_ETHMAC_MAC_ADDR0 ) = d32;
91
 
92
    d32 = self_g.mac[0]<<8|self_g.mac[1];
93
    *(unsigned int *) ( ADR_ETHMAC_MAC_ADDR1 ) = d32;
94
 
95
    if (!config_phy()) return 0;
96
 
97
    /* Write the Receive Packet Buffer Descriptor */
98
    /* Buffer Pointer */
99
    for (packet=0; packet<ETHMAC_RX_BUFFERS; packet++) {
100
        *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x204 + packet*8 ) = ETHMAC_RX_BUFFER + packet * 0x1000;
101
        /* Ready Rx buffer
102
           [31:16] = length in bytes,
103
           [15] = empty
104
           [14] = Enable IRQ
105
           [13] = wrap bit */
106
        /* set empty flag again */
107
        if (packet == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
108
            /* Set wrap bit is last buffer */
109
            *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + packet*8 ) = 0x0000e000;
110
        else
111
            *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + packet*8 ) = 0x0000c000;
112
        }
113
 
114
    /* Enable EthMac interrupts in Ethmac core */
115
    /* Receive frame and receive error botgh enabled */
116
    /* When a bad frame is received is still gets written to a buffer
117
       so needs to be dealt with */
118
    *(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0xc;
119
 
120
    /* Enable Ethmac interrupt in interrupt controller */
121
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
122
 
123
    /* Set transmit packet buffer location */
124
    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 4 ) = ETHMAC_TX_BUFFER;
125
 
126
    /* Set the ready bit, bit 15, low */
127
    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0 ) = 0x7800;
128
 
129
    /* Enable Rx & Tx - MODER Register
130
     [15] = Add pads to short frames
131
     [13] = CRCEN
132
     [10] = Enable full duplex
133
     [7]  = loopback
134
     [5]  = 1 for promiscuous, 0 rx only frames that match mac address
135
     [1]  = txen
136
     [0]  = rxen  */
137
    *(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa423;
138
 
139
    return 1;
140
}
141
 
142
 
143
void tx_packet(int len)
144
{
145
    unsigned int status = 0;
146
 
147
 
148
    /* Poll the ready bit.
149
       Wait until the ready bit is cleared by the ethmac hardware
150
       This holds everything up while the packet is being transmitted, but
151
       it keeps things simple. */
152
    status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0 );
153
    while ((status & 0x8000) != 0) {
154
        udelay20();
155
        status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0 );
156
        }
157
 
158
 
159
    /* Enable packet tx
160
       [31:16] = length in bytes,
161
       [15] = ready
162
       [14] = tx int
163
       [13] = wrap bit
164
       [12] = pad enable for short packets
165
       [11] = crc en
166
    */
167
    *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0 ) = len<<16 | 0xf800;
168
}
169
 
170
 
171
/* returns 1 if link comes up */
172
int config_phy (void)
173
{
174
    int addr;
175
    int bmcr;
176
    int stat;
177
    int phy_id;
178
    int link_up = 1;
179
 
180
    time_t* link_timer;
181
 
182
    link_timer = init_timer();
183
 
184
    /* Bring PHY out of reset */
185
    phy_rst(1);  /* reset is active low */
186
 
187
    /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
188
    for(addr = 0; addr < 32; addr++) {
189
            phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
190
            bmcr = mdio_read(phy_id, MII_BMCR);  /* Basic Mode Control Register */
191
            stat = mdio_read(phy_id, MII_BMSR);
192
            stat = mdio_read(phy_id, MII_BMSR);
193
            if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
194
                    break;
195
    }
196
 
197
    /* Reset PHY */
198
    bmcr = mdio_read(phy_id, MII_BMCR);
199
    mdio_write(phy_id, MII_BMCR, bmcr | BMCR_RESET);
200
 
201
    /* Advertise that PHY is NOT B1000-T capable */
202
    /* Set bits 9.8, 9.9 to 0 */
203
    bmcr = mdio_read(phy_id, MII_CTRL1000);
204
    mdio_write(phy_id, MII_CTRL1000, bmcr & 0xfcff );
205
 
206
    /* Restart autoneg */
207
    bmcr = mdio_read(phy_id, MII_BMCR);
208
    mdio_write(phy_id, MII_BMCR, bmcr | BMCR_ANRESTART);
209
 
210
    /* Wait for link up */
211
    /* Print PHY status MII_BMSR = Basic Mode Status Register*/
212
    /* allow 2 seconds for the link to come up before giving up */
213
    set_timer(link_timer, 5000);
214
    while (!((stat = mdio_read(phy_id, MII_BMSR)) & BMSR_LSTATUS)) {
215
        if (timer_expired(link_timer)) {
216
            link_up = 0;
217
            break;
218
            }
219
        }
220
 
221
    return link_up;
222
}
223
 
224
 
225
int mdio_read(int addr, int reg)
226
{
227
    return mdio_ctrl(addr, mdi_read, reg, 0);
228
}
229
 
230
 
231
void mdio_write(int addr, int reg, int data)
232
{
233
    mdio_ctrl(addr, mdi_write, reg, data);
234
}
235
 
236
 
237
/*
238
 addr = PHY address
239
 reg  = register address within PHY
240
 */
241
unsigned short mdio_ctrl(unsigned int addr, unsigned int dir, unsigned int reg, unsigned short data)
242
{
243
    unsigned int data_out = 0;
244
    unsigned int i;
245
    unsigned long flags;
246
 
247
    mdio_ready();
248
 
249
    *(volatile unsigned int *)(ADR_ETHMAC_MIIADDRESS) = (reg << 8) | (addr & 0x1f);
250
 
251
    if (dir == mdi_write) {
252
        *(volatile unsigned int *)(ADR_ETHMAC_MIITXDATA) = data;
253
        /* Execute Write ! */
254
        *(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x4;
255
    }
256
    else {
257
        /* Execute Read ! */
258
        *(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x2;
259
        mdio_ready();
260
        data_out = *(volatile unsigned int *)(ADR_ETHMAC_MIIRXDATA);
261
    }
262
 
263
    return (unsigned short) data_out;
264
}
265
 
266
 
267
/* Wait until its ready */
268
void mdio_ready()
269
{
270
    int i;
271
    for (;;) {
272
        /* Bit 1 is high when the MD i/f is busy */
273
        if ((*(volatile unsigned int *)(ADR_ETHMAC_MIISTATUS) & 0x2) == 0x0)
274
            break;
275
 
276
        i++;
277
        if (i==10000000) {
278
            i=0;
279
            }
280
        }
281
}
282
 
283
 
284
 
285
void ethmac_interrupt(void)
286
{
287
    int buffer;
288
    unsigned int int_src;
289
    unsigned int rx_buf_status;
290
 
291
    /* Mask ethmac interrupts */
292
    *(volatile unsigned int *) ( ADR_ETHMAC_INT_MASK   ) = 0;
293
 
294
    int_src = *(volatile unsigned int *) ( ADR_ETHMAC_INT_SOURCE );
295
 
296
    for (buffer=0; buffer<ETHMAC_RX_BUFFERS; buffer++) {
297
 
298
       rx_buf_status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 );
299
 
300
       if ((rx_buf_status & 0x8000) == 0) {
301
 
302
            parse_rx_packet((char*)(ETHMAC_RX_BUFFER+buffer*0x1000), rx_packet_g);
303
 
304
            /* set empty flag again */
305
            if (buffer == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
306
                *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000e000;
307
            else
308
                *(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000c000;
309
            }
310
        }
311
 
312
    /* Clear all ethmac interrupts */
313
    *(volatile unsigned int *) ( ADR_ETHMAC_INT_SOURCE ) = int_src;
314
 
315
    /* UnMask ethmac interrupts */
316
    *(volatile unsigned int *) ( ADR_ETHMAC_INT_MASK   ) = 0xc;
317
}
318
 
319
 

powered by: WebSVN 2.1.0

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