[coldfire]: 2.6.31 support (WiP)
[openwrt.git] / target / linux / coldfire / files-2.6.31 / drivers / net / phy / broadcom522x.c
1 /*
2 *Copyright (C) 2009 Freescale Semiconductor, Inc. All rights reserved.
3 * Chenghu Wu <b16972@freescale.com>
4 *
5 * Driver for broadcom PHYs 522x
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/mii.h>
17 #include <linux/ethtool.h>
18 #include <linux/phy.h>
19 #include <linux/netdevice.h>
20
21 /* DP83865 phy identifier values */
22 #define BCM5222_PHY_ID 0x00406320
23
24 /* PHY Register */
25 #define BCM5222_TIMEOUT 0x100
26
27 /* MII Registers */
28 #define BCM5222_CTRL 0x00
29 #define BCM5222_STATUS 0x01
30 #define BCM5222_ID_HIGH 0x02
31 #define BCM5222_ID_LOW 0x03
32 #define BCM5222_AN_ADV 0x04
33 #define BCM5222_AN_LP 0x05
34 #define BCM5222_AN_EXP 0x06
35 #define BCM5222_AN_NEXTPG 0x07
36 #define BCM5222_AN_LP_NPTX 0x08
37 #define BCM5222_AUX_CS 0x18
38 #define BCM5222_AUX_STATUS 0x19
39
40 /* CONTROL Bits */
41 #define BCM5222_CTRL_RESET 0x8000
42 #define BCM5222_CTRL_LOOPBACK 0x4000
43 #define BCM5222_CTRL_FORCE 0x2000
44 #define BCM5222_CTRL_AUTOEN 0x1000
45 #define BCM5222_CTRL_PWRDN 0x0800
46 #define BCM5222_CTRL_ISOLATE 0x0400
47 #define BCM5222_CTRL_RESTART 0x0200
48 #define BCM5222_CTRL_DUPLEX 0x0100
49 #define BCM5222_CTRL_COLLEN 0x0080
50
51 /* STATUS Bits */
52 #define BCM5222_STATUS_100T4 0x8000
53 #define BCM5222_STATUS_100TXFDX 0x4000
54 #define BCM5222_STATUS_100TX 0x2000
55 #define BCM5222_STATUS_10FDX 0x1000
56 #define BCM5222_STATUS_10 0x0800
57 #define BCM5222_STATUS_MF_PREAMBLE 0x0040
58 #define BCM5222_STATUS_AN_COMPLETE 0x0020
59 #define BCM5222_STATUS_REMOTE_FAULT 0x0010
60 #define BCM5222_STATUS_AN_CAPABLE 0x0008
61 #define BCM5222_STATUS_LINK 0x0004
62 #define BCM5222_STATUS_JABBER 0x0002
63 #define BCM5222_STATUS_EXT_CAP 0x0001
64
65 /* ID Values */
66 #define BCM5222_ID_HIGH_VAL 0x0040
67 #define BCM5222_ID_LOW_VAL 0x6320
68
69 /* Advertise Bits */
70 #define BCM5222_AN_ADV_NEXTPG 0x8000
71 #define BCM5222_AN_ADV_REMOTE_FAULT 0x2000
72 #define BCM5222_AN_ADV_PAUSE 0x0400
73 #define BCM5222_AN_ADV_100T4 0x0200
74 #define BCM5222_AN_ADV_100TXFDX 0x0100
75 #define BCM5222_AN_ADV_100TX 0x0080
76 #define BCM5222_AN_ADV_10FDX 0x0040
77 #define BCM5222_AN_ADV_10 0x0020
78 #define BCM5222_AN_ADV_8023 0x0001
79 #define BCM5222_AN_ADV_ALL \
80 (BCM5222_AN_ADV_100TXFDX | \
81 BCM5222_AN_ADV_100TXFDX | \
82 BCM5222_AN_ADV_100TX | \
83 BCM5222_AN_ADV_10FDX | \
84 BCM5222_AN_ADV_10 | \
85 BCM5222_AN_ADV_8023)
86
87 /* AUX CTRL/STATUS Bits */
88 #define BCM5222_AUX_CS_JABBER_DIS 0x8000
89 #define BCM5222_AUX_CS_FORCE_LINK 0x4000
90 #define BCM5222_AUX_CS_10M_TX_PWR 0x0100
91 #define BCM5222_AUX_CS_HSQ_LSQ_MASK 0x00c0
92 #define BCM5222_AUX_CS_EDGE_RATE_MASK 0x0030
93 #define BCM5222_AUX_CS_AN_IND 0x0008
94 #define BCM5222_AUX_CS_SPEED_FORCE 0x0004
95 #define BCM5222_AUX_CS_SPEED 0x0002
96 #define BCM5222_AUX_CS_DUPLEX 0x0001
97
98 /* AUX STATUS Bits */
99 #define BCM5222_AUX_STATUS_AN_COMP 0x8000
100 #define BCM5222_AUX_STATUS_AN_COMPACK 0x4000
101 #define BCM5222_AUX_STATUS_AN_ACKDET 0x2000
102 #define BCM5222_AUX_STATUS_AN_ABDET 0x1000
103 #define BCM5222_AUX_STATUS_AN_PAUSE 0x0800
104 #define BCM5222_AUX_STATUS_AN_HCDMASK 0x0700
105 #define BCM5222_AUX_STATUS_AN_PDFAULT 0x0080
106 #define BCM5222_AUX_STATUS_LP_RMTFAULT 0x0040
107 #define BCM5222_AUX_STATUS_LP_PGRX 0x0020
108 #define BCM5222_AUX_STATUS_LP_NEGABLE 0x0010
109 #define BCM5222_AUX_STATUS_SPEED 0x0008
110 #define BCM5222_AUX_STATUS_LINK 0x0004
111 #define BCM5222_AUX_STATUS_AN_EN 0x0002
112 #define BCM5222_AUX_STATUS_JABBER 0x0001
113
114 static int bcm5222_config_intr(struct phy_device *phydev)
115 {
116 int err = 0;
117 printk(KERN_INFO "%s PHY_INTERRUPT %x\n",
118 __func__, phydev->interrupts);
119
120 return err;
121 }
122
123 static int bcm5222_ack_interrupt(struct phy_device *phydev)
124 {
125 return 0;
126 }
127
128 static int bcm5222_config_init(struct phy_device *phydev)
129 {
130 return bcm5222_ack_interrupt(phydev);
131 }
132
133 static int bcm5222_config_init_old(struct phy_device *phydev)
134 {
135 int timeout;
136 int flag = 1;
137 int ret = phy_read(phydev, BCM5222_AUX_STATUS);
138 if (ret < 0) {
139 printk(KERN_INFO "%s MII_BCM5222_ISR %x\n",
140 __func__, ret);
141 }
142 /*
143 * reset
144 */
145 phy_write(phydev, BCM5222_CTRL, BCM5222_CTRL_RESET);
146
147 /* check that it cleared */
148 ret = phy_read(phydev, BCM5222_CTRL);
149 printk(KERN_INFO "%s BCM5222_CTRL %x\n",
150 __func__, ret);
151 /*if reset bit is set, return */
152 if (ret & BCM5222_CTRL_RESET) {
153 printk(KERN_ERR "%s %x = BCM5222_CTRL_RESET(%x)\n",
154 __func__, ret, BCM5222_CTRL_RESET);
155 return -ETIME;
156 }
157
158 /*
159 * setup auto-negotiation
160 */
161
162 /* disable */
163 phy_write(phydev, BCM5222_CTRL, 0);
164 ret = phy_read(phydev, BCM5222_CTRL);
165 printk(KERN_INFO "%s BCM5222_CTRL %x\n",
166 __func__, ret);
167 /* set the auto-negotiation advertisement register */
168 phy_write(phydev, BCM5222_AN_ADV, BCM5222_AN_ADV_ALL);
169 ret = phy_read(phydev, BCM5222_AN_ADV);
170 printk(KERN_INFO "%s BCM5222_AN_ADV %x, BCM5222_AN_ADV_ALL %x\n",
171 __func__, ret, BCM5222_AN_ADV_ALL);
172 /* enable */
173 phy_write(phydev, BCM5222_CTRL, BCM5222_CTRL_AUTOEN);
174 ret = phy_read(phydev, BCM5222_CTRL);
175 printk(KERN_INFO "%s BCM5222_CTRL %x\n",
176 __func__, ret);
177 printk(KERN_INFO "** wait for complete\n");
178
179 /* read aux status reg */
180 ret = phy_read(phydev, BCM5222_AUX_STATUS);
181 /* Wait for the auto-negotiation completion */
182 timeout = BCM5222_TIMEOUT;
183 while (!(ret & BCM5222_AUX_STATUS_AN_COMP)) {
184 if (!timeout--) {
185 flag = 0;
186 printk(KERN_INFO "BCM5222: TIMEOUT\n");
187 break;
188 }
189
190 mdelay(10);
191 /* Read PHY status register */
192 ret = phy_read(phydev, BCM5222_AUX_STATUS);
193 }
194
195 ret = phy_read(phydev, BCM5222_AUX_STATUS);
196 ret = phy_read(phydev, BCM5222_AN_ADV);
197 return 0;
198 }
199
200 static int bcm5222_read_status(struct phy_device *phydev)
201 {
202 int ret;
203 ret = phy_read(phydev, BCM5222_AUX_STATUS);
204 printk(KERN_INFO "%s ret %x\n", __func__, ret);
205
206 if (ret & BCM5222_AUX_STATUS_LINK)
207 phydev->link = 1;
208 else
209 phydev->link = 0;
210
211 if (ret & BCM5222_AUX_STATUS_SPEED)
212 phydev->speed = SPEED_100;
213 else
214 phydev->speed = SPEED_10;
215
216 ret = phy_read(phydev, BCM5222_AUX_CS);
217 printk(KERN_INFO "%s ret %x\n", __func__, ret);
218 if (ret & BCM5222_AUX_CS_DUPLEX)
219 phydev->duplex = DUPLEX_FULL;
220 else
221 phydev->duplex = DUPLEX_HALF;
222 return 0;
223 }
224
225 static int bcm5222_config_aneg(struct phy_device *phydev)
226 {
227 phy_read(phydev, BCM5222_AUX_STATUS);
228 phy_read(phydev, BCM5222_AN_ADV);
229 return 0;
230 }
231
232 static struct phy_driver bcm5222_driver = {
233 .phy_id = BCM5222_PHY_ID,
234 .phy_id_mask = 0xfffffff0,
235 .name = "Broadcom BCM5222",
236 .features = PHY_BASIC_FEATURES,
237 .flags = PHY_HAS_INTERRUPT,
238 .config_init = bcm5222_config_init,
239 .config_aneg = genphy_config_aneg,
240 .read_status = genphy_read_status,
241 .ack_interrupt = bcm5222_ack_interrupt,
242 .config_intr = bcm5222_config_intr,
243 .driver = {.owner = THIS_MODULE,}
244 };
245
246 static int __init bcm5222_init(void)
247 {
248 int ret;
249
250 ret = phy_driver_register(&bcm5222_driver);
251 if (ret)
252 goto err1;
253
254 return 0;
255 err1:
256 printk(KERN_INFO "register bcm5222 PHY driver fail\n");
257 return ret;
258 }
259
260 static void __exit bcm5222_exit(void)
261 {
262 phy_driver_unregister(&bcm5222_driver);
263 }
264
265 MODULE_DESCRIPTION("Broadcom PHY driver");
266 MODULE_LICENSE("GPL v2");
267
268 module_init(bcm5222_init);
269 module_exit(bcm5222_exit);
This page took 0.067105 seconds and 5 git commands to generate.