blob: 9fe379369a764379b3ff2e1df76f031dee7443b6 [file] [log] [blame]
Tom Rix3db7af72009-09-27 07:47:24 -05001/*
2 * (C) Copyright 2006
3 * Author : Eric Benard (Eukrea Electromatique)
4 * based on dm9161.c which is :
5 * (C) Copyright 2003
6 * Author : Hamid Ikdoumi (Atmel)
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
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.
15 *
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.
20 *
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,
24 * MA 02111-1307 USA
25 */
26
27#include <at91rm9200_net.h>
28#include <net.h>
29#include <ks8721.h>
30
31#ifdef CONFIG_DRIVER_ETHER
32
33#if defined(CONFIG_CMD_NET)
34
35/*
36 * Name:
37 * ks8721_isphyconnected
38 * Description:
39 * Reads the 2 PHY ID registers
40 * Arguments:
41 * p_mac - pointer to AT91S_EMAC struct
42 * Return value:
43 * 1 - if id read successfully
44 * 0 - if error
45 */
46unsigned int ks8721_isphyconnected(AT91PS_EMAC p_mac)
47{
48 unsigned short id1, id2;
49
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);
56
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 : ");
61 else
62 printf("Unknown Micrel PHY detected : ");
63 return 1;
64 }
65 return 0;
66}
67
68/*
69 * Name:
70 * ks8721_getlinkspeed
71 * Description:
72 * Link parallel detection status of MAC is checked and set in the
73 * MAC configuration registers
74 * Arguments:
75 * p_mac - pointer to MAC
76 * Return value:
77 * 1 - if link status set succesfully
78 * 0 - if link status not set
79 */
80unsigned char ks8721_getlinkspeed(AT91PS_EMAC p_mac)
81{
82 unsigned short stat1;
83
84 if (!at91rm9200_EmacReadPhy(p_mac, KS8721_BMSR, &stat1))
85 return 0;
86
87 if (!(stat1 & KS8721_LINK_STATUS)) {
88 /* link status up? */
89 printf("Link Down !\n");
90 return 0;
91 }
92
93 if (stat1 & KS8721_100BASE_TX_FD) {
94 /* set Emac for 100BaseTX and Full Duplex */
95 printf("100BT FD\n");
96 p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
97 return 1;
98 }
99
100 if (stat1 & KS8721_10BASE_T_FD) {
101 /* set MII for 10BaseT and Full Duplex */
102 printf("10BT FD\n");
103 p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
104 ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
105 | AT91C_EMAC_FD;
106 return 1;
107 }
108
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))
114 | AT91C_EMAC_SPD;
115 return 1;
116 }
117
118 if (stat1 & KS8721_10BASE_T_HD) {
119 /* set MII for 10BaseT and Half Duplex */
120 printf("10BT HD\n");
121 p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
122 return 1;
123 }
124 return 0;
125}
126
127/*
128 * Name:
129 * ks8721_initphy
130 * Description:
131 * MAC starts checking its link by using parallel detection and
132 * Autonegotiation and the same is set in the MAC configuration registers
133 * Arguments:
134 * p_mac - pointer to struct AT91S_EMAC
135 * Return value:
136 * 1 - if link status set succesfully
137 * 0 - if link status not set
138 */
139unsigned char ks8721_initphy(AT91PS_EMAC p_mac)
140{
141 unsigned char ret = 1;
142 unsigned short intvalue;
143
144 at91rm9200_EmacEnableMDIO(p_mac);
145
146 /* Try another time */
147 if (!ks8721_getlinkspeed(p_mac))
148 ret = ks8721_getlinkspeed(p_mac);
149
150 /* Disable PHY Interrupts */
151 intvalue = 0;
152 at91rm9200_EmacWritePhy(p_mac,
153 CONFIG_PHY_ADDRESS | KS8721_MDINTR, &intvalue);
154 at91rm9200_EmacDisableMDIO(p_mac);
155
156 return ret;
157}
158
159/*
160 * Name:
161 * ks8721_autonegotiate
162 * Description:
163 * MAC Autonegotiates with the partner status of same is set in the
164 * MAC configuration registers
165 * Arguments:
166 * dev - pointer to struct net_device
167 * Return value:
168 * 1 - if link status set successfully
169 * 0 - if link status not set
170 */
171unsigned char ks8721_autonegotiate(AT91PS_EMAC p_mac, int *status)
172{
173 unsigned short value;
174 unsigned short phyanar;
175 unsigned short phyanalpar;
176
177 /* Set ks8721 control register */
178 if (!at91rm9200_EmacReadPhy(p_mac,
179 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value))
180 return 0;
181
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)) {
188 return 0;
189 }
190 /*
191 * Set the Auto_negotiation Advertisement Register
192 * MII advertising for Next page, 100BaseTxFD and HD,
193 * 10BaseTFD and HD, IEEE 802.3
194 */
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)) {
199 return 0;
200 }
201 /* Read the Control Register */
202 if (!at91rm9200_EmacReadPhy(p_mac,
203 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
204 return 0;
205 }
206 value |= KS8721_SPEED_SELECT | KS8721_AUTONEG | KS8721_DUPLEX_MODE;
207 if (!at91rm9200_EmacWritePhy(p_mac,
208 CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
209 return 0;
210 }
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)) {
216 return 0;
217 }
218 /* Check AutoNegotiate complete */
219 udelay(10000);
220 at91rm9200_EmacReadPhy(p_mac,
221 CONFIG_PHY_ADDRESS | KS8721_BMSR, &value);
222 if (!(value & KS8721_AUTONEG_COMP))
223 return 0;
224
225 /* Get the AutoNeg Link partner base page */
226 if (!at91rm9200_EmacReadPhy(p_mac,
227 CONFIG_PHY_ADDRESS | KS8721_ANLPAR, &phyanalpar)) {
228 return 0;
229 }
230
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;
234 return 1;
235 }
236
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))
241 | AT91C_EMAC_FD;
242 return 1;
243 }
244 return 0;
245}
246
247#endif /* CONFIG_CMD_NET */
248
249#endif /* CONFIG_DRIVER_ETHER */