1 //####ECOSGPLCOPYRIGHTBEGIN####
2 // -------------------------------------------
3 // This file is part of eCos, the Embedded Configurable Operating System.
4 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
5 // Copyright (C) 2002 Gary Thomas
7 // eCos is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 2 or (at your option) any later version.
11 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // You should have received a copy of the GNU General Public License along
17 // with eCos; if not, write to the Free Software Foundation, Inc.,
18 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 // As a special exception, if other files instantiate templates or use macros
21 // or inline functions from this file, or you compile this file and link it
22 // with other works to produce a work based on this file, this file does not
23 // by itself cause the resulting work to be covered by the GNU General Public
24 // License. However the source code for this file must still be made available
25 // in accordance with section (3) of the GNU General Public License.
27 // This exception does not invalidate any other reasons why a work based on
28 // this file might be covered by the GNU General Public License.
30 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
31 // at http://sources.redhat.com/ecos/ecos-license/
32 // -------------------------------------------
33 //####ECOSGPLCOPYRIGHTEND####
34 /*-------------------------------------------------------------------
38 * DESCRIPTION: GPIO Management Pins driver for the LXT970a
41 * Modified for the mpc8260 VADS board
42 *--------------------------------------------------------------------*/
44 #include <cyg/hal/hal_intr.h> /* HAL_DELAY_US */
47 /* Internal functions */
48 void MdioSend(UINT32, UINT16);
49 UINT16 MdioReceive(UINT16);
50 UINT16 MdioFrame(MDIORW, UINT16, UINT16, UINT32);
55 /*-------------------------------------------------------------------
61 * EXTERNAL EFFECT: Turns on the LXT970 transciever
69 *-------------------------------------------------------------------*/
71 EnableResetPHY(volatile t_BCSR *pBCSR)
73 #ifdef CYGPKG_HAL_POWERPC_TS6
74 #define ETH_RST_MASK 0x20
75 /* The FPGA control register on the TS6 board uses the same memory
76 * location as the BCSR register on the VADS board.
78 volatile cyg_uint32 *fpga_ctrl = (cyg_uint32 *) pBCSR;
79 volatile cyg_uint32 *fpga_vers;
81 fpga_vers = fpga_ctrl + 1;
83 if(value >= 6){ /* version 06 of the FPGA added PHY reset control */
85 /* Set the PHY reset bit */
86 value |= ETH_RST_MASK;
89 /* Give the PHY time to reset */
92 /* Clear the reset bit */
93 *fpga_vers = value & ~ETH_RST_MASK;
96 // active low FETHIEN on BSCR1, assert reset low
97 pBCSR->bcsr1 &= ~(FETHIEN_ | FETHRST_);
99 pBCSR->bcsr1 |= FETHRST_;
104 /*-------------------------------------------------------------------
108 * DESCRIPTION: Writes parameters to the control registers of LXT970
118 *-------------------------------------------------------------------*/
120 InitEthernetPHY(VUINT32* pdir, VUINT32* pdat, UINT16 link)
125 /* 8101 Ethernet Management Pin Assignments */
129 (*pPortDir) |= MDC_PIN_MASK; /* MD_Clock will always be output only */
131 /* Test MDC & MDIO Pin Connection to PHY */
132 MdioFrame(WRITE, 0, MIRROR_REG, MD_TEST_FRAME); //send test frame
133 MdioFrame(WRITE, 0, MIRROR_REG, MD_TEST_FRAME); //send test frame
134 FrameValue = MdioFrame(READ, 0, MIRROR_REG, 0); //read test frame
136 if (FrameValue != MD_TEST_FRAME)
137 return LINKERROR; //test data integrity
139 /* General Configuration */
140 MdioFrame(WRITE, 0, CONFIG_REG, 0x0000);
142 if(link == HUNDRED_HD)
143 MdioFrame(WRITE, 0, AUTONEG_AD_REG, 0x0081); //100 Mbps Half, 802.3
145 MdioFrame(WRITE, 0, AUTONEG_AD_REG, 0x0021); //10 Mbps Half, 802.3
147 // 100 Mbps full duplex not supported
148 // MdioFrame(WRITE, 0, AUTONEG_AD_REG, 0x0101); //100 Mbps Full, 802.3
150 MdioFrame(WRITE, 0, CONTROL_REG, 0x1300);
155 /*-------------------------------------------------------------------
169 *-------------------------------------------------------------------*/
171 EthernetPHYInterruptHandler()
173 // Reading registers 1 and 18 in sequence
174 // clears the transceiver interrupt
176 MdioFrame(READ, 0, STATUS_REG, 0);
177 MdioFrame(READ, 0, INT_STAT_REG, 0);
179 return LinkTestPHY();
180 } /* end EthernetPHYInterruptHandler */
182 /*-------------------------------------------------------------------
196 *-------------------------------------------------------------------*/
201 UINT16 FrameValue = 0;
203 for (j = 0; j < 50; j++) {
205 HAL_DELAY_US(100000);
207 FrameValue = MdioFrame(READ,0,CHIP_STAT_REG,0);
209 if ( (FrameValue & 0x0200) != 0 )
213 FrameValue &= 0x3800;
215 switch (FrameValue) {
217 case 0x3800: return HUNDRED_FD;
218 case 0x2800: return HUNDRED_HD;
219 case 0x3000: return TEN_FD;
220 case 0x2000: return TEN_HD;
221 default: return NOTLINKED;
226 /*-------------------------------------------------------------------
240 *-------------------------------------------------------------------*/
241 void EnablePHYinterrupt(UINT8 enable)
243 MdioFrame(WRITE, 0, INT_EN_REG, enable?0x2:0x0);
246 /*----------------------------------------------------------------------
250 * DESCRIPTION: generic READ/WRITE function of LXT970
251 * through the MDC/MDIO interface.
261 *---------------------------------------------------------------------*/
263 MdioFrame(MDIORW R_W, UINT16 PhyAddr, UINT16 RegAddr, UINT32 PutData) {
267 *pPortDir |= MDIO_PIN_MASK; //set to output mode
269 MdioSend(0xFFFFFFFF,32); //PreAmble
270 MdioSend(0x1,2); //Start Frame Delimiter
272 MdioSend(0x2,2); //Read OpCode
274 MdioSend(0x1,2); //Write OpCode
276 MdioSend(PhyAddr,5); //Send PHY transciever Address
277 MdioSend(RegAddr,5); //Send Register Address
280 *pPortDir &= ~MDIO_PIN_MASK; //set to input mode
281 GetData = MdioReceive(17); //Drive TurnAround and Data
285 MdioSend(0x2,2); //Drive TurnAround
286 MdioSend(PutData, 16); //Send Data
288 *pPortDir &= ~MDIO_PIN_MASK; //set to input mode
294 /*----------------------------------------------------------------------
298 * DESCRIPTION: Shift out bits of data
308 *----------------------------------------------------------------------*/
310 MdioSend(UINT32 txF, UINT16 size) {
315 dmask = 1 << (size-1); // msbit out first
317 for (i = 0; i < size; i++) { // for "size" bits
319 if ( txF & dmask ) //output data bit high
320 *pPortData |= MDIO_PIN_MASK;
321 else //output data bit low > 400ns
322 *pPortData &= ~MDIO_PIN_MASK;
324 *pPortData |= MDC_PIN_MASK; // clock rise
326 txF = (UINT32)(txF << 1); // >160ns
328 for (j=0; j<MDC_HOLD_TIME; j++);
330 *pPortData &= ~MDC_PIN_MASK; // clock fall
332 for (j=0; j<MDC_HOLD_TIME; j++);
340 /*---------------------------------------------------------------------
344 * DESCRIPTION: Shifts in bits of data
354 *---------------------------------------------------------------------*/
356 MdioReceive(UINT16 size) {
360 for (i = 0; i < size; i++) { // 16 bits
362 *pPortData |= MDC_PIN_MASK; // clock rise
364 if ( *pPortData & MDIO_PIN_MASK ) // if read in a high bit
365 rxF = ( (UINT16)(rxF << 1) | 1 ); // shift in a one
366 else // if read in a low bit
367 rxF = ( (UINT16)(rxF << 1) & ~(UINT16)1 ); // shift in a zero
370 for (j=0; j<MDC_HOLD_TIME; j++);
372 *pPortData &= ~MDC_PIN_MASK; // clock fall
374 for (j=0; j<MDC_HOLD_TIME; j++);