Merge branch 'mpc86xx'
[platform/kernel/u-boot.git] / cpu / ixp / npe / IxEthAccMii.c
1 /**
2  * @file IxEthAccMii.c
3  *
4  * @author Intel Corporation
5  * @date 
6  *
7  * @brief  MII control functions
8  *
9  * Design Notes:
10  *
11  * IXP400 SW Release version 2.0
12  * 
13  * -- Copyright Notice --
14  * 
15  * @par
16  * Copyright 2001-2005, Intel Corporation.
17  * All rights reserved.
18  * 
19  * @par
20  * Redistribution and use in source and binary forms, with or without
21  * modification, are permitted provided that the following conditions
22  * are met:
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer.
25  * 2. Redistributions in binary form must reproduce the above copyright
26  *    notice, this list of conditions and the following disclaimer in the
27  *    documentation and/or other materials provided with the distribution.
28  * 3. Neither the name of the Intel Corporation nor the names of its contributors
29  *    may be used to endorse or promote products derived from this software
30  *    without specific prior written permission.
31  * 
32  * @par
33  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
34  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  * SUCH DAMAGE.
44  * 
45  * @par
46  * -- End of Copyright Notice --
47  */
48
49 #include "IxOsal.h"
50 #include "IxEthAcc.h"
51 #include "IxEthAcc_p.h"
52 #include "IxEthAccMac_p.h"
53 #include "IxEthAccMii_p.h"
54
55
56 PRIVATE UINT32 miiBaseAddressVirt;
57 PRIVATE IxOsalMutex miiAccessLock;
58
59 PUBLIC UINT32 ixEthAccMiiRetryCount    = IX_ETH_ACC_MII_TIMEOUT_10TH_SECS;
60 PUBLIC UINT32 ixEthAccMiiAccessTimeout = IX_ETH_ACC_MII_10TH_SEC_IN_MILLIS;
61
62 /* -----------------------------------
63  * private function prototypes
64  */
65 PRIVATE void
66 ixEthAccMdioCmdWrite(UINT32 mdioCommand);
67
68 PRIVATE void
69 ixEthAccMdioCmdRead(UINT32 *data);
70
71 PRIVATE void
72 ixEthAccMdioStatusRead(UINT32 *data);
73
74
75 PRIVATE void
76 ixEthAccMdioCmdWrite(UINT32 mdioCommand)
77 {
78     REG_WRITE(miiBaseAddressVirt,
79               IX_ETH_ACC_MAC_MDIO_CMD_1,
80               mdioCommand & 0xff);
81
82     REG_WRITE(miiBaseAddressVirt,
83               IX_ETH_ACC_MAC_MDIO_CMD_2,
84               (mdioCommand >> 8) & 0xff);
85
86     REG_WRITE(miiBaseAddressVirt,
87               IX_ETH_ACC_MAC_MDIO_CMD_3,
88               (mdioCommand >> 16) & 0xff);
89
90     REG_WRITE(miiBaseAddressVirt,
91               IX_ETH_ACC_MAC_MDIO_CMD_4,
92               (mdioCommand >> 24) & 0xff);
93 }
94
95 PRIVATE void
96 ixEthAccMdioCmdRead(UINT32 *data)
97 {
98     UINT32 regval;
99
100     REG_READ(miiBaseAddressVirt,
101              IX_ETH_ACC_MAC_MDIO_CMD_1,
102              regval);
103
104     *data = regval & 0xff;
105
106     REG_READ(miiBaseAddressVirt,
107              IX_ETH_ACC_MAC_MDIO_CMD_2,
108              regval);
109
110     *data |= (regval & 0xff) << 8;
111
112     REG_READ(miiBaseAddressVirt,
113              IX_ETH_ACC_MAC_MDIO_CMD_3,
114              regval);
115
116     *data |= (regval & 0xff) << 16;
117
118     REG_READ(miiBaseAddressVirt,
119              IX_ETH_ACC_MAC_MDIO_CMD_4,
120              regval);
121
122     *data |= (regval & 0xff) << 24;
123
124 }
125
126 PRIVATE void
127 ixEthAccMdioStatusRead(UINT32 *data)
128 {
129     UINT32 regval;
130
131     REG_READ(miiBaseAddressVirt,
132              IX_ETH_ACC_MAC_MDIO_STS_1,
133              regval);
134
135     *data = regval & 0xff;
136
137     REG_READ(miiBaseAddressVirt,
138              IX_ETH_ACC_MAC_MDIO_STS_2,
139              regval);
140
141     *data |= (regval & 0xff) << 8;
142
143     REG_READ(miiBaseAddressVirt,
144              IX_ETH_ACC_MAC_MDIO_STS_3,
145              regval);
146
147     *data |= (regval & 0xff) << 16;
148
149     REG_READ(miiBaseAddressVirt,
150              IX_ETH_ACC_MAC_MDIO_STS_4,
151              regval);
152     
153     *data |= (regval & 0xff) << 24;
154     
155 }
156
157
158 /********************************************************************
159  * ixEthAccMiiInit
160  */
161 IxEthAccStatus
162 ixEthAccMiiInit()
163 {
164     if(ixOsalMutexInit(&miiAccessLock)!= IX_SUCCESS)
165     {
166         return IX_ETH_ACC_FAIL;
167     }
168
169     miiBaseAddressVirt = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, IX_OSAL_IXP400_ETHA_MAP_SIZE);
170     
171     if (miiBaseAddressVirt == 0)
172     {
173       ixOsalLog(IX_OSAL_LOG_LVL_FATAL, 
174                 IX_OSAL_LOG_DEV_STDOUT, 
175                 "EthAcc: Could not map MII I/O mapped memory\n", 
176                 0, 0, 0, 0, 0, 0);
177       
178       return IX_ETH_ACC_FAIL;
179     }
180     
181     return IX_ETH_ACC_SUCCESS;
182 }
183
184 void
185 ixEthAccMiiUnload(void)
186 {
187     IX_OSAL_MEM_UNMAP(miiBaseAddressVirt);
188   
189     miiBaseAddressVirt = 0;
190 }
191
192 PUBLIC IxEthAccStatus
193 ixEthAccMiiAccessTimeoutSet(UINT32 timeout, UINT32 retryCount)
194 {
195     if (retryCount < 1) return IX_ETH_ACC_FAIL;
196
197     ixEthAccMiiRetryCount    = retryCount;
198     ixEthAccMiiAccessTimeout = timeout;
199
200     return IX_ETH_ACC_SUCCESS;
201 }
202
203 /*********************************************************************
204  * ixEthAccMiiReadRtn - read a 16 bit value from a PHY
205  */
206 IxEthAccStatus      
207 ixEthAccMiiReadRtn (UINT8 phyAddr, 
208                     UINT8 phyReg, 
209                     UINT16 *value)
210 {
211     UINT32 mdioCommand;
212     UINT32 regval;
213     UINT32 miiTimeout;
214
215     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
216     {
217         return (IX_ETH_ACC_FAIL);
218     }
219
220     if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR) 
221         || (phyReg >= IXP425_ETH_ACC_MII_MAX_REG))
222     {
223         return (IX_ETH_ACC_FAIL);
224     }
225
226     if (value == NULL)
227     {
228         return (IX_ETH_ACC_FAIL);
229     }
230
231     ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
232     mdioCommand = phyReg <<  IX_ETH_ACC_MII_REG_SHL 
233         | phyAddr << IX_ETH_ACC_MII_ADDR_SHL;
234     mdioCommand |= IX_ETH_ACC_MII_GO;
235
236     ixEthAccMdioCmdWrite(mdioCommand);
237     
238     miiTimeout = ixEthAccMiiRetryCount;
239
240     while(miiTimeout)
241     {
242         
243         ixEthAccMdioCmdRead(&regval);
244      
245         if((regval & IX_ETH_ACC_MII_GO) == 0x0)
246         {           
247             break;
248         }
249         /* Sleep for a while */
250         ixOsalSleep(ixEthAccMiiAccessTimeout);
251         miiTimeout--;
252     }
253     
254
255     
256     if(miiTimeout == 0)
257     {   
258         ixOsalMutexUnlock(&miiAccessLock);
259         *value = 0xffff;
260         return IX_ETH_ACC_FAIL;
261     }
262     
263     
264     ixEthAccMdioStatusRead(&regval);
265     if(regval & IX_ETH_ACC_MII_READ_FAIL)
266     {
267         ixOsalMutexUnlock(&miiAccessLock);
268         *value = 0xffff;
269         return IX_ETH_ACC_FAIL;
270     }
271
272     *value = regval & 0xffff;
273     ixOsalMutexUnlock(&miiAccessLock);
274     return IX_ETH_ACC_SUCCESS;
275     
276 }
277
278
279 /*********************************************************************
280  * ixEthAccMiiWriteRtn - write a 16 bit value to a PHY
281  */
282 IxEthAccStatus
283 ixEthAccMiiWriteRtn (UINT8 phyAddr, 
284                      UINT8 phyReg, 
285                      UINT16 value)
286 {
287     UINT32 mdioCommand;
288     UINT32 regval;
289     UINT16 readVal;
290     UINT32 miiTimeout;
291
292     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
293     {
294         return (IX_ETH_ACC_FAIL);
295     }
296
297     if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR) 
298         || (phyReg >= IXP425_ETH_ACC_MII_MAX_REG))
299     {
300         return (IX_ETH_ACC_FAIL);
301     }
302    
303     /* ensure that a PHY is present at this address */
304     if(ixEthAccMiiReadRtn(phyAddr,
305                           IX_ETH_ACC_MII_CTRL_REG,
306                           &readVal) != IX_ETH_ACC_SUCCESS)
307     {
308         return (IX_ETH_ACC_FAIL);
309     }
310
311     ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
312     mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL
313         | phyAddr << IX_ETH_ACC_MII_ADDR_SHL ;
314     mdioCommand |= IX_ETH_ACC_MII_GO | IX_ETH_ACC_MII_WRITE | value;
315
316     ixEthAccMdioCmdWrite(mdioCommand);
317     
318     miiTimeout = ixEthAccMiiRetryCount;
319
320     while(miiTimeout)
321     {
322         
323         ixEthAccMdioCmdRead(&regval);
324
325         /*The "GO" bit is reset to 0 when the write completes*/
326         if((regval & IX_ETH_ACC_MII_GO) == 0x0)
327         {                   
328             break;
329         }
330         /* Sleep for a while */
331         ixOsalSleep(ixEthAccMiiAccessTimeout);
332         miiTimeout--;
333     }
334     
335     ixOsalMutexUnlock(&miiAccessLock);
336     if(miiTimeout == 0)
337     {
338         return IX_ETH_ACC_FAIL;
339     }
340     return IX_ETH_ACC_SUCCESS;
341 }
342
343
344 /*****************************************************************
345  *
346  *  Phy query functions
347  *
348  */
349 IxEthAccStatus
350 ixEthAccMiiStatsShow (UINT32 phyAddr)
351 {
352     UINT16 regval;
353     printf("Regisers on PHY at address 0x%x\n", phyAddr);
354     ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_CTRL_REG, &regval);
355     printf("    Control Register                  :      0x%4.4x\n", regval);
356     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_STAT_REG, &regval);
357     printf("    Status Register                   :      0x%4.4x\n", regval);
358     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_PHY_ID1_REG, &regval);
359     printf("    PHY ID1 Register                  :      0x%4.4x\n", regval);
360     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_PHY_ID2_REG, &regval);
361     printf("    PHY ID2 Register                  :      0x%4.4x\n", regval);
362     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_ADS_REG, &regval);
363     printf("    Auto Neg ADS Register             :      0x%4.4x\n", regval);
364     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_PRTN_REG, &regval);
365     printf("    Auto Neg Partner Ability Register :      0x%4.4x\n", regval);
366     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_EXP_REG, &regval);
367     printf("    Auto Neg Expansion Register       :      0x%4.4x\n", regval);
368     ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_NEXT_REG, &regval);
369     printf("    Auto Neg Next Register            :      0x%4.4x\n", regval);
370
371     return IX_ETH_ACC_SUCCESS;
372 }
373
374
375 /*****************************************************************
376  *
377  *  Interface query functions
378  *
379  */
380 IxEthAccStatus
381 ixEthAccMdioShow (void)
382 {
383     UINT32 regval;
384
385     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
386     {
387         return (IX_ETH_ACC_FAIL);
388     }
389
390     ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
391     ixEthAccMdioCmdRead(&regval);
392     ixOsalMutexUnlock(&miiAccessLock);
393     
394     printf("MDIO command register\n");
395     printf("    Go bit      : 0x%x\n", (regval & BIT(31)) >> 31);
396     printf("    MDIO Write  : 0x%x\n", (regval & BIT(26)) >> 26);
397     printf("    PHY address : 0x%x\n", (regval >> 21) & 0x1f);
398     printf("    Reg address : 0x%x\n", (regval >> 16) & 0x1f);
399         
400     ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER);
401     ixEthAccMdioStatusRead(&regval);
402     ixOsalMutexUnlock(&miiAccessLock);
403
404     printf("MDIO status register\n");
405     printf("    Read OK     : 0x%x\n", (regval & BIT(31)) >> 31);
406     printf("    Read Data   : 0x%x\n", (regval >> 16) & 0xff);
407
408     return IX_ETH_ACC_SUCCESS;   
409 }
410