1 //==========================================================================
5 // Driver for LXT972 PHY
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
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.
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
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.
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.
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.
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 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: Based on code from: gthomas, jskov
45 // Grant Edwards <grante@visi.com>
50 //####DESCRIPTIONEND####
52 //========================================================================*/
54 #include <pkgconf/devs_eth_arm_ks32c5000.h>
59 #define Bit(n) (1<<(n))
61 // address of the LX972 phy
62 #ifdef CYGPKG_DEVS_ETH_ARM_KS32C5000_PHYADDR
63 #define LX972_ADDR CYGPKG_DEVS_ETH_ARM_KS32C5000_PHYADDR
68 // LX972 register offsets
69 #define LX972_CTRL_REG 0x00
70 #define LX972_STATUS1_REG 0x01
71 #define LX972_PHY_ID1_REG 0x02
72 #define LX972_PHY_ID2_REG 0x03
73 #define LX972_AN_ADVRT_REG 0x04
74 #define LX972_AN_LPAR_REG 0x05
75 #define LX972_AN_EXP_REG 0x06
76 #define LX972_AN_NEXTPAGE_REG 0x07
77 #define LX972_AN_LPAR_NP_REG 0x08
78 #define LX972_PORT_CONFIG_REG 0x10
79 #define LX972_STATUS2_REG 0x11
80 #define LX972_INT_ENAB_REG 0x12
81 #define LX972_INT_STAT_REG 0x13
82 #define LX972_LED_CONFIG_REG 0x14
83 #define LX972_DIG_CONFIG_REG 0x1A
84 #define LX972_TX_CTRL2_REG 0x1E
86 // LX972 Control register bit defines
87 #define LX972_CTRL_RESET 0x8000
88 #define LX972_CTRL_LOOPBACK 0x4000
89 #define LX972_CTRL_SPEED 0x2000 // 1=100Meg, 0=10Meg
90 #define LX972_CTRL_AN 0x1000 // 1=Enable auto negotiation, 0=disable it
91 #define LX972_CTRL_PWRDN 0x0800 // 1=Enable power down
92 #define LX972_CTRL_ISOLATE 0x0400 // 1=Isolate from MII
93 #define LX972_CTRL_RSTRT_AN 0x0200 // 1=Restart Auto Negotioation process
94 #define LX972_CTRL_FULL_DUP 0x0100 // 1=Enable full duplex mode, 0=half dup
95 #define LX972_CTRL_TST_COLL 0x0080 // 1=Enable collision test
97 // LX972 Interrupt enable register bit defines
98 #define LX972_INT_ENAB_ANMSK Bit(7)
99 #define LX972_INT_ENAB_SPEEDMSK Bit(6)
100 #define LX972_INT_ENAB_DUPLEXMSK Bit(5)
101 #define LX972_INT_ENAB_LINKMSK Bit(4)
102 #define LX972_INT_ENAB_INTEN Bit(1)
103 #define LX972_INT_ENAB_TINT Bit(0)
105 // Map LED values from CDL file to reg defines
106 #define LINK_SPEED LX972_LED_CONFIG_SPEED_STATUS
107 #define TX_ACTIVITY LX972_LED_CONFIG_TX_STATUS
108 #define RX_ACTIVITY LX972_LED_CONFIG_RX_STATUS
109 #define COLLISION_STATUS LX972_LED_CONFIG_COLLISION_STATUS
110 #define DUPLEX_STATUS LX972_LED_CONFIG_DUPLEX_STATUS
111 #define LINK_ACTIVITY LX972_LED_CONFIG_RXTX_ACTIVITY
112 #define LINK_STATUS_RX_STATUS_COMBINED LX972_LED_CONFIG_LINK_RX_COMB
113 #define LINK_STATUS_LINK_ACTIVITY_COMBINED LX972_LED_CONFIG_LINK_ACT_COMB
114 #define DUPLEX_STATUS_COLLISION_STATUS_COMBINED LX972_LED_CONFIG_DUPLEX_COLL_COMB
115 #define LINK_STATUS LX972_LED_CONFIG_LINK_STATUS
116 #define TEST_ON LX972_LED_CONFIG_TEST_ON
117 #define TEST_OFF LX972_LED_CONFIG_TEST_OFF
118 #define TEST_BLINK_FAST LX972_LED_CONFIG_BLINK_FAST
119 #define TEST_BLINK_SLOW LX972_LED_CONFIG_BLINK_SLOW
121 // LX972 LED Config register bit defines
122 #define LX972_LED_CONFIG_LED1SHIFT 12
123 #define LX972_LED_CONFIG_LED2SHIFT 8
124 #define LX972_LED_CONFIG_LED3SHIFT 4
125 #define LX972_LED_CONFIG_SPEED_STATUS 0x0
126 #define LX972_LED_CONFIG_TX_STATUS 0x1
127 #define LX972_LED_CONFIG_RX_STATUS 0x2
128 #define LX972_LED_CONFIG_COLLISION_STATUS 0x3
129 #define LX972_LED_CONFIG_LINK_STATUS 0x4
130 #define LX972_LED_CONFIG_DUPLEX_STATUS 0x5
131 #define LX972_LED_CONFIG_RXTX_ACTIVITY 0x7
132 #define LX972_LED_CONFIG_TEST_ON 0x8
133 #define LX972_LED_CONFIG_TEST_OFF 0x9
134 #define LX972_LED_CONFIG_BLINK_FAST 0xA
135 #define LX972_LED_CONFIG_BLINK_SLOW 0xB
136 #define LX972_LED_CONFIG_LINK_RX_COMB 0xC
137 #define LX972_LED_CONFIG_LINK_ACT_COMB 0xD
138 #define LX972_LED_CONFIG_DUPLEX_COLL_COMB 0xE
139 #define LX972_LED_CONFIG_STRETCH_100MS 0x8
140 #define LX972_LED_CONFIG_ENAB_LED_STRETCH Bit(1)
142 // LX972 Auto Negotiation Advertisement register bit defines
143 #define LX972_AN_ADVRT_NEXT_PAGE Bit(15)
144 #define LX972_AN_ADVRT_PAUSE_ENA Bit(10)
145 #define LX972_AN_ADVRT_100T4 Bit(9)
146 #define LX972_AN_ADVRT_100TX_FULL Bit(8)
147 #define LX972_AN_ADVRT_100TX Bit(7)
148 #define LX972_AN_ADVRT_10T_FULL Bit(6)
149 #define LX972_AN_ADVRT_10T Bit(5)
150 #define LX972_AN_ADVRT_SEL_802_3 Bit(0)
152 // LX972 Status register #2 bit defines
153 #define LX972_STATUS2_100M Bit(14)
154 #define LX972_STATUS2_LINKUP Bit(10)
155 #define LX972_STATUS2_FULLDUP Bit(9)
156 #define LX972_STATUS2_ANEG_DONE Bit(7)
158 // phy functions for Level1 PHY LXT972
162 unsigned CtrlRegData;
163 // First software reset the LX972
164 MiiStationWrite(LX972_CTRL_REG, LX972_ADDR, LX972_CTRL_RESET);
165 MiiStationWrite(LX972_CTRL_REG, LX972_ADDR, 0);
167 // Wait until the LX972 reset cycle has completed
168 // The Control register will read 0x7FFF until the reset cycle has completed
169 CtrlRegData = 0x7FFF;
170 while (CtrlRegData == 0x7FFF)
172 CtrlRegData = MiiStationRead(LX972_CTRL_REG, LX972_ADDR);
175 // Set up the LEDs' modes
176 MiiStationWrite(LX972_LED_CONFIG_REG, LX972_ADDR,
177 (CYGPKG_DEVS_ETH_ARM_KS32C5000_PHY_LXT972_LED1 << LX972_LED_CONFIG_LED1SHIFT)
178 | (CYGPKG_DEVS_ETH_ARM_KS32C5000_PHY_LXT972_LED2 << LX972_LED_CONFIG_LED2SHIFT)
179 | (CYGPKG_DEVS_ETH_ARM_KS32C5000_PHY_LXT972_LED3 << LX972_LED_CONFIG_LED3SHIFT)
180 | LX972_LED_CONFIG_STRETCH_100MS
181 | LX972_LED_CONFIG_ENAB_LED_STRETCH);
183 // Set MII drive strength
184 MiiStationWrite(LX972_DIG_CONFIG_REG, LX972_ADDR, 0);
187 MiiStationWrite(LX972_INT_ENAB_REG, LX972_ADDR,
189 | LX972_INT_ENAB_SPEEDMSK
190 | LX972_INT_ENAB_DUPLEXMSK
191 | LX972_INT_ENAB_LINKMSK
192 | LX972_INT_ENAB_INTEN);
194 // Initialize auto-negotiation capabilities
195 // Next page not enabled
196 MiiStationWrite(LX972_AN_ADVRT_REG, LX972_ADDR,
197 LX972_AN_ADVRT_PAUSE_ENA
198 | LX972_AN_ADVRT_100T4
199 | LX972_AN_ADVRT_100TX_FULL
200 | LX972_AN_ADVRT_100TX
201 | LX972_AN_ADVRT_10T_FULL
203 | LX972_AN_ADVRT_SEL_802_3);
205 // Now start an auto negotiation
206 MiiStationWrite(LX972_CTRL_REG, LX972_ADDR,
208 | LX972_CTRL_RSTRT_AN);
210 // force to 10M full duplex
211 MiiStationWrite(LX972_CTRL_REG, LX972_ADDR,
212 LX972_CTRL_FULL_DUP);
216 unsigned PhyStatus(void)
218 unsigned lxt972Status = MiiStationRead(LX972_STATUS2_REG,LX972_ADDR);
220 if (lxt972Status & LX972_STATUS2_LINKUP)
221 r |= PhyStatus_LinkUp;
222 if (lxt972Status & LX972_STATUS2_FULLDUP)
223 r |= PhyStatus_FullDuplex;
224 if (lxt972Status & LX972_STATUS2_100M)
225 r |= PhyStatus_100Mb;
229 void PhyInterruptAck(void)
231 MiiStationRead(LX972_STATUS1_REG, LX972_ADDR);
232 MiiStationRead(LX972_INT_STAT_REG, LX972_ADDR);