• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/net/
1/*
2 * drivers/net/titan_mdio.c - Driver for Titan ethernet ports
3 *
4 * Copyright (C) 2003 PMC-Sierra Inc.
5 * Author : Manish Lachwani (lachwani@pmc-sierra.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * Management Data IO (MDIO) driver for the Titan GMII. Interacts with the Marvel PHY
22 * on the Titan. No support for the TBI as yet.
23 *
24 */
25
26#include	"titan_mdio.h"
27
28#define MDIO_DEBUG
29
30/*
31 * Local constants
32 */
33#define MAX_CLKA            1023
34#define MAX_PHY_DEV         31
35#define MAX_PHY_REG         31
36#define WRITEADDRS_OPCODE   0x0
37#define	READ_OPCODE	    0x2
38#define WRITE_OPCODE        0x1
39#define MAX_MDIO_POLL       100
40
41/*
42 * Titan MDIO and SCMB registers
43 */
44#define TITAN_GE_SCMB_CONTROL                0x01c0  /* SCMB Control */
45#define TITAN_GE_SCMB_CLKA	             0x01c4  /* SCMB Clock A */
46#define TITAN_GE_MDIO_COMMAND                0x01d0  /* MDIO Command */
47#define TITAN_GE_MDIO_DEVICE_PORT_ADDRESS    0x01d4  /* MDIO Device and Port addrs */
48#define TITAN_GE_MDIO_DATA                   0x01d8  /* MDIO Data */
49#define TITAN_GE_MDIO_INTERRUPTS             0x01dC  /* MDIO Interrupts */
50
51/*
52 * Function to poll the MDIO
53 */
54static int titan_ge_mdio_poll(void)
55{
56	int	i, val;
57
58	for (i = 0; i < MAX_MDIO_POLL; i++) {
59		val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND);
60
61		if (!(val & 0x8000))
62			return TITAN_GE_MDIO_GOOD;
63	}
64
65	return TITAN_GE_MDIO_ERROR;
66}
67
68
69/*
70 * Initialize and configure the MDIO
71 */
72int titan_ge_mdio_setup(titan_ge_mdio_config *titan_mdio)
73{
74	unsigned long	val;
75
76	/* Reset the SCMB and program into MDIO mode*/
77	TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CONTROL, 0x9000);
78	TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CONTROL, 0x1000);
79
80	/* CLK A */
81	val = TITAN_GE_MDIO_READ(TITAN_GE_SCMB_CLKA);
82	val = ( (val & ~(0x03ff)) | (titan_mdio->clka & 0x03ff));
83	TITAN_GE_MDIO_WRITE(TITAN_GE_SCMB_CLKA, val);
84
85	/* Preamble Suppresion */
86	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND);
87	val = ( (val & ~(0x0001)) | (titan_mdio->mdio_spre & 0x0001));
88	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val);
89
90	/* MDIO mode */
91	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS);
92	val = ( (val & ~(0x4000)) | (titan_mdio->mdio_mode & 0x4000));
93	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val);
94
95	return TITAN_GE_MDIO_GOOD;
96}
97
98/*
99 * Set the PHY address in indirect mode
100 */
101int titan_ge_mdio_inaddrs(int dev_addr, int reg_addr)
102{
103	volatile unsigned long	val;
104
105	/* Setup the PHY device */
106	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS);
107	val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00));
108	val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f));
109	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val);
110
111	/* Write the new address */
112	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND);
113	val = ( (val & ~(0x0300)) | ( (WRITEADDRS_OPCODE << 8) & 0x0300));
114	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val);
115
116	return TITAN_GE_MDIO_GOOD;
117}
118
119/*
120 * Read the MDIO register. This is what the individual parametes mean:
121 *
122 * dev_addr : PHY ID
123 * reg_addr : register offset
124 *
125 * See the spec for the Titan MAC. We operate in the Direct Mode.
126 */
127
128#define MAX_RETRIES	2
129
130int titan_ge_mdio_read(int dev_addr, int reg_addr, unsigned int *pdata)
131{
132	volatile unsigned long	val;
133	int retries = 0;
134
135	/* Setup the PHY device */
136
137again:
138	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS);
139	val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00));
140	val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f));
141	val |= 0x4000;
142	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val);
143
144	udelay(30);
145
146	/* Issue the read command */
147	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND);
148	val = ( (val & ~(0x0300)) | ( (READ_OPCODE << 8) & 0x0300));
149	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val);
150
151	udelay(30);
152
153	if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD)
154		return TITAN_GE_MDIO_ERROR;
155
156	*pdata = (unsigned int)TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DATA);
157	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_INTERRUPTS);
158
159	udelay(30);
160
161	if (val & 0x2) {
162		if (retries == MAX_RETRIES)
163			return TITAN_GE_MDIO_ERROR;
164		else {
165			retries++;
166			goto again;
167		}
168	}
169
170	return TITAN_GE_MDIO_GOOD;
171}
172
173/*
174 * Write to the MDIO register
175 *
176 * dev_addr : PHY ID
177 * reg_addr : register that needs to be written to
178 *
179 */
180int titan_ge_mdio_write(int dev_addr, int reg_addr, unsigned int data)
181{
182	volatile unsigned long	val;
183
184	if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD)
185		return TITAN_GE_MDIO_ERROR;
186
187	/* Setup the PHY device */
188	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS);
189	val = ( (val & ~(0x1f00)) | ( (dev_addr << 8) & 0x1f00));
190	val = ( (val & ~(0x001f)) | ( reg_addr & 0x001f));
191	val |= 0x4000;
192	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DEVICE_PORT_ADDRESS, val);
193
194	udelay(30);
195
196	/* Setup the data to write */
197	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_DATA, data);
198
199	udelay(30);
200
201	/* Issue the write command */
202	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_COMMAND);
203	val = ( (val & ~(0x0300)) | ( (WRITE_OPCODE << 8) & 0x0300));
204	TITAN_GE_MDIO_WRITE(TITAN_GE_MDIO_COMMAND, val);
205
206	udelay(30);
207
208	if (titan_ge_mdio_poll() != TITAN_GE_MDIO_GOOD)
209		return TITAN_GE_MDIO_ERROR;
210
211	val = TITAN_GE_MDIO_READ(TITAN_GE_MDIO_INTERRUPTS);
212	if (val & 0x2)
213		return TITAN_GE_MDIO_ERROR;
214
215	return TITAN_GE_MDIO_GOOD;
216}
217