diff options
Diffstat (limited to 'drivers/net/fs_enet/mii-bitbang.c')
-rw-r--r-- | drivers/net/fs_enet/mii-bitbang.c | 449 |
1 files changed, 226 insertions, 223 deletions
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index 24a5e2e23d18..0b9b8b5c847c 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | 15 | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | 16 | #include <linux/module.h> |
18 | #include <linux/types.h> | 17 | #include <linux/types.h> |
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -34,6 +33,7 @@ | |||
34 | #include <linux/mii.h> | 33 | #include <linux/mii.h> |
35 | #include <linux/ethtool.h> | 34 | #include <linux/ethtool.h> |
36 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/platform_device.h> | ||
37 | 37 | ||
38 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
39 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
@@ -41,129 +41,25 @@ | |||
41 | 41 | ||
42 | #include "fs_enet.h" | 42 | #include "fs_enet.h" |
43 | 43 | ||
44 | #ifdef CONFIG_8xx | 44 | static int bitbang_prep_bit(u8 **datp, u8 *mskp, |
45 | static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) | 45 | struct fs_mii_bit *mii_bit) |
46 | { | 46 | { |
47 | immap_t *im = (immap_t *)fs_enet_immap; | 47 | void *dat; |
48 | void *dir, *dat, *ppar; | ||
49 | int adv; | 48 | int adv; |
50 | u8 msk; | 49 | u8 msk; |
51 | 50 | ||
52 | switch (port) { | 51 | dat = (void*) mii_bit->offset; |
53 | case fsiop_porta: | ||
54 | dir = &im->im_ioport.iop_padir; | ||
55 | dat = &im->im_ioport.iop_padat; | ||
56 | ppar = &im->im_ioport.iop_papar; | ||
57 | break; | ||
58 | |||
59 | case fsiop_portb: | ||
60 | dir = &im->im_cpm.cp_pbdir; | ||
61 | dat = &im->im_cpm.cp_pbdat; | ||
62 | ppar = &im->im_cpm.cp_pbpar; | ||
63 | break; | ||
64 | |||
65 | case fsiop_portc: | ||
66 | dir = &im->im_ioport.iop_pcdir; | ||
67 | dat = &im->im_ioport.iop_pcdat; | ||
68 | ppar = &im->im_ioport.iop_pcpar; | ||
69 | break; | ||
70 | |||
71 | case fsiop_portd: | ||
72 | dir = &im->im_ioport.iop_pddir; | ||
73 | dat = &im->im_ioport.iop_pddat; | ||
74 | ppar = &im->im_ioport.iop_pdpar; | ||
75 | break; | ||
76 | |||
77 | case fsiop_porte: | ||
78 | dir = &im->im_cpm.cp_pedir; | ||
79 | dat = &im->im_cpm.cp_pedat; | ||
80 | ppar = &im->im_cpm.cp_pepar; | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | printk(KERN_ERR DRV_MODULE_NAME | ||
85 | "Illegal port value %d!\n", port); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | adv = bit >> 3; | ||
90 | dir = (char *)dir + adv; | ||
91 | dat = (char *)dat + adv; | ||
92 | ppar = (char *)ppar + adv; | ||
93 | |||
94 | msk = 1 << (7 - (bit & 7)); | ||
95 | if ((in_8(ppar) & msk) != 0) { | ||
96 | printk(KERN_ERR DRV_MODULE_NAME | ||
97 | "pin %d on port %d is not general purpose!\n", bit, port); | ||
98 | return -EINVAL; | ||
99 | } | ||
100 | |||
101 | *dirp = dir; | ||
102 | *datp = dat; | ||
103 | *mskp = msk; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | #endif | ||
108 | |||
109 | #ifdef CONFIG_8260 | ||
110 | static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) | ||
111 | { | ||
112 | iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport; | ||
113 | void *dir, *dat, *ppar; | ||
114 | int adv; | ||
115 | u8 msk; | ||
116 | |||
117 | switch (port) { | ||
118 | case fsiop_porta: | ||
119 | dir = &io->iop_pdira; | ||
120 | dat = &io->iop_pdata; | ||
121 | ppar = &io->iop_ppara; | ||
122 | break; | ||
123 | |||
124 | case fsiop_portb: | ||
125 | dir = &io->iop_pdirb; | ||
126 | dat = &io->iop_pdatb; | ||
127 | ppar = &io->iop_pparb; | ||
128 | break; | ||
129 | |||
130 | case fsiop_portc: | ||
131 | dir = &io->iop_pdirc; | ||
132 | dat = &io->iop_pdatc; | ||
133 | ppar = &io->iop_pparc; | ||
134 | break; | ||
135 | |||
136 | case fsiop_portd: | ||
137 | dir = &io->iop_pdird; | ||
138 | dat = &io->iop_pdatd; | ||
139 | ppar = &io->iop_ppard; | ||
140 | break; | ||
141 | |||
142 | default: | ||
143 | printk(KERN_ERR DRV_MODULE_NAME | ||
144 | "Illegal port value %d!\n", port); | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | 52 | ||
148 | adv = bit >> 3; | 53 | adv = mii_bit->bit >> 3; |
149 | dir = (char *)dir + adv; | ||
150 | dat = (char *)dat + adv; | 54 | dat = (char *)dat + adv; |
151 | ppar = (char *)ppar + adv; | ||
152 | 55 | ||
153 | msk = 1 << (7 - (bit & 7)); | 56 | msk = 1 << (7 - (mii_bit->bit & 7)); |
154 | if ((in_8(ppar) & msk) != 0) { | ||
155 | printk(KERN_ERR DRV_MODULE_NAME | ||
156 | "pin %d on port %d is not general purpose!\n", bit, port); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | 57 | ||
160 | *dirp = dir; | ||
161 | *datp = dat; | 58 | *datp = dat; |
162 | *mskp = msk; | 59 | *mskp = msk; |
163 | 60 | ||
164 | return 0; | 61 | return 0; |
165 | } | 62 | } |
166 | #endif | ||
167 | 63 | ||
168 | static inline void bb_set(u8 *p, u8 m) | 64 | static inline void bb_set(u8 *p, u8 m) |
169 | { | 65 | { |
@@ -180,44 +76,44 @@ static inline int bb_read(u8 *p, u8 m) | |||
180 | return (in_8(p) & m) != 0; | 76 | return (in_8(p) & m) != 0; |
181 | } | 77 | } |
182 | 78 | ||
183 | static inline void mdio_active(struct fs_enet_mii_bus *bus) | 79 | static inline void mdio_active(struct bb_info *bitbang) |
184 | { | 80 | { |
185 | bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); | 81 | bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk); |
186 | } | 82 | } |
187 | 83 | ||
188 | static inline void mdio_tristate(struct fs_enet_mii_bus *bus) | 84 | static inline void mdio_tristate(struct bb_info *bitbang ) |
189 | { | 85 | { |
190 | bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); | 86 | bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk); |
191 | } | 87 | } |
192 | 88 | ||
193 | static inline int mdio_read(struct fs_enet_mii_bus *bus) | 89 | static inline int mdio_read(struct bb_info *bitbang ) |
194 | { | 90 | { |
195 | return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); | 91 | return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk); |
196 | } | 92 | } |
197 | 93 | ||
198 | static inline void mdio(struct fs_enet_mii_bus *bus, int what) | 94 | static inline void mdio(struct bb_info *bitbang , int what) |
199 | { | 95 | { |
200 | if (what) | 96 | if (what) |
201 | bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); | 97 | bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk); |
202 | else | 98 | else |
203 | bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); | 99 | bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk); |
204 | } | 100 | } |
205 | 101 | ||
206 | static inline void mdc(struct fs_enet_mii_bus *bus, int what) | 102 | static inline void mdc(struct bb_info *bitbang , int what) |
207 | { | 103 | { |
208 | if (what) | 104 | if (what) |
209 | bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); | 105 | bb_set(bitbang->mdc_dat, bitbang->mdc_msk); |
210 | else | 106 | else |
211 | bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); | 107 | bb_clr(bitbang->mdc_dat, bitbang->mdc_msk); |
212 | } | 108 | } |
213 | 109 | ||
214 | static inline void mii_delay(struct fs_enet_mii_bus *bus) | 110 | static inline void mii_delay(struct bb_info *bitbang ) |
215 | { | 111 | { |
216 | udelay(bus->bus_info->i.bitbang.delay); | 112 | udelay(bitbang->delay); |
217 | } | 113 | } |
218 | 114 | ||
219 | /* Utility to send the preamble, address, and register (common to read and write). */ | 115 | /* Utility to send the preamble, address, and register (common to read and write). */ |
220 | static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) | 116 | static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg) |
221 | { | 117 | { |
222 | int j; | 118 | int j; |
223 | 119 | ||
@@ -229,177 +125,284 @@ static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) | |||
229 | * but it is safer and will be much more robust. | 125 | * but it is safer and will be much more robust. |
230 | */ | 126 | */ |
231 | 127 | ||
232 | mdio_active(bus); | 128 | mdio_active(bitbang); |
233 | mdio(bus, 1); | 129 | mdio(bitbang, 1); |
234 | for (j = 0; j < 32; j++) { | 130 | for (j = 0; j < 32; j++) { |
235 | mdc(bus, 0); | 131 | mdc(bitbang, 0); |
236 | mii_delay(bus); | 132 | mii_delay(bitbang); |
237 | mdc(bus, 1); | 133 | mdc(bitbang, 1); |
238 | mii_delay(bus); | 134 | mii_delay(bitbang); |
239 | } | 135 | } |
240 | 136 | ||
241 | /* send the start bit (01) and the read opcode (10) or write (10) */ | 137 | /* send the start bit (01) and the read opcode (10) or write (10) */ |
242 | mdc(bus, 0); | 138 | mdc(bitbang, 0); |
243 | mdio(bus, 0); | 139 | mdio(bitbang, 0); |
244 | mii_delay(bus); | 140 | mii_delay(bitbang); |
245 | mdc(bus, 1); | 141 | mdc(bitbang, 1); |
246 | mii_delay(bus); | 142 | mii_delay(bitbang); |
247 | mdc(bus, 0); | 143 | mdc(bitbang, 0); |
248 | mdio(bus, 1); | 144 | mdio(bitbang, 1); |
249 | mii_delay(bus); | 145 | mii_delay(bitbang); |
250 | mdc(bus, 1); | 146 | mdc(bitbang, 1); |
251 | mii_delay(bus); | 147 | mii_delay(bitbang); |
252 | mdc(bus, 0); | 148 | mdc(bitbang, 0); |
253 | mdio(bus, read); | 149 | mdio(bitbang, read); |
254 | mii_delay(bus); | 150 | mii_delay(bitbang); |
255 | mdc(bus, 1); | 151 | mdc(bitbang, 1); |
256 | mii_delay(bus); | 152 | mii_delay(bitbang); |
257 | mdc(bus, 0); | 153 | mdc(bitbang, 0); |
258 | mdio(bus, !read); | 154 | mdio(bitbang, !read); |
259 | mii_delay(bus); | 155 | mii_delay(bitbang); |
260 | mdc(bus, 1); | 156 | mdc(bitbang, 1); |
261 | mii_delay(bus); | 157 | mii_delay(bitbang); |
262 | 158 | ||
263 | /* send the PHY address */ | 159 | /* send the PHY address */ |
264 | for (j = 0; j < 5; j++) { | 160 | for (j = 0; j < 5; j++) { |
265 | mdc(bus, 0); | 161 | mdc(bitbang, 0); |
266 | mdio(bus, (addr & 0x10) != 0); | 162 | mdio(bitbang, (addr & 0x10) != 0); |
267 | mii_delay(bus); | 163 | mii_delay(bitbang); |
268 | mdc(bus, 1); | 164 | mdc(bitbang, 1); |
269 | mii_delay(bus); | 165 | mii_delay(bitbang); |
270 | addr <<= 1; | 166 | addr <<= 1; |
271 | } | 167 | } |
272 | 168 | ||
273 | /* send the register address */ | 169 | /* send the register address */ |
274 | for (j = 0; j < 5; j++) { | 170 | for (j = 0; j < 5; j++) { |
275 | mdc(bus, 0); | 171 | mdc(bitbang, 0); |
276 | mdio(bus, (reg & 0x10) != 0); | 172 | mdio(bitbang, (reg & 0x10) != 0); |
277 | mii_delay(bus); | 173 | mii_delay(bitbang); |
278 | mdc(bus, 1); | 174 | mdc(bitbang, 1); |
279 | mii_delay(bus); | 175 | mii_delay(bitbang); |
280 | reg <<= 1; | 176 | reg <<= 1; |
281 | } | 177 | } |
282 | } | 178 | } |
283 | 179 | ||
284 | static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) | 180 | static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location) |
285 | { | 181 | { |
286 | u16 rdreg; | 182 | u16 rdreg; |
287 | int ret, j; | 183 | int ret, j; |
288 | u8 addr = phy_id & 0xff; | 184 | u8 addr = phy_id & 0xff; |
289 | u8 reg = location & 0xff; | 185 | u8 reg = location & 0xff; |
186 | struct bb_info* bitbang = bus->priv; | ||
290 | 187 | ||
291 | bitbang_pre(bus, 1, addr, reg); | 188 | bitbang_pre(bitbang, 1, addr, reg); |
292 | 189 | ||
293 | /* tri-state our MDIO I/O pin so we can read */ | 190 | /* tri-state our MDIO I/O pin so we can read */ |
294 | mdc(bus, 0); | 191 | mdc(bitbang, 0); |
295 | mdio_tristate(bus); | 192 | mdio_tristate(bitbang); |
296 | mii_delay(bus); | 193 | mii_delay(bitbang); |
297 | mdc(bus, 1); | 194 | mdc(bitbang, 1); |
298 | mii_delay(bus); | 195 | mii_delay(bitbang); |
299 | 196 | ||
300 | /* check the turnaround bit: the PHY should be driving it to zero */ | 197 | /* check the turnaround bit: the PHY should be driving it to zero */ |
301 | if (mdio_read(bus) != 0) { | 198 | if (mdio_read(bitbang) != 0) { |
302 | /* PHY didn't drive TA low */ | 199 | /* PHY didn't drive TA low */ |
303 | for (j = 0; j < 32; j++) { | 200 | for (j = 0; j < 32; j++) { |
304 | mdc(bus, 0); | 201 | mdc(bitbang, 0); |
305 | mii_delay(bus); | 202 | mii_delay(bitbang); |
306 | mdc(bus, 1); | 203 | mdc(bitbang, 1); |
307 | mii_delay(bus); | 204 | mii_delay(bitbang); |
308 | } | 205 | } |
309 | ret = -1; | 206 | ret = -1; |
310 | goto out; | 207 | goto out; |
311 | } | 208 | } |
312 | 209 | ||
313 | mdc(bus, 0); | 210 | mdc(bitbang, 0); |
314 | mii_delay(bus); | 211 | mii_delay(bitbang); |
315 | 212 | ||
316 | /* read 16 bits of register data, MSB first */ | 213 | /* read 16 bits of register data, MSB first */ |
317 | rdreg = 0; | 214 | rdreg = 0; |
318 | for (j = 0; j < 16; j++) { | 215 | for (j = 0; j < 16; j++) { |
319 | mdc(bus, 1); | 216 | mdc(bitbang, 1); |
320 | mii_delay(bus); | 217 | mii_delay(bitbang); |
321 | rdreg <<= 1; | 218 | rdreg <<= 1; |
322 | rdreg |= mdio_read(bus); | 219 | rdreg |= mdio_read(bitbang); |
323 | mdc(bus, 0); | 220 | mdc(bitbang, 0); |
324 | mii_delay(bus); | 221 | mii_delay(bitbang); |
325 | } | 222 | } |
326 | 223 | ||
327 | mdc(bus, 1); | 224 | mdc(bitbang, 1); |
328 | mii_delay(bus); | 225 | mii_delay(bitbang); |
329 | mdc(bus, 0); | 226 | mdc(bitbang, 0); |
330 | mii_delay(bus); | 227 | mii_delay(bitbang); |
331 | mdc(bus, 1); | 228 | mdc(bitbang, 1); |
332 | mii_delay(bus); | 229 | mii_delay(bitbang); |
333 | 230 | ||
334 | ret = rdreg; | 231 | ret = rdreg; |
335 | out: | 232 | out: |
336 | return ret; | 233 | return ret; |
337 | } | 234 | } |
338 | 235 | ||
339 | static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) | 236 | static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val) |
340 | { | 237 | { |
341 | int j; | 238 | int j; |
239 | struct bb_info* bitbang = bus->priv; | ||
240 | |||
342 | u8 addr = phy_id & 0xff; | 241 | u8 addr = phy_id & 0xff; |
343 | u8 reg = location & 0xff; | 242 | u8 reg = location & 0xff; |
344 | u16 value = val & 0xffff; | 243 | u16 value = val & 0xffff; |
345 | 244 | ||
346 | bitbang_pre(bus, 0, addr, reg); | 245 | bitbang_pre(bitbang, 0, addr, reg); |
347 | 246 | ||
348 | /* send the turnaround (10) */ | 247 | /* send the turnaround (10) */ |
349 | mdc(bus, 0); | 248 | mdc(bitbang, 0); |
350 | mdio(bus, 1); | 249 | mdio(bitbang, 1); |
351 | mii_delay(bus); | 250 | mii_delay(bitbang); |
352 | mdc(bus, 1); | 251 | mdc(bitbang, 1); |
353 | mii_delay(bus); | 252 | mii_delay(bitbang); |
354 | mdc(bus, 0); | 253 | mdc(bitbang, 0); |
355 | mdio(bus, 0); | 254 | mdio(bitbang, 0); |
356 | mii_delay(bus); | 255 | mii_delay(bitbang); |
357 | mdc(bus, 1); | 256 | mdc(bitbang, 1); |
358 | mii_delay(bus); | 257 | mii_delay(bitbang); |
359 | 258 | ||
360 | /* write 16 bits of register data, MSB first */ | 259 | /* write 16 bits of register data, MSB first */ |
361 | for (j = 0; j < 16; j++) { | 260 | for (j = 0; j < 16; j++) { |
362 | mdc(bus, 0); | 261 | mdc(bitbang, 0); |
363 | mdio(bus, (value & 0x8000) != 0); | 262 | mdio(bitbang, (value & 0x8000) != 0); |
364 | mii_delay(bus); | 263 | mii_delay(bitbang); |
365 | mdc(bus, 1); | 264 | mdc(bitbang, 1); |
366 | mii_delay(bus); | 265 | mii_delay(bitbang); |
367 | value <<= 1; | 266 | value <<= 1; |
368 | } | 267 | } |
369 | 268 | ||
370 | /* | 269 | /* |
371 | * Tri-state the MDIO line. | 270 | * Tri-state the MDIO line. |
372 | */ | 271 | */ |
373 | mdio_tristate(bus); | 272 | mdio_tristate(bitbang); |
374 | mdc(bus, 0); | 273 | mdc(bitbang, 0); |
375 | mii_delay(bus); | 274 | mii_delay(bitbang); |
376 | mdc(bus, 1); | 275 | mdc(bitbang, 1); |
377 | mii_delay(bus); | 276 | mii_delay(bitbang); |
277 | return 0; | ||
378 | } | 278 | } |
379 | 279 | ||
380 | int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus) | 280 | static int fs_enet_mii_bb_reset(struct mii_bus *bus) |
281 | { | ||
282 | /*nothing here - dunno how to reset it*/ | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi) | ||
381 | { | 287 | { |
382 | const struct fs_mii_bus_info *bi = bus->bus_info; | ||
383 | int r; | 288 | int r; |
384 | 289 | ||
385 | r = bitbang_prep_bit(&bus->bitbang.mdio_dir, | 290 | bitbang->delay = fmpi->delay; |
386 | &bus->bitbang.mdio_dat, | 291 | |
387 | &bus->bitbang.mdio_msk, | 292 | r = bitbang_prep_bit(&bitbang->mdio_dir, |
388 | bi->i.bitbang.mdio_port, | 293 | &bitbang->mdio_dir_msk, |
389 | bi->i.bitbang.mdio_bit); | 294 | &fmpi->mdio_dir); |
390 | if (r != 0) | 295 | if (r != 0) |
391 | return r; | 296 | return r; |
392 | 297 | ||
393 | r = bitbang_prep_bit(&bus->bitbang.mdc_dir, | 298 | r = bitbang_prep_bit(&bitbang->mdio_dat, |
394 | &bus->bitbang.mdc_dat, | 299 | &bitbang->mdio_dat_msk, |
395 | &bus->bitbang.mdc_msk, | 300 | &fmpi->mdio_dat); |
396 | bi->i.bitbang.mdc_port, | ||
397 | bi->i.bitbang.mdc_bit); | ||
398 | if (r != 0) | 301 | if (r != 0) |
399 | return r; | 302 | return r; |
400 | 303 | ||
401 | bus->mii_read = mii_read; | 304 | r = bitbang_prep_bit(&bitbang->mdc_dat, |
402 | bus->mii_write = mii_write; | 305 | &bitbang->mdc_msk, |
306 | &fmpi->mdc_dat); | ||
307 | if (r != 0) | ||
308 | return r; | ||
403 | 309 | ||
404 | return 0; | 310 | return 0; |
405 | } | 311 | } |
312 | |||
313 | |||
314 | static int __devinit fs_enet_mdio_probe(struct device *dev) | ||
315 | { | ||
316 | struct platform_device *pdev = to_platform_device(dev); | ||
317 | struct fs_mii_bb_platform_info *pdata; | ||
318 | struct mii_bus *new_bus; | ||
319 | struct bb_info *bitbang; | ||
320 | int err = 0; | ||
321 | |||
322 | if (NULL == dev) | ||
323 | return -EINVAL; | ||
324 | |||
325 | new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); | ||
326 | |||
327 | if (NULL == new_bus) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); | ||
331 | |||
332 | if (NULL == bitbang) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | new_bus->name = "BB MII Bus", | ||
336 | new_bus->read = &fs_enet_mii_bb_read, | ||
337 | new_bus->write = &fs_enet_mii_bb_write, | ||
338 | new_bus->reset = &fs_enet_mii_bb_reset, | ||
339 | new_bus->id = pdev->id; | ||
340 | |||
341 | new_bus->phy_mask = ~0x9; | ||
342 | pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data; | ||
343 | |||
344 | if (NULL == pdata) { | ||
345 | printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id); | ||
346 | return -ENODEV; | ||
347 | } | ||
348 | |||
349 | /*set up workspace*/ | ||
350 | fs_mii_bitbang_init(bitbang, pdata); | ||
351 | |||
352 | new_bus->priv = bitbang; | ||
353 | |||
354 | new_bus->irq = pdata->irq; | ||
355 | |||
356 | new_bus->dev = dev; | ||
357 | dev_set_drvdata(dev, new_bus); | ||
358 | |||
359 | err = mdiobus_register(new_bus); | ||
360 | |||
361 | if (0 != err) { | ||
362 | printk (KERN_ERR "%s: Cannot register as MDIO bus\n", | ||
363 | new_bus->name); | ||
364 | goto bus_register_fail; | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | bus_register_fail: | ||
370 | kfree(bitbang); | ||
371 | kfree(new_bus); | ||
372 | |||
373 | return err; | ||
374 | } | ||
375 | |||
376 | |||
377 | static int fs_enet_mdio_remove(struct device *dev) | ||
378 | { | ||
379 | struct mii_bus *bus = dev_get_drvdata(dev); | ||
380 | |||
381 | mdiobus_unregister(bus); | ||
382 | |||
383 | dev_set_drvdata(dev, NULL); | ||
384 | |||
385 | iounmap((void *) (&bus->priv)); | ||
386 | bus->priv = NULL; | ||
387 | kfree(bus); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static struct device_driver fs_enet_bb_mdio_driver = { | ||
393 | .name = "fsl-bb-mdio", | ||
394 | .bus = &platform_bus_type, | ||
395 | .probe = fs_enet_mdio_probe, | ||
396 | .remove = fs_enet_mdio_remove, | ||
397 | }; | ||
398 | |||
399 | int fs_enet_mdio_bb_init(void) | ||
400 | { | ||
401 | return driver_register(&fs_enet_bb_mdio_driver); | ||
402 | } | ||
403 | |||
404 | void fs_enet_mdio_bb_exit(void) | ||
405 | { | ||
406 | driver_unregister(&fs_enet_bb_mdio_driver); | ||
407 | } | ||
408 | |||