blob: d282aa6725b850608e5b324698bc93a53deec64e [file] [log] [blame]
Wolfgang Denk4646d2a2006-05-30 15:56:48 +02001/**
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
56PRIVATE UINT32 miiBaseAddressVirt;
57PRIVATE IxOsalMutex miiAccessLock;
58
59PUBLIC UINT32 ixEthAccMiiRetryCount = IX_ETH_ACC_MII_TIMEOUT_10TH_SECS;
60PUBLIC UINT32 ixEthAccMiiAccessTimeout = IX_ETH_ACC_MII_10TH_SEC_IN_MILLIS;
61
62/* -----------------------------------
63 * private function prototypes
64 */
65PRIVATE void
66ixEthAccMdioCmdWrite(UINT32 mdioCommand);
67
68PRIVATE void
69ixEthAccMdioCmdRead(UINT32 *data);
70
71PRIVATE void
72ixEthAccMdioStatusRead(UINT32 *data);
73
74
75PRIVATE void
76ixEthAccMdioCmdWrite(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
95PRIVATE void
96ixEthAccMdioCmdRead(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
126PRIVATE void
127ixEthAccMdioStatusRead(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 */
161IxEthAccStatus
162ixEthAccMiiInit()
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
184void
185ixEthAccMiiUnload(void)
186{
187 IX_OSAL_MEM_UNMAP(miiBaseAddressVirt);
188
189 miiBaseAddressVirt = 0;
190}
191
192PUBLIC IxEthAccStatus
193ixEthAccMiiAccessTimeoutSet(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 */
206IxEthAccStatus
207ixEthAccMiiReadRtn (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 */
282IxEthAccStatus
283ixEthAccMiiWriteRtn (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)
Wolfgang Denka1be4762008-05-20 16:00:29 +0200327 {
Wolfgang Denk4646d2a2006-05-30 15:56:48 +0200328 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 */
349IxEthAccStatus
350ixEthAccMiiStatsShow (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 */
380IxEthAccStatus
381ixEthAccMdioShow (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