diff options
author | Andy Fleming <afleming@freescale.com> | 2007-02-09 19:13:58 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-17 15:16:08 -0500 |
commit | 76884679c644a34ead40d74f4df6075a61d51990 (patch) | |
tree | 0a8825745ae26f5cff3bcb5168c167d4f4417374 /drivers/net/phy/marvell.c | |
parent | f630fe2817601314b2eb7ca5ddc23c7834646731 (diff) |
phylib: Add support for Marvell 88e1111S and 88e1145
Changes include:
* New support for 88e1145
* New support for 88e111s
* Fixing 88e1101 driver to not match non-88e1101 PHYs
* Increases in feature support across Marvell PHY product line
* Fixes a bunch of whitespace issues found by Lindent
Signed-off-by: Andrew Fleming <afleming@freescale.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/phy/marvell.c')
-rw-r--r-- | drivers/net/phy/marvell.c | 156 |
1 files changed, 144 insertions, 12 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index f4d4eb659cad..22aec5cce683 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c | |||
@@ -42,6 +42,19 @@ | |||
42 | #define MII_M1011_IMASK_INIT 0x6400 | 42 | #define MII_M1011_IMASK_INIT 0x6400 |
43 | #define MII_M1011_IMASK_CLEAR 0x0000 | 43 | #define MII_M1011_IMASK_CLEAR 0x0000 |
44 | 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 | |||
45 | MODULE_DESCRIPTION("Marvell PHY driver"); | 58 | MODULE_DESCRIPTION("Marvell PHY driver"); |
46 | MODULE_AUTHOR("Andy Fleming"); | 59 | MODULE_AUTHOR("Andy Fleming"); |
47 | MODULE_LICENSE("GPL"); | 60 | MODULE_LICENSE("GPL"); |
@@ -63,7 +76,7 @@ static int marvell_config_intr(struct phy_device *phydev) | |||
63 | { | 76 | { |
64 | int err; | 77 | int err; |
65 | 78 | ||
66 | if(phydev->interrupts == PHY_INTERRUPT_ENABLED) | 79 | if (phydev->interrupts == PHY_INTERRUPT_ENABLED) |
67 | err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); | 80 | err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); |
68 | else | 81 | else |
69 | err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); | 82 | err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); |
@@ -103,34 +116,153 @@ static int marvell_config_aneg(struct phy_device *phydev) | |||
103 | if (err < 0) | 116 | if (err < 0) |
104 | return err; | 117 | return err; |
105 | 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; | ||
106 | 128 | ||
107 | err = genphy_config_aneg(phydev); | 129 | err = genphy_config_aneg(phydev); |
108 | 130 | ||
109 | return err; | 131 | return err; |
110 | } | 132 | } |
111 | 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 | } | ||
112 | 195 | ||
113 | static struct phy_driver m88e1101_driver = { | 196 | static struct phy_driver m88e1101_driver = { |
114 | .phy_id = 0x01410c00, | 197 | .phy_id = 0x01410c60, |
115 | .phy_id_mask = 0xffffff00, | 198 | .phy_id_mask = 0xfffffff0, |
116 | .name = "Marvell 88E1101", | 199 | .name = "Marvell 88E1101", |
117 | .features = PHY_GBIT_FEATURES, | 200 | .features = PHY_GBIT_FEATURES, |
118 | .flags = PHY_HAS_INTERRUPT, | 201 | .flags = PHY_HAS_INTERRUPT, |
119 | .config_aneg = &marvell_config_aneg, | 202 | .config_aneg = &marvell_config_aneg, |
120 | .read_status = &genphy_read_status, | 203 | .read_status = &genphy_read_status, |
121 | .ack_interrupt = &marvell_ack_interrupt, | 204 | .ack_interrupt = &marvell_ack_interrupt, |
122 | .config_intr = &marvell_config_intr, | 205 | .config_intr = &marvell_config_intr, |
123 | .driver = { .owner = THIS_MODULE,}, | 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,}, | ||
124 | }; | 234 | }; |
125 | 235 | ||
126 | static int __init marvell_init(void) | 236 | static int __init marvell_init(void) |
127 | { | 237 | { |
128 | return phy_driver_register(&m88e1101_driver); | 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; | ||
129 | } | 259 | } |
130 | 260 | ||
131 | static void __exit marvell_exit(void) | 261 | static void __exit marvell_exit(void) |
132 | { | 262 | { |
133 | phy_driver_unregister(&m88e1101_driver); | 263 | phy_driver_unregister(&m88e1101_driver); |
264 | phy_driver_unregister(&m88e1111s_driver); | ||
265 | phy_driver_unregister(&m88e1145_driver); | ||
134 | } | 266 | } |
135 | 267 | ||
136 | module_init(marvell_init); | 268 | module_init(marvell_init); |