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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [eth/] [powerpc/] [adder/] [current/] [src/] [adder_eth.c] - Blame information for rev 817

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

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      adder_eth.c
4
//
5
//      Ethernet device driver specifics for Analogue & Micro Adder (PPC850)
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    gthomas
43
// Contributors: gthomas
44
// Date:         2002-11-25
45
// Purpose:      
46
// Description:  platform driver specifics for A&M Adder
47
//              
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
// Ethernet device driver support for PHY on Adder/MPC850
54
 
55
#include <pkgconf/system.h>
56
#include <cyg/infra/cyg_type.h>
57
#include <cyg/infra/diag.h>
58
 
59
#include <cyg/hal/hal_arch.h>
60
#include <cyg/hal/hal_cache.h>
61
#include <cyg/hal/hal_if.h>
62
#include <cyg/hal/drv_api.h>
63
 
64
#include CYGDAT_DEVS_QUICC_ETH_INL  // Platform specifics
65
#include <cyg/hal/quicc/ppc8xx.h>                  // QUICC structure definitions
66
 
67
// MII interface
68
#define MII_Start            0x40000000
69
#define MII_Read             0x20000000
70
#define MII_Write            0x10000000
71
#define MII_Cmd              0x30000000
72
#define MII_Phy(phy)         (phy << 23)
73
#define MII_Reg(reg)         (reg << 18)
74
#define MII_TA               0x00020000
75
 
76
// Transceiver mode
77
#define PHY_BMCR             0x00    // Register number
78
#define PHY_BMCR_RESET       0x8000
79
#define PHY_BMCR_LOOPBACK    0x4000
80
#define PHY_BMCR_100MB       0x2000
81
#define PHY_BMCR_AUTO_NEG    0x1000
82
#define PHY_BMCR_POWER_DOWN  0x0800
83
#define PHY_BMCR_ISOLATE     0x0400
84
#define PHY_BMCR_RESTART     0x0200
85
#define PHY_BMCR_FULL_DUPLEX 0x0100
86
#define PHY_BMCR_COLL_TEST   0x0080
87
 
88
#define PHY_BMSR             0x01    // Status register
89
#define PHY_BMSR_AUTO_NEG    0x0020  
90
#define PHY_BMSR_LINK        0x0004
91
 
92
// Bits in port D - used for 2 wire MII interface
93
#define MII_DATA             0x1000
94
#define MII_CLOCK            0x0800
95
 
96
#define MII_SET_DATA(val)                      \
97
    if (val) {                                 \
98
        eppc->pio_pddat |= MII_DATA;           \
99
    } else {                                   \
100
        eppc->pio_pddat &= ~MII_DATA;          \
101
    }
102
 
103
#define MII_GET_DATA()                         \
104
    ((eppc->pio_pddat & MII_DATA) != 0)
105
 
106
#define MII_SET_CLOCK(val)                     \
107
    if (val) {                                 \
108
        eppc->pio_pddat |= MII_CLOCK;          \
109
    } else {                                   \
110
        eppc->pio_pddat &= ~MII_CLOCK;         \
111
    }
112
 
113
static cyg_uint32
114
phy_cmd(cyg_uint32 cmd)
115
{
116
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
117
    cyg_uint32  retval;
118
    int         i, off;
119
    bool        is_read = ((cmd & MII_Cmd) == MII_Read);
120
 
121
    // Set both bits as output
122
    eppc->pio_pddir |= MII_DATA | MII_CLOCK;
123
 
124
    // Preamble
125
    for (i = 0; i < 32; i++) {
126
        MII_SET_CLOCK(0);
127
        MII_SET_DATA(1);
128
        CYGACC_CALL_IF_DELAY_US(1);
129
        MII_SET_CLOCK(1);
130
        CYGACC_CALL_IF_DELAY_US(1);
131
    }
132
 
133
    // Command/data
134
    for (i = 0, off = 31; i < (is_read ? 14 : 32); i++, --off) {
135
        MII_SET_CLOCK(0);
136
        MII_SET_DATA((cmd >> off) & 0x00000001);
137
        CYGACC_CALL_IF_DELAY_US(1);
138
        MII_SET_CLOCK(1);
139
        CYGACC_CALL_IF_DELAY_US(1);
140
    }
141
 
142
    retval = cmd;
143
 
144
    // If read, fetch data register
145
    if (is_read) {
146
        retval >>= 16;
147
 
148
        MII_SET_CLOCK(0);
149
        eppc->pio_pddir &= ~MII_DATA;  // Data bit is now input
150
        CYGACC_CALL_IF_DELAY_US(1);
151
        MII_SET_CLOCK(1);
152
        CYGACC_CALL_IF_DELAY_US(1);
153
        MII_SET_CLOCK(0);
154
        CYGACC_CALL_IF_DELAY_US(1);
155
 
156
        for (i = 0, off = 15; i < 16; i++, off--) {
157
            MII_SET_CLOCK(1);
158
            retval <<= 1;
159
            retval |= MII_GET_DATA();
160
            CYGACC_CALL_IF_DELAY_US(1);
161
            MII_SET_CLOCK(0);
162
            CYGACC_CALL_IF_DELAY_US(1);
163
        }
164
    }
165
 
166
    // Set both bits as output
167
    eppc->pio_pddir |= MII_DATA | MII_CLOCK;
168
 
169
    // Postamble
170
    for (i = 0; i < 32; i++) {
171
        MII_SET_CLOCK(0);
172
        MII_SET_DATA(1);
173
        CYGACC_CALL_IF_DELAY_US(1);
174
        MII_SET_CLOCK(1);
175
        CYGACC_CALL_IF_DELAY_US(1);
176
    }
177
 
178
    return retval;
179
}
180
 
