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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [software/] [greth/] [greth_api.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
/*****************************************************************************/
2
/*   This file is a part of the GRLIB VHDL IP LIBRARY                        */
3
/*   Copyright (C) 2007 GAISLER RESEARCH                                     */
4
/*                                                                           */
5
/*   This program is free software; you can redistribute it and/or modify    */
6
/*   it under the terms of the GNU General Public License as published by    */
7
/*   the Free Software Foundation; either version 2 of the License, or       */
8
/*   (at your option) any later version.                                     */
9
/*                                                                           */
10
/*   See the file COPYING for the full details of the license.               */
11
/*****************************************************************************/
12
 
13
/* Changelog */
14
/* 2008-02-01: GRETH API separated from test  - Marko Isomaki */
15
 
16
#include "greth_api.h"
17
 
18
/* Bypass cache load  */
19
static inline int load(int addr)
20
{
21
    int tmp;
22
    asm(" lda [%1]1, %0 "
23
        : "=r"(tmp)
24
        : "r"(addr)
25
        );
26
    return tmp;
27
}
28
 
29
static inline int save(unsigned int addr, unsigned int data)
30
{
31
    *((volatile unsigned int *)addr) = data;
32
}
33
 
34
/* Allocate memory aligned to the size */
35
static char *almalloc(int sz)
36
{
37
    char *tmp;
38
    tmp = calloc(1,2*sz);
39
    tmp = (char *) (((int)tmp+sz) & ~(sz -1));
40
    return(tmp);
41
}
42
 
43
int read_mii(int phyaddr, int addr, volatile greth_regs *regs)
44
{
45
    unsigned int tmp;
46
 
47
    do {
48
        tmp = load((int)&regs->mdio);
49
    } while (tmp & GRETH_MII_BUSY);
50
 
51
    tmp = (phyaddr << 11) | ((addr&0x1F) << 6) | 2;
52
    save((int)&regs->mdio, tmp);
53
 
54
    do {
55
        tmp = load((int)&regs->mdio);
56
    } while (tmp & GRETH_MII_BUSY);
57
 
58
    if (!(tmp & GRETH_MII_NVALID)) {
59
        tmp = load((int)&regs->mdio);
60
        return (tmp>>16)&0xFFFF;
61
    }
62
    else {
63
        /* printf("GRETH: failed to read mii\n"); */
64
        return -1;
65
    }
66
}
67
 
68
void write_mii(int phyaddr, int addr, int data, volatile greth_regs *regs)
69
{
70
    unsigned int tmp;
71
 
72
    do {
73
        tmp = load((int)&regs->mdio);
74
    } while (tmp & GRETH_MII_BUSY);
75
 
76
    tmp = ((data&0xFFFF)<<16) | (phyaddr << 11) | ((addr&0x1F) << 6) | 1;
77
 
78
    save((int)&regs->mdio, tmp);
79
 
80
    do {
81
        tmp = load((int)&regs->mdio);
82
    } while (tmp & GRETH_MII_BUSY);
83
 
84
}
85
 
86
int greth_set_mac_address(struct greth_info *greth, unsigned char *addr)
87
{
88
    greth->esa[0] = addr[0];
89
    greth->esa[1] = addr[1];
90
    greth->esa[2] = addr[2];
91
    greth->esa[3] = addr[3];
92
    greth->esa[4] = addr[4];
93
    greth->esa[5] = addr[5];
94
    save((int)&greth->regs->esa_msb, addr[0] << 8 | addr[1]);
95
    save((int)&greth->regs->esa_lsb, addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5]);
96
    return 1;
97
}
98
 
