2 * Copyright (c) 2003-2004 Stefano Ceccherini (burton666@libero.it)
3 * Copyright (c) 1997, 1998
4 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Bill Paul.
17 * 4. Neither the name of the author nor the names of any co-contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
37 #include "interface.h"
39 #include <ByteOrder.h>
40 #include <KernelExport.h>
46 write32(device->reg_base + WB_SIO, \
47 read32(device->reg_base + WB_SIO) | x)
50 write32(device->reg_base + WB_SIO, \
51 read32(device->reg_base + WB_SIO) & ~x)
53 #define MII_DELAY(x) read32(x->reg_base + WB_SIO)
57 mii_sync(struct wb_device
*device
)
59 // Set data bit and strobe the clock 32 times
62 SIO_SET(WB_SIO_MII_DIR
|WB_SIO_MII_DATAIN
);
65 SIO_SET(WB_SIO_MII_CLK
);
67 SIO_CLR(WB_SIO_MII_CLK
);
74 mii_send(wb_device
*device
, uint32 bits
, int count
)
78 SIO_CLR(WB_SIO_MII_CLK
);
80 for (i
= (0x1 << (count
- 1)); i
; i
>>= 1) {
82 SIO_SET(WB_SIO_MII_DATAIN
);
84 SIO_CLR(WB_SIO_MII_DATAIN
);
86 SIO_CLR(WB_SIO_MII_CLK
);
88 SIO_SET(WB_SIO_MII_CLK
);
93 * Read an PHY register through the MII.
96 wb_mii_readreg(wb_device
*device
, wb_mii_frame
*frame
)
101 * Set up frame for RX.
103 frame
->mii_stdelim
= WB_MII_STARTDELIM
;
104 frame
->mii_opcode
= WB_MII_READOP
;
105 frame
->mii_turnaround
= 0;
108 write32(device
->reg_base
+ WB_SIO
, 0);
113 SIO_SET(WB_SIO_MII_DIR
);
118 * Send command/address info.
120 mii_send(device
, frame
->mii_stdelim
, 2);
121 mii_send(device
, frame
->mii_opcode
, 2);
122 mii_send(device
, frame
->mii_phyaddr
, 5);
123 mii_send(device
, frame
->mii_regaddr
, 5);
126 SIO_CLR((WB_SIO_MII_CLK
|WB_SIO_MII_DATAIN
));
128 SIO_SET(WB_SIO_MII_CLK
);
132 SIO_CLR(WB_SIO_MII_DIR
);
134 SIO_CLR(WB_SIO_MII_CLK
);
136 ack
= read32(device
->reg_base
+ WB_SIO
) & WB_SIO_MII_DATAOUT
;
137 SIO_SET(WB_SIO_MII_CLK
);
139 SIO_CLR(WB_SIO_MII_CLK
);
141 SIO_SET(WB_SIO_MII_CLK
);
145 * Now try reading data bits. If the ack failed, we still
146 * need to clock through 16 cycles to keep the PHY(s) in sync.
149 for(i
= 0; i
< 16; i
++) {
150 SIO_CLR(WB_SIO_MII_CLK
);
152 SIO_SET(WB_SIO_MII_CLK
);
158 for (i
= 0x8000; i
; i
>>= 1) {
159 SIO_CLR(WB_SIO_MII_CLK
);
162 if (read32(device
->reg_base
+ WB_SIO
) & WB_SIO_MII_DATAOUT
)
163 frame
->mii_data
|= i
;
166 SIO_SET(WB_SIO_MII_CLK
);
172 SIO_CLR(WB_SIO_MII_CLK
);
174 SIO_SET(WB_SIO_MII_CLK
);
183 * Write to a PHY register through the MII.
186 wb_mii_writereg(wb_device
*device
, wb_mii_frame
*frame
)
189 * Set up frame for TX.
192 frame
->mii_stdelim
= WB_MII_STARTDELIM
;
193 frame
->mii_opcode
= WB_MII_WRITEOP
;
194 frame
->mii_turnaround
= WB_MII_TURNAROUND
;
197 * Turn on data output.
199 SIO_SET(WB_SIO_MII_DIR
);
203 mii_send(device
, frame
->mii_stdelim
, 2);
204 mii_send(device
, frame
->mii_opcode
, 2);
205 mii_send(device
, frame
->mii_phyaddr
, 5);
206 mii_send(device
, frame
->mii_regaddr
, 5);
207 mii_send(device
, frame
->mii_turnaround
, 2);
208 mii_send(device
, frame
->mii_data
, 16);
211 SIO_SET(WB_SIO_MII_CLK
);
213 SIO_CLR(WB_SIO_MII_CLK
);
219 SIO_CLR(WB_SIO_MII_DIR
);
226 wb_miibus_readreg(wb_device
*device
, int phy
, int reg
)
228 struct wb_mii_frame frame
;
230 memset(&frame
, 0, sizeof(frame
));
232 frame
.mii_phyaddr
= phy
;
233 frame
.mii_regaddr
= reg
;
234 wb_mii_readreg(device
, &frame
);
236 return frame
.mii_data
;
241 wb_miibus_writereg(wb_device
*device
, int phy
, int reg
, int data
)
243 struct wb_mii_frame frame
;
245 memset(&frame
, 0, sizeof(frame
));
247 frame
.mii_phyaddr
= phy
;
248 frame
.mii_regaddr
= reg
;
249 frame
.mii_data
= data
;
251 wb_mii_writereg(device
, &frame
);
257 #define EEPROM_DELAY(x) read32(x->reg_base + WB_SIO)
261 wb_eeprom_putbyte(wb_device
*device
, int addr
)
266 d
= addr
| WB_EECMD_READ
;
269 * Feed in each bit and strobe the clock.
271 for (i
= 0x400; i
; i
>>= 1) {
273 SIO_SET(WB_SIO_EE_DATAIN
);
275 SIO_CLR(WB_SIO_EE_DATAIN
);
277 for (delay
= 0; delay
< 100; delay
++)
280 SIO_SET(WB_SIO_EE_CLK
);
282 for (delay
= 0; delay
< 150; delay
++)
285 SIO_CLR(WB_SIO_EE_CLK
);
287 for (delay
= 0; delay
< 100; delay
++)
298 wb_eeprom_askdata(wb_device
*device
, int addr
)
303 command
= addr
| WB_EECMD_READ
;
305 /* Feed in each bit and strobe the clock. */
306 for(i
= 0x400; i
; i
>>= 1) {
308 SIO_SET(WB_SIO_EE_DATAIN
);
310 SIO_CLR(WB_SIO_EE_DATAIN
);
312 SIO_SET(WB_SIO_EE_CLK
);
314 SIO_CLR(WB_SIO_EE_CLK
);
315 for (delay
= 0; delay
< 100; delay
++)
316 EEPROM_DELAY(device
);
321 /* Read a word of data stored in the EEPROM at address "addr". */
323 wb_eeprom_getword(wb_device
*device
, int addr
, uint16
*dest
)
328 /* Enter EEPROM access mode */
329 write32(device
->reg_base
+ WB_SIO
, WB_SIO_EESEL
|WB_SIO_EE_CS
);
331 /* Send address of word we want to read. */
332 wb_eeprom_askdata(device
, addr
);
334 write32(device
->reg_base
+ WB_SIO
, WB_SIO_EESEL
|WB_SIO_EE_CS
);
336 /* Start reading bits from EEPROM */
337 for (i
= 0x8000; i
> 0; i
>>= 1) {
338 SIO_SET(WB_SIO_EE_CLK
);
339 if (read32(device
->reg_base
+ WB_SIO
) & WB_SIO_EE_DATAOUT
)
341 SIO_CLR(WB_SIO_EE_CLK
);
344 /* Turn off EEPROM access mode */
345 write32(device
->reg_base
+ WB_SIO
, 0);
352 wb_read_eeprom(wb_device
*device
, void* dest
,
353 int offset
, int count
, bool swap
)
356 uint16 word
= 0, *ptr
;
358 for (i
= 0; i
< count
; i
++) {
359 wb_eeprom_getword(device
, offset
+ i
, &word
);
360 ptr
= (uint16
*)((uint8
*)dest
+ (i
* 2));