aboutsummaryrefslogtreecommitdiff
path: root/cpu/ppc4xx/miiphy.c
blob: fce5f4b648aa21d5b53d6620033d5c3381cf1092 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/*-----------------------------------------------------------------------------+
  |
  |       This source code has been made available to you by IBM on an AS-IS
  |       basis.  Anyone receiving this source is licensed under IBM
  |       copyrights to use it in any way he or she deems fit, including
  |       copying it, modifying it, compiling it, and redistributing it either
  |       with or without modifications.  No license under IBM patents or
  |       patent applications is to be implied by the copyright license.
  |
  |       Any user of this software should understand that IBM cannot provide
  |       technical support for this software and will not be responsible for
  |       any consequences resulting from the use of this software.
  |
  |       Any person who transfers this source code or any derivative work
  |       must include the IBM copyright notice, this paragraph, and the
  |       preceding two paragraphs in the transferred software.
  |
  |       COPYRIGHT   I B M   CORPORATION 1995
  |       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
  +-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------+
  |
  |  File Name:  miiphy.c
  |
  |  Function:   This module has utilities for accessing the MII PHY through
  |	       the EMAC3 macro.
  |
  |  Author:     Mark Wisner
  |
  |  Change Activity-
  |
  |  Date        Description of Change                                       BY
  |  ---------   ---------------------                                       ---
  |  05-May-99   Created                                                     MKW
  |  01-Jul-99   Changed clock setting of sta_reg from 66Mhz to 50Mhz to
  |              better match OPB speed. Also modified delay times.      	   JWB
  |  29-Jul-99   Added Full duplex support                                   MKW
  |  24-Aug-99   Removed printf from dp83843_duplex()                      JWB
  |  19-Jul-00   Ported to esd cpci405                                       sr
  |
  +-----------------------------------------------------------------------------*/

#include <common.h>
#include <asm/processor.h>
#include <ppc_asm.tmpl>
#include <commproc.h>
#include <405gp_enet.h>
#include <405_mal.h>
#include <miiphy.h>

#if defined(CONFIG_405GP) || defined(CONFIG_440) || defined(CONFIG_405EP)


/***********************************************************/
/* Dump out to the screen PHY regs                         */
/***********************************************************/

void miiphy_dump (unsigned char addr)
{
	unsigned long i;
	unsigned short data;


	for (i = 0; i < 0x1A; i++) {
		if (miiphy_read (addr, i, &data)) {
			printf ("read error for reg %lx\n", i);
			return;
		}
		printf ("Phy reg %lx ==> %4x\n", i, data);

		/* jump to the next set of regs */
		if (i == 0x07)
			i = 0x0f;

	} /* end for loop */
} /* end dump */


/***********************************************************/
/* read a phy reg and return the value with a rc           */
/***********************************************************/

int miiphy_read (unsigned char addr, unsigned char reg,
				 unsigned short *value)
{
	unsigned long sta_reg;		/* STA scratch area */
	unsigned long i;

	/* see if it is ready for 1000 nsec */
	i = 0;

	/* see if it is ready for  sec */
	while ((in32 (EMAC_STACR) & EMAC_STACR_OC) == 0) {
		udelay (7);
		if (i > 5) {
#if 0	/* test-only */
			printf ("read err 1\n");
#endif
			return -1;
		}
		i++;
	}
	sta_reg = reg;				/* reg address */
	/* set clock (50Mhz) and read flags */
	sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
#ifdef CONFIG_PHY_CLK_FREQ
	sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
#endif
	sta_reg = sta_reg | (addr << 5);	/* Phy address */

	out32 (EMAC_STACR, sta_reg);
#if 0	/* test-only */
	printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg);	/* test-only */
#endif

	sta_reg = in32 (EMAC_STACR);
	i = 0;
	while ((sta_reg & EMAC_STACR_OC) == 0) {
		udelay (7);
		if (i > 5) {
#if 0	/* test-only */
			printf ("read err 2\n");
#endif
			return -1;
		}
		i++;
		sta_reg = in32 (EMAC_STACR);
	}
	if ((sta_reg & EMAC_STACR_PHYE) != 0) {
#if 0	/* test-only */
		printf ("read err 3\n");
		printf ("a2: read: EMAC_STACR=0x%0lx, i=%d\n",
			sta_reg, (int) i);	/* test-only */
#endif
		return -1;
	}

	*value = *(short *) (&sta_reg);
	return 0;


} /* phy_read */


/***********************************************************/
/* write a phy reg and return the value with a rc           */
/***********************************************************/

int miiphy_write (unsigned char addr, unsigned char reg,
		  unsigned short value)
{
	unsigned long sta_reg;		/* STA scratch area */
	unsigned long i;

	/* see if it is ready for 1000 nsec */
	i = 0;

	while ((in32 (EMAC_STACR) & EMAC_STACR_OC) == 0) {
		if (i > 5)
			return -1;
		udelay (7);
		i++;
	}
	sta_reg = 0;
	sta_reg = reg;				/* reg address */
	/* set clock (50Mhz) and read flags */
	sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
#ifdef CONFIG_PHY_CLK_FREQ
	sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */
#endif
	sta_reg = sta_reg | ((unsigned long) addr << 5);	/* Phy address */
	memcpy (&sta_reg, &value, 2);	/* put in data */

	out32 (EMAC_STACR, sta_reg);

	/* wait for completion */
	i = 0;
	sta_reg = in32 (EMAC_STACR);
	while ((sta_reg & EMAC_STACR_OC) == 0) {
		udelay (7);
		if (i > 5)
			return -1;
		i++;
		sta_reg = in32 (EMAC_STACR);
	}

	if ((sta_reg & EMAC_STACR_PHYE) != 0)
		return -1;
	return 0;

} /* phy_read */

#endif	/* CONFIG_405GP */