1 /* MII, MDIO and EEPROM interface of SiS 900
3 * Copyright 2001-2005 pinc Software. All Rights Reserved.
4 * Distributed under the terms of the MIT license.
9 #include <KernelExport.h>
10 #include <SupportDefs.h>
18 #include "ether_driver.h"
21 #include "interface.h"
25 // EEPROM access definitions
26 #define EEPROM_DELAY() read32(eepromAccess)
27 #define EEPROM_READ32() read32(eepromAccess)
28 #define EEPROM_WRITE8(value) write8(eepromAccess,value)
29 #define EEPROM_WRITE32(value) write32(eepromAccess,value)
33 eeprom_read(struct sis_info
*info
, int address
)
35 long eepromAccess
= (long)info
->registers
+ SiS900_MAC_EEPROM_ACCESS
;
36 uint32 readCmd
= SiS900_EEPROM_CMD_READ
| address
;
37 uint16 returnValue
= 0;
42 EEPROM_WRITE32(SiS900_EEPROM_CLOCK
);
45 // Shift the read command (9) bits out.
46 for (i
= 8; i
>= 0; i
--) {
47 uint32 value
= (readCmd
& (1 << i
)) ? SiS900_EEPROM_DATA_IN
| SiS900_EEPROM_SELECT
48 : SiS900_EEPROM_SELECT
;
50 EEPROM_WRITE32(value
);
52 EEPROM_WRITE32(value
| SiS900_EEPROM_CLOCK
);
56 EEPROM_WRITE8(SiS900_EEPROM_SELECT
);
59 // read in the 16 bit data
60 for (i
= 16; i
> 0; i
--) {
61 EEPROM_WRITE32(SiS900_EEPROM_SELECT
);
63 EEPROM_WRITE32(SiS900_EEPROM_SELECT
| SiS900_EEPROM_CLOCK
);
65 returnValue
= (returnValue
<< 1) | ((EEPROM_READ32() & SiS900_EEPROM_DATA_OUT
) ? 1 : 0);
71 EEPROM_WRITE32(SiS900_EEPROM_CLOCK
);
77 /**************************** MII/MDIO ****************************/
82 mdio_delay(addr_t address
)
84 return read32(address
);
89 mdio_idle(uint32 address
)
91 write32(address
, SiS900_MII_MDIO
| SiS900_MII_MDDIR
);
93 write32(address
, SiS900_MII_MDIO
| SiS900_MII_MDDIR
| SiS900_MII_MDC
);
98 mdio_reset(uint32 address
)
102 for (i
= 32; i
-- > 0;) {
103 write32(address
, SiS900_MII_MDIO
| SiS900_MII_MDDIR
);
105 write32(address
, SiS900_MII_MDIO
| SiS900_MII_MDDIR
| SiS900_MII_MDC
);
112 mdio_writeToPHY(struct sis_info
*info
, uint16 phy
, uint16 reg
, uint16 value
)
114 uint32 address
= info
->registers
+ SiS900_MAC_EEPROM_ACCESS
;
115 int32 cmd
= MII_CMD_WRITE
| (phy
<< MII_PHY_SHIFT
) | (reg
<< MII_REG_SHIFT
);
122 for (i
= 16; i
-- > 0;) {
123 int32 data
= SiS900_MII_MDDIR
| (cmd
& (1 << i
) ? SiS900_MII_MDIO
: 0);
125 write8(address
, data
);
127 write8(address
, data
| SiS900_MII_MDC
);
133 for (i
= 16; i
-- > 0;) {
134 int32 data
= SiS900_MII_MDDIR
| (value
& (1 << i
) ? SiS900_MII_MDIO
: 0);
136 write32(address
, data
);
138 write32(address
, data
| SiS900_MII_MDC
);
144 for (i
= 2; i
-- > 0;) {
147 write8(address
, SiS900_MII_MDC
);
156 mdio_readFromPHY(struct sis_info
*info
, uint16 phy
, uint16 reg
)
158 uint32 address
= info
->registers
+ SiS900_MAC_EEPROM_ACCESS
;
159 int32 cmd
= MII_CMD_READ
| (phy
<< MII_PHY_SHIFT
) | (reg
<< MII_REG_SHIFT
);
166 for (i
= 16; i
-- > 0;) {
167 int32 data
= SiS900_MII_MDDIR
| (cmd
& (1 << i
) ? SiS900_MII_MDIO
: 0);
169 write32(address
, data
);
171 write32(address
, data
| SiS900_MII_MDC
);
176 for (i
= 16; i
-- > 0;) {
179 value
= (value
<< 1) | (read32(address
) & SiS900_MII_MDIO
? 1 : 0);
180 write32(address
, SiS900_MII_MDC
);
190 mdio_read(struct sis_info
*info
, uint16 reg
)
192 return mdio_readFromPHY(info
, info
->phy
, reg
);
197 mdio_write(struct sis_info
*info
, uint16 reg
, uint16 value
)
199 mdio_writeToPHY(info
,info
->phy
,reg
,value
);
204 mdio_statusFromPHY(struct sis_info
*info
, uint16 phy
)
209 // the status must be retrieved two times, because the first
210 // one may not work on some PHYs (notably ICS 1893)
212 status
= mdio_readFromPHY(info
, phy
, MII_STATUS
);
219 mdio_status(struct sis_info
*info
)
221 return mdio_statusFromPHY(info
, info
->phy
);