181
//
182
// PHY unit access (via MII channel)
183
//
184
static void
185
phy_write(int reg, int addr, unsigned short data)
186
{
187
    phy_cmd(MII_Start | MII_Write | MII_Phy(addr) | MII_Reg(reg) | MII_TA | data);
188
}
189
 
190
static bool
191
phy_read(int reg, int addr, unsigned short *val)
192
{
193
    cyg_uint32 ret;
194
 
195
    ret = phy_cmd(MII_Start | MII_Read | MII_Phy(addr) | MII_Reg(reg) | MII_TA);
196
    *val = ret;
197
    return true;
198
}
199
 
200
bool
201
_adder_reset_phy(void)
202
{
203
    volatile EPPC *eppc = (volatile EPPC *)eppc_base();
204
    int phy_timeout = 5*1000;  // Wait 5 seconds max for link to clear
205
    bool phy_ok;
206
    unsigned short phy_state = 0;
207
    int phy_unit = -1;
208
    int i;
209
 
210
    // Reset PHY (transceiver)
211
    eppc->pip_pbdat &= ~0x00004000;  // Reset PHY chip
212
    CYGACC_CALL_IF_DELAY_US(15000);  // > 10ms
213
    eppc->pip_pbdat |= 0x00004000;   // Enable PHY chip
214
 
215
    phy_ok = false;
216
 
217
    // Try and discover how this PHY is wired
218
    for (i = 0; i < 0x20; i++) {
219
        phy_read(PHY_BMCR, i, &phy_state);
220
        if ((phy_state & PHY_BMCR_RESET) == 0) {
221
            phy_unit = i;
222
            break;
223
        }
224
    }
225
    if (phy_unit < 0) {
226
        diag_printf("QUICC ETH - Can't locate PHY\n");
227
        return false;
228
    } else {
229
#if 0
230
        diag_printf("QUICC ETH - using PHY %d\n", phy_unit);
231
#endif
232
    }
233
    if (phy_read(PHY_BMSR, phy_unit, &phy_state)) {
234
        if ((phy_state & PHY_BMSR_LINK) !=  PHY_BMSR_LINK) {
235
            unsigned short reset_mode;
236
            phy_write(PHY_BMCR, phy_unit, PHY_BMCR_RESET);
237
            for (i = 0;  i < 10;  i++) {
238
                phy_ok = phy_read(PHY_BMCR, phy_unit, &phy_state);
239
                if (!phy_ok) break;
240
                if (!(phy_state & PHY_BMCR_RESET)) break;
241
            }
242
            if (!phy_ok || (phy_state & PHY_BMCR_RESET)) {
243
                diag_printf("QUICC/ETH: Can't get PHY unit to soft reset: %x\n", phy_state);
244
                return false;
245
            }
246
            reset_mode = PHY_BMCR_RESTART | PHY_BMCR_AUTO_NEG | PHY_BMCR_FULL_DUPLEX;
247
            phy_write(PHY_BMCR, phy_unit, reset_mode);
248
            while (phy_timeout-- >= 0) {
249
                phy_ok = phy_read(PHY_BMSR, phy_unit, &phy_state);
250
                if (phy_ok && (phy_state & PHY_BMSR_LINK)) {
251
                    break;
252
                } else {
253
                    CYGACC_CALL_IF_DELAY_US(10000);   // 10ms
254
                }
255
            }
256
            if (phy_timeout <= 0) {
257
                diag_printf("** QUICC/ETH Warning: PHY LINK UP failed\n");
258
            }
259
        }
260
        else {
261
            diag_printf("** QUICC/ETH Info: PHY LINK already UP \n");
262
        }
263
    }
264
 
265
    return phy_ok;
266
}
267
 

powered by: WebSVN 2.1.0

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