Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
[sfrench/cifs-2.6.git] / drivers / net / phy / marvell.c
1 /*
2  * drivers/net/phy/marvell.c
3  *
4  * Driver for Marvell PHYs
5  *
6  * Author: Andy Fleming
7  *
8  * Copyright (c) 2004 Freescale Semiconductor, Inc.
9  *
10  * This program is free software; you can redistribute  it and/or modify it
11  * under  the terms of  the GNU General  Public License as published by the
12  * Free Software Foundation;  either version 2 of the  License, or (at your
13  * option) any later version.
14  *
15  */
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/unistd.h>
20 #include <linux/slab.h>
21 #include <linux/interrupt.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/netdevice.h>
25 #include <linux/etherdevice.h>
26 #include <linux/skbuff.h>
27 #include <linux/spinlock.h>
28 #include <linux/mm.h>
29 #include <linux/module.h>
30 #include <linux/mii.h>
31 #include <linux/ethtool.h>
32 #include <linux/phy.h>
33
34 #include <asm/io.h>
35 #include <asm/irq.h>
36 #include <asm/uaccess.h>
37
38 #define MII_M1011_IEVENT                0x13
39 #define MII_M1011_IEVENT_CLEAR          0x0000
40
41 #define MII_M1011_IMASK                 0x12
42 #define MII_M1011_IMASK_INIT            0x6400
43 #define MII_M1011_IMASK_CLEAR           0x0000
44
45 #define MII_M1011_PHY_SCR               0x10
46 #define MII_M1011_PHY_SCR_AUTO_CROSS    0x0060
47
48 #define MII_M1145_PHY_EXT_CR            0x14
49 #define MII_M1145_RGMII_RX_DELAY        0x0080
50 #define MII_M1145_RGMII_TX_DELAY        0x0002
51
52 #define M1145_DEV_FLAGS_RESISTANCE      0x00000001
53
54 #define MII_M1111_PHY_LED_CONTROL       0x18
55 #define MII_M1111_PHY_LED_DIRECT        0x4100
56 #define MII_M1111_PHY_LED_COMBINE       0x411c
57
58 MODULE_DESCRIPTION("Marvell PHY driver");
59 MODULE_AUTHOR("Andy Fleming");
60 MODULE_LICENSE("GPL");
61
62 static int marvell_ack_interrupt(struct phy_device *phydev)
63 {
64         int err;
65
66         /* Clear the interrupts by reading the reg */
67         err = phy_read(phydev, MII_M1011_IEVENT);
68
69         if (err < 0)
70                 return err;
71
72         return 0;
73 }
74
75 static int marvell_config_intr(struct phy_device *phydev)
76 {
77         int err;
78
79         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
80                 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
81         else
82                 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
83
84         return err;
85 }
86
87 static int marvell_config_aneg(struct phy_device *phydev)
88 {
89         int err;
90
91         /* The Marvell PHY has an errata which requires
92          * that certain registers get written in order
93          * to restart autonegotiation */
94         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
95
96         if (err < 0)
97                 return err;
98
99         err = phy_write(phydev, 0x1d, 0x1f);
100         if (err < 0)
101                 return err;
102
103         err = phy_write(phydev, 0x1e, 0x200c);
104         if (err < 0)
105                 return err;
106
107         err = phy_write(phydev, 0x1d, 0x5);
108         if (err < 0)
109                 return err;
110
111         err = phy_write(phydev, 0x1e, 0);
112         if (err < 0)
113                 return err;
114
115         err = phy_write(phydev, 0x1e, 0x100);
116         if (err < 0)
117                 return err;
118
119         err = phy_write(phydev, MII_M1011_PHY_SCR,
120                         MII_M1011_PHY_SCR_AUTO_CROSS);
121         if (err < 0)
122                 return err;
123
124         err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
125                         MII_M1111_PHY_LED_DIRECT);
126         if (err < 0)
127                 return err;
128
129         err = genphy_config_aneg(phydev);
130
131         return err;
132 }
133
134 static int m88e1145_config_init(struct phy_device *phydev)
135 {
136         int err;
137
138         /* Take care of errata E0 & E1 */
139         err = phy_write(phydev, 0x1d, 0x001b);
140         if (err < 0)
141                 return err;
142
143         err = phy_write(phydev, 0x1e, 0x418f);
144         if (err < 0)
145                 return err;
146
147         err = phy_write(phydev, 0x1d, 0x0016);
148         if (err < 0)
149                 return err;
150
151         err = phy_write(phydev, 0x1e, 0xa2da);
152         if (err < 0)
153                 return err;
154
155         if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
156                 int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
157                 if (temp < 0)
158                         return temp;
159
160                 temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
161
162                 err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
163                 if (err < 0)
164                         return err;
165
166                 if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) {
167                         err = phy_write(phydev, 0x1d, 0x0012);
168                         if (err < 0)
169                                 return err;
170
171                         temp = phy_read(phydev, 0x1e);
172                         if (temp < 0)
173                                 return temp;
174
175                         temp &= 0xf03f;
176                         temp |= 2 << 9; /* 36 ohm */
177                         temp |= 2 << 6; /* 39 ohm */
178
179                         err = phy_write(phydev, 0x1e, temp);
180                         if (err < 0)
181                                 return err;
182
183                         err = phy_write(phydev, 0x1d, 0x3);
184                         if (err < 0)
185                                 return err;
186
187                         err = phy_write(phydev, 0x1e, 0x8000);
188                         if (err < 0)
189                                 return err;
190                 }
191         }
192
193         return 0;
194 }
195
196 static struct phy_driver m88e1101_driver = {
197         .phy_id = 0x01410c60,
198         .phy_id_mask = 0xfffffff0,
199         .name = "Marvell 88E1101",
200         .features = PHY_GBIT_FEATURES,
201         .flags = PHY_HAS_INTERRUPT,
202         .config_aneg = &marvell_config_aneg,
203         .read_status = &genphy_read_status,
204         .ack_interrupt = &marvell_ack_interrupt,
205         .config_intr = &marvell_config_intr,
206         .driver = {.owner = THIS_MODULE,},
207 };
208
209 static struct phy_driver m88e1111s_driver = {
210         .phy_id = 0x01410cc0,
211         .phy_id_mask = 0xfffffff0,
212         .name = "Marvell 88E1111",
213         .features = PHY_GBIT_FEATURES,
214         .flags = PHY_HAS_INTERRUPT,
215         .config_aneg = &marvell_config_aneg,
216         .read_status = &genphy_read_status,
217         .ack_interrupt = &marvell_ack_interrupt,
218         .config_intr = &marvell_config_intr,
219         .driver = {.owner = THIS_MODULE,},
220 };
221
222 static struct phy_driver m88e1145_driver = {
223         .phy_id = 0x01410cd0,
224         .phy_id_mask = 0xfffffff0,
225         .name = "Marvell 88E1145",
226         .features = PHY_GBIT_FEATURES,
227         .flags = PHY_HAS_INTERRUPT,
228         .config_init = &m88e1145_config_init,
229         .config_aneg = &marvell_config_aneg,
230         .read_status = &genphy_read_status,
231         .ack_interrupt = &marvell_ack_interrupt,
232         .config_intr = &marvell_config_intr,
233         .driver = {.owner = THIS_MODULE,},
234 };
235
236 static int __init marvell_init(void)
237 {
238         int ret;
239
240         ret = phy_driver_register(&m88e1101_driver);
241         if (ret)
242                 return ret;
243
244         ret = phy_driver_register(&m88e1111s_driver);
245         if (ret)
246                 goto err1111s;
247
248         ret = phy_driver_register(&m88e1145_driver);
249         if (ret)
250                 goto err1145;
251
252         return 0;
253
254       err1145:
255         phy_driver_unregister(&m88e1111s_driver);
256       err1111s:
257         phy_driver_unregister(&m88e1101_driver);
258         return ret;
259 }
260
261 static void __exit marvell_exit(void)
262 {
263         phy_driver_unregister(&m88e1101_driver);
264         phy_driver_unregister(&m88e1111s_driver);
265         phy_driver_unregister(&m88e1145_driver);
266 }
267
268 module_init(marvell_init);
269 module_exit(marvell_exit);