]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/eth/frv/pdk403/v2_0/src/pdk403_eth_init.c
Initial revision
[karo-tx-redboot.git] / packages / devs / eth / frv / pdk403 / v2_0 / src / pdk403_eth_init.c
1 //==========================================================================
2 //
3 //      pdk403_eth_init.c
4 //
5 //      Ethernet device driver for NS DP83902a ethernet controller
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, 2003, 2004 Red Hat, 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 version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //####BSDCOPYRIGHTBEGIN####
41 //
42 // -------------------------------------------
43 //
44 // Portions of this software may have been derived from OpenBSD or other sources,
45 // and are covered by the appropriate copyright disclaimers included herein.
46 //
47 // -------------------------------------------
48 //
49 //####BSDCOPYRIGHTEND####
50 //==========================================================================
51 //#####DESCRIPTIONBEGIN####
52 //
53 // Author(s):    dwmw2
54 // Contributors: 
55 // Date:         2003-11-17
56 // Purpose:      
57 // Description:
58 //
59 //####DESCRIPTIONEND####
60 //
61 //==========================================================================
62
63 #include <pkgconf/system.h>
64 #include <pkgconf/io_eth_drivers.h>
65
66 #include <cyg/infra/cyg_type.h>
67 #include <cyg/hal/hal_arch.h>
68 #include <cyg/infra/diag.h>
69 #include <cyg/hal/drv_api.h>
70 #include <cyg/io/eth/eth_drv.h>
71 #include <cyg/io/eth/netdev.h>
72
73 #include <cyg/io/dp83902a.h>
74
75 #define _EECLK  0x80
76 #define _EEO    0x40
77 #define _EEI    0x20
78 #define _EECS   0x10
79
80 void cyg_ax88796_eth_init(dp83902a_priv_data_t *dp)
81 {
82         int i;
83         unsigned char x;
84 #if defined(CYGSEM_DEVS_ETH_PDK403_ETH0_SET_ESA) 
85         cyg_bool esa_ok;
86         unsigned char _esa[6];
87 #endif
88     
89         /* Reset */
90         DP_IN(dp->base, 0x1f, x);
91
92         /* Wait (but not indefinitely) for RST bit in ISR */
93         for (i=0; i < 10000; i++) {
94                 DP_IN(dp->base, DP_ISR, x);
95                 if (x & DP_ISR_RESET)
96                         goto ready;
97                 CYGACC_CALL_IF_DELAY_US(1);
98         }
99         diag_printf("AX88796 at %p not ready after 10ms. Giving up\n",
100                     dp->base);
101         dp->base = 0;
102         return;
103
104  ready:
105         diag_printf("AX88796 at %p, interrupt: %x\n", dp->base, dp->interrupt);
106
107         /* Wait for 2s for link, else power cycle the PHY */
108         for (i=0; i<2000; i++) {
109                 DP_IN(dp->base, 0x17, x);
110                 if (x&1) {
111                         diag_printf("Link OK: %dMbps %s duplex (after %d ms)\n",
112                                     x&4?100:10, x&2?"full":"half", i);
113                         goto link_ok;
114                 }
115                 CYGACC_CALL_IF_DELAY_US(1000);
116         }
117         diag_printf("No Ethernet link after 2s, power cycle PHY...");
118
119         // Assert PPDSET to turn off internal PHY, wait 2s, turn it back on again.
120         DP_OUT(dp->base, 0x17, 0x40);
121         CYGACC_CALL_IF_DELAY_US(2000000);
122         DP_OUT(dp->base, 0x17, 0x00);
123         diag_printf("done.\n");
124
125         // Maybe we're not actually connected. Don't wait.
126  link_ok:
127
128 #if defined(CYGSEM_DEVS_ETH_PDK403_ETH0_SET_ESA) 
129         esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,         
130                                              "lan_esa", _esa, CONFIG_ESA);
131         if (esa_ok) {
132                 memcpy(dp->esa, _esa, sizeof(_esa));
133         }
134 #else
135         // Send 13 bits of EEPROM read command 0.0110.0000.0000.
136         for (i=0; i < 13; i++) {
137                 x = _EECS;
138                 if (i == 2 || i == 3)
139                         x |= _EEI;
140
141                 DP_OUT(dp->base, 0x14, x);
142                 CYGACC_CALL_IF_DELAY_US(10);
143
144                 DP_OUT(dp->base, 0x14, x | _EECLK);
145                 CYGACC_CALL_IF_DELAY_US(10);
146         }
147
148         // Read MAC address
149         for (i=0; i<6; i++) {
150                 int j;
151
152                 dp->esa[i] = 0;
153                 for (j=0; j<8; j++) {
154                         DP_OUT(dp->base, 0x14, _EECS);
155                         CYGACC_CALL_IF_DELAY_US(10);
156                            
157                         DP_OUT(dp->base, 0x14, _EECS | _EECLK);
158                         CYGACC_CALL_IF_DELAY_US(10);
159                            
160                         DP_IN(dp->base, 0x14, x);
161                            
162                         dp->esa[i] <<= 1;
163                         dp->esa[i] |= !!(x & _EEO);
164                 }
165         }
166         DP_OUT(dp->base, 0x14, _EECS);
167         CYGACC_CALL_IF_DELAY_US(20);
168         DP_OUT(dp->base, 0x14, 0);
169         CYGACC_CALL_IF_DELAY_US(20);
170         if (dp->esa[0] != 0 || dp->esa[1] != 0x0e ||
171             dp->esa[2] != 0 || dp->esa[3] != 0x50) {
172                 /* Bad MAC address. PDK docs say these four bytes should always
173                    be as above */
174                 diag_printf("Bad EEPROM MAC address %02x:02x:%02x:%02x:%02x:%02x. Disabling AX88796\n",
175                             dp->esa[0], dp->esa[1], dp->esa[2], dp->esa[3], dp->esa[4], dp->esa[5]);
176                 // Turn off PHY and stop chip
177                 DP_OUT(dp->base, 0x17, 0x40);
178                 dp->base = 0;
179                 return;
180         }
181
182         // Set ESA into chip
183         DP_OUT(dp->base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1);  // Select page 1
184         for (i = 0; i < 6; i++)
185                 DP_OUT(dp->base, DP_P1_PAR0+i, dp->esa[i]);
186
187         DP_OUT(dp->base, DP_CR, DP_CR_NODMA | DP_CR_PAGE0);  // Select page 0
188 #endif
189 }