99
int greth_init(struct greth_info *greth) {
100
 
101
    unsigned int tmp;
102
    int i;
103
    int duplex, speed;
104
    int gbit;
105
 
106
    tmp = load((int)&greth->regs->control);
107
    greth->gbit = (tmp >> 27) & 1;
108
    greth->edcl = (tmp >> 31) & 1;
109
 
110
    if (greth->edcl == 0) {
111
            /* Reset the controller. */
112
            save((int)&greth->regs->control, GRETH_RESET);
113
 
114
            do {
115
                    tmp = load((int)&greth->regs->control);
116
            } while (tmp & GRETH_RESET);
117
    }
118
 
119
    /* Get the phy address which assumed to have been set
120
     * correctly with the reset value in hardware
121
     */
122
    tmp = load((int)&greth->regs->mdio);
123
    greth->phyaddr = ((tmp >> 11) & 0x1F);
124
 
125
    greth->txd = (struct descriptor *) almalloc(1024);
126
    greth->rxd = (struct descriptor *) almalloc(1024);
127
    save((int)&greth->regs->tx_desc_p, (unsigned int) greth->txd);
128
    save((int)&greth->regs->rx_desc_p, (unsigned int) greth->rxd);
129
 
130
    /* Reset PHY */
131
    if (greth->edcl == 0) {
132
            write_mii(greth->phyaddr, 0, 0x8000, greth->regs);
133
            while ( (tmp=read_mii(greth->phyaddr,0, greth->regs)) & 0x8000)
134
                    ;
135
            i = 0;
136
            if (tmp & 0x1000) { /* auto neg */
137
                    while ( !(read_mii(greth->phyaddr,1, greth->regs) & 0x20 ) ) {
138
                            i++;
139
                            if (i > 50000) {
140
                                    /* printf("Auto-negotiation failed\n"); */
141
                                    break;
142
                            }
143
                    }
144
            }
145
            tmp = read_mii(greth->phyaddr, 0, greth->regs);
146
 
147
            if (greth->gbit && !(tmp >> 13) && (tmp >> 6)) {
148
                    gbit = 1; speed = 0;
149
            } else if ((tmp >> 13) && !(tmp >> 6)) {
150
                    gbit = 0; speed = 1;
151
            } else if (!(tmp >> 13) && !(tmp >> 6)) {
152
                    gbit = 0; speed = 0;
153
            }
154
            duplex = (tmp >> 8) & 1;
155
 
156
            save((int)&greth->regs->control, (duplex << 4) || (speed << 7) || (gbit << 8));
157
    } else {
158
            /* wait for edcl phy initialisation to finish */
159
            i = 0;
160
 
161
            while (i < 3) {
162
                    tmp = load((int)&greth->regs->mdio);
163
                    if ((tmp >> 3) & 1) {
164
                            i = 0;
165
                    } else {
166
                            i++;
167
                    }
168
            }
169
 
170
 
171
    }
172
 
173
 
174
 
175
 
176
    /* printf("GRETH(%s) Ethernet MAC at [0x%x]. Running %d Mbps %s duplex\n", greth->gbit?"10/100/1000":"10/100" , \ */
177
/*                                                          (unsigned int)(greth->regs),  \ */
178
/*                                                          (speed == 0x2000) ? 100:10, duplex ? "full":"half"); */
179
 
180
    greth_set_mac_address(greth, greth->esa);
181
 
182
}
183
 
184
inline int greth_tx(int size, char *buf, struct greth_info *greth)
185
{
186
    if ((load((int)&(greth->txd[greth->txpnt].ctrl)) >> 11) & 1) {
187
        return 0;
188
    }
189
 
190
    greth->txd[greth->txpnt].addr = (int) buf;
191
 
192
    if (greth->txpnt == 127) {
193
        greth->txd[greth->txpnt].ctrl =  GRETH_BD_WR | GRETH_BD_EN | size;
194
        greth->txpnt = 0;
195
    } else {
196
        greth->txd[greth->txpnt].ctrl = GRETH_BD_EN | size;
197
        greth->txpnt++;
198
    }
199
 
200
    greth->regs->control = load((int)&(greth->regs->control)) | GRETH_TXEN;
201
 
202
    return 1;
203
}
204
 
205
inline int greth_rx(char *buf, struct greth_info *greth)
206
{
207
    if (((load((int)&(greth->rxd[greth->rxpnt].ctrl)) >> 11) & 1)) {
208
        return 0;
209
    }
210
    greth->rxd[greth->rxpnt].addr = (int)buf;
211
    if (greth->rxpnt == 127) {
212
        greth->rxd[greth->rxpnt].ctrl = GRETH_BD_WR | GRETH_BD_EN;
213
        greth->rxpnt = 0;
214
    } else {
215
        greth->rxd[greth->rxpnt].ctrl = GRETH_BD_EN;
216
        greth->rxpnt++;
217
    }
218
    greth->regs->control = load((int)&(greth->regs->control)) | GRETH_RXEN;
219
    return 1;
220
}
221
 
222
inline int greth_checkrx(int *size, struct rxstatus *rxs, struct greth_info *greth)
223
{
224
    int tmp;
225
    tmp = load((int)&(greth->rxd[greth->rxchkpnt].ctrl));
226
    if (!((tmp >> 11) & 1)) {
227
        *size = tmp & GRETH_BD_LEN;
228
        if (greth->rxchkpnt == 127) {
229
            greth->rxchkpnt = 0;
230
        } else {
231
            greth->rxchkpnt++;
232
        }
233
        return 1;
234
    } else {
235
        return 0;
236
    }
237
}
238
 
239
inline int greth_checktx(struct greth_info *greth)
240
{
241
  int tmp;
242
  tmp = load((int)&(greth->txd[greth->txchkpnt].ctrl));
243
  if (!((tmp >> 11) & 1)) {
244
    if (greth->txchkpnt == 127) {
245
      greth->txchkpnt = 0;
246
    } else {
247
      greth->txchkpnt++;
248
    }
249
    return 1;
250
  } else {
251
      return 0;
252
  }
253
}

powered by: WebSVN 2.1.0

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