]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/arm920t/at91rm9200/ks8721.c
omap4: clock init support for omap4460
[karo-tx-uboot.git] / arch / arm / cpu / arm920t / at91rm9200 / ks8721.c
1 /*
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  */
46 unsigned 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  */
80 unsigned 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  */
139 unsigned 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  */
171 unsigned 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 */