3 * Author : Eric Benard (Eukrea Electromatique)
4 * based on dm9161.c which is :
6 * Author : Hamid Ikdoumi (Atmel)
8 * See file CREDITS for list of people who contributed to this
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 #include <at91rm9200_net.h>
31 #ifdef CONFIG_DRIVER_ETHER
33 #if defined(CONFIG_CMD_NET)
37 * ks8721_isphyconnected
39 * Reads the 2 PHY ID registers
41 * p_mac - pointer to AT91S_EMAC struct
43 * 1 - if id read successfully
46 unsigned int ks8721_isphyconnected(AT91PS_EMAC p_mac)
48 unsigned short id1, id2;
50 at91rm9200_EmacEnableMDIO(p_mac);
51 at91rm9200_EmacReadPhy(p_mac,
52 CONFIG_PHY_ADDRESS | KS8721_PHYID1, &id1);
53 at91rm9200_EmacReadPhy(p_mac,
54 CONFIG_PHY_ADDRESS | KS8721_PHYID2, &id2);
55 at91rm9200_EmacDisableMDIO(p_mac);
57 if ((id1 == (KS8721_PHYID_OUI >> 6)) &&
58 ((id2 >> 10) == (KS8721_PHYID_OUI & KS8721_LSB_MASK))) {
59 if ((id2 & KS8721_MODELMASK) == KS8721BL_MODEL)
60 printf("Micrel KS8721bL PHY detected : ");
62 printf("Unknown Micrel PHY detected : ");
72 * Link parallel detection status of MAC is checked and set in the
73 * MAC configuration registers
75 * p_mac - pointer to MAC
77 * 1 - if link status set succesfully
78 * 0 - if link status not set
80 unsigned char ks8721_getlinkspeed(AT91PS_EMAC p_mac)
84 if (!at91rm9200_EmacReadPhy(p_mac, KS8721_BMSR, &stat1))
87 if (!(stat1 & KS8721_LINK_STATUS)) {
89 printf("Link Down !\n");
93 if (stat1 & KS8721_100BASE_TX_FD) {
94 /* set Emac for 100BaseTX and Full Duplex */
96 p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
100 if (stat1 & KS8721_10BASE_T_FD) {
101 /* set MII for 10BaseT and Full Duplex */
103 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
104 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
109 if (stat1 & KS8721_100BASE_T4_HD) {
110 /* set MII for 100BaseTX and Half Duplex */
111 printf("100BT HD\n");
112 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
113 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
118 if (stat1 & KS8721_10BASE_T_HD) {
119 /* set MII for 10BaseT and Half Duplex */
121 p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
131 * MAC starts checking its link by using parallel detection and
132 * Autonegotiation and the same is set in the MAC configuration registers
134 * p_mac - pointer to struct AT91S_EMAC
136 * 1 - if link status set succesfully
137 * 0 - if link status not set
139 unsigned char ks8721_initphy(AT91PS_EMAC p_mac)
141 unsigned char ret = 1;
142 unsigned short intvalue;
144 at91rm9200_EmacEnableMDIO(p_mac);
146 /* Try another time */
147 if (!ks8721_getlinkspeed(p_mac))
148 ret = ks8721_getlinkspeed(p_mac);
150 /* Disable PHY Interrupts */
152 at91rm9200_EmacWritePhy(p_mac,
153 CONFIG_PHY_ADDRESS | KS8721_MDINTR, &intvalue);
154 at91rm9200_EmacDisableMDIO(p_mac);
161 * ks8721_autonegotiate
163 * MAC Autonegotiates with the partner status of same is set in the
164 * MAC configuration registers
166 * dev - pointer to struct net_device
168 * 1 - if link status set successfully
169 * 0 - if link status not set
171 unsigned char ks8721_autonegotiate(AT91PS_EMAC p_mac, int *status)
173 unsigned short value;
174 unsigned short phyanar;
175 unsigned short phyanalpar;
177 /* Set ks8721 control register */
178 if (!at91rm9200_EmacReadPhy(p_mac,
179 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value))
182 /* remove autonegotiation enable */
183 value &= ~KS8721_AUTONEG;
184 /* Electrically isolate PHY */
185 value |= KS8721_ISOLATE;
186 if (!at91rm9200_EmacWritePhy(p_mac,
187 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
191 * Set the Auto_negotiation Advertisement Register
192 * MII advertising for Next page, 100BaseTxFD and HD,
193 * 10BaseTFD and HD, IEEE 802.3
195 phyanar = KS8721_NP | KS8721_TX_FDX | KS8721_TX_HDX |
196 KS8721_10_FDX | KS8721_10_HDX | KS8721_AN_IEEE_802_3;
197 if (!at91rm9200_EmacWritePhy(p_mac,
198 CONFIG_PHY_ADDRESS | KS8721_ANAR, &phyanar)) {
201 /* Read the Control Register */
202 if (!at91rm9200_EmacReadPhy(p_mac,
203 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
206 value |= KS8721_SPEED_SELECT | KS8721_AUTONEG | KS8721_DUPLEX_MODE;
207 if (!at91rm9200_EmacWritePhy(p_mac,
208 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
211 /* Restart Auto_negotiation */
212 value |= KS8721_RESTART_AUTONEG;
213 value &= ~KS8721_ISOLATE;
214 if (!at91rm9200_EmacWritePhy(p_mac,
215 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
218 /* Check AutoNegotiate complete */
220 at91rm9200_EmacReadPhy(p_mac,
221 CONFIG_PHY_ADDRESS | KS8721_BMSR, &value);
222 if (!(value & KS8721_AUTONEG_COMP))
225 /* Get the AutoNeg Link partner base page */
226 if (!at91rm9200_EmacReadPhy(p_mac,
227 CONFIG_PHY_ADDRESS | KS8721_ANLPAR, &phyanalpar)) {
231 if ((phyanar & KS8721_TX_FDX) && (phyanalpar & KS8721_TX_FDX)) {
232 /* Set MII for 100BaseTX and Full Duplex */
233 p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
237 if ((phyanar & KS8721_10_FDX) && (phyanalpar & KS8721_10_FDX)) {
238 /* Set MII for 10BaseT and Full Duplex */
239 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
240 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
247 #endif /* CONFIG_CMD_NET */
249 #endif /* CONFIG_DRIVER_ETHER */