OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [phy/] [phy_device.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * drivers/net/phy/phy_device.c
3
 *
4
 * Framework for finding and configuring PHYs.
5
 * Also contains generic PHY driver
6
 *
7
 * Author: Andy Fleming
8
 *
9
 * Copyright (c) 2004 Freescale Semiconductor, Inc.
10
 *
11
 * This program is free software; you can redistribute  it and/or modify it
12
 * under  the terms of  the GNU General  Public License as published by the
13
 * Free Software Foundation;  either version 2 of the  License, or (at your
14
 * option) any later version.
15
 *
16
 */
17
#include <linux/kernel.h>
18
#include <linux/string.h>
19
#include <linux/errno.h>
20
#include <linux/unistd.h>
21
#include <linux/slab.h>
22
#include <linux/interrupt.h>
23
#include <linux/init.h>
24
#include <linux/delay.h>
25
#include <linux/netdevice.h>
26
#include <linux/etherdevice.h>
27
#include <linux/skbuff.h>
28
#include <linux/spinlock.h>
29
#include <linux/mm.h>
30
#include <linux/module.h>
31
#include <linux/mii.h>
32
#include <linux/ethtool.h>
33
#include <linux/phy.h>
34
 
35
#include <asm/io.h>
36
#include <asm/irq.h>
37
#include <asm/uaccess.h>
38
 
39
MODULE_DESCRIPTION("PHY library");
40
MODULE_AUTHOR("Andy Fleming");
41
MODULE_LICENSE("GPL");
42
 
43
static struct phy_driver genphy_driver;
44
extern int mdio_bus_init(void);
45
extern void mdio_bus_exit(void);
46
 
47
void phy_device_free(struct phy_device *phydev)
48
{
49
        kfree(phydev);
50
}
51
 
52
static void phy_device_release(struct device *dev)
53
{
54
        phy_device_free(to_phy_device(dev));
55
}
56
 
57
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
58
{
59
        struct phy_device *dev;
60
        /* We allocate the device, and initialize the
61
         * default values */
62
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
63
 
64
        if (NULL == dev)
65
                return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
66
 
67
        dev->dev.release = phy_device_release;
68
 
69
        dev->speed = 0;
70
        dev->duplex = -1;
71
        dev->pause = dev->asym_pause = 0;
72
        dev->link = 1;
73
        dev->interface = PHY_INTERFACE_MODE_GMII;
74
 
75
        dev->autoneg = AUTONEG_ENABLE;
76
 
77
        dev->addr = addr;
78
        dev->phy_id = phy_id;
79
        dev->bus = bus;
80
 
81
        dev->state = PHY_DOWN;
82
 
83
        spin_lock_init(&dev->lock);
84
 
85
        return dev;
86
}
87
EXPORT_SYMBOL(phy_device_create);
88
 
89
/**
90
 * get_phy_device - reads the specified PHY device and returns its @phy_device struct
91
 * @bus: the target MII bus
92
 * @addr: PHY address on the MII bus
93
 *
94
 * Description: Reads the ID registers of the PHY at @addr on the
95
 *   @bus, then allocates and returns the phy_device to represent it.
96
 */
97
struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
98
{
99
        int phy_reg;
100
        u32 phy_id;
101
        struct phy_device *dev = NULL;
102
 
103
        /* Grab the bits from PHYIR1, and put them
104
         * in the upper half */
105
        phy_reg = bus->read(bus, addr, MII_PHYSID1);
106
 
107
        if (phy_reg < 0)
108
                return ERR_PTR(phy_reg);
109
 
110
        phy_id = (phy_reg & 0xffff) << 16;
111
 
112
        /* Grab the bits from PHYIR2, and put them in the lower half */
113
        phy_reg = bus->read(bus, addr, MII_PHYSID2);
114
 
115
        if (phy_reg < 0)
116
                return ERR_PTR(phy_reg);
117
 
118
        phy_id |= (phy_reg & 0xffff);
119
 
120
        /* If the phy_id is all Fs, there is no device there */
121
        if (0xffffffff == phy_id)
122
                return NULL;
123
 
124
        dev = phy_device_create(bus, addr, phy_id);
125
 
126
        return dev;
127
}
128
 
129
/**
130
 * phy_prepare_link - prepares the PHY layer to monitor link status
131
 * @phydev: target phy_device struct
132
 * @handler: callback function for link status change notifications
133
 *
134
 * Description: Tells the PHY infrastructure to handle the
135
 *   gory details on monitoring link status (whether through
136
 *   polling or an interrupt), and to call back to the
137
 *   connected device driver when the link status changes.
138
 *   If you want to monitor your own link state, don't call
139
 *   this function.
140
 */
141
void phy_prepare_link(struct phy_device *phydev,
142
                void (*handler)(struct net_device *))
143
{
144
        phydev->adjust_link = handler;
145
}
146
 
147
/**
148
 * phy_connect - connect an ethernet device to a PHY device
149
 * @dev: the network device to connect
150
 * @phy_id: the PHY device to connect
151
 * @handler: callback function for state change notifications
152
 * @flags: PHY device's dev_flags
153
 * @interface: PHY device's interface
154
 *
155
 * Description: Convenience function for connecting ethernet
156
 *   devices to PHY devices.  The default behavior is for
157
 *   the PHY infrastructure to handle everything, and only notify
158
 *   the connected driver when the link status changes.  If you
159
 *   don't want, or can't use the provided functionality, you may
160
 *   choose to call only the subset of functions which provide
161
 *   the desired functionality.
162
 */
163
struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
164
                void (*handler)(struct net_device *), u32 flags,
165
                phy_interface_t interface)
166
{
167
        struct phy_device *phydev;
168
 
169
        phydev = phy_attach(dev, phy_id, flags, interface);
170
 
171
        if (IS_ERR(phydev))
172
                return phydev;
173
 
174
        phy_prepare_link(phydev, handler);
175
 
176
        phy_start_machine(phydev, NULL);
177
 
178
        if (phydev->irq > 0)
179
                phy_start_interrupts(phydev);
180
 
181
        return phydev;
182
}
183
EXPORT_SYMBOL(phy_connect);
184
 
185
/**
186
 * phy_disconnect - disable interrupts, stop state machine, and detach a PHY device
187
 * @phydev: target phy_device struct
188
 */
189
void phy_disconnect(struct phy_device *phydev)
190
{
191
        if (phydev->irq > 0)
192
                phy_stop_interrupts(phydev);
193
 
194
        phy_stop_machine(phydev);
195
 
196
        phydev->adjust_link = NULL;
197
 
198
        phy_detach(phydev);
199
}
200
EXPORT_SYMBOL(phy_disconnect);
201
 
202
static int phy_compare_id(struct device *dev, void *data)
203
{
204
        return strcmp((char *)data, dev->bus_id) ? 0 : 1;
205
}
206
 
207
/**
208
 * phy_attach - attach a network device to a particular PHY device
209
 * @dev: network device to attach
210
 * @phy_id: PHY device to attach
211
 * @flags: PHY device's dev_flags
212
 * @interface: PHY device's interface
213
 *
214
 * Description: Called by drivers to attach to a particular PHY
215
 *     device. The phy_device is found, and properly hooked up
216
 *     to the phy_driver.  If no driver is attached, then the
217
 *     genphy_driver is used.  The phy_device is given a ptr to
218
 *     the attaching device, and given a callback for link status
219
 *     change.  The phy_device is returned to the attaching driver.
220
 */
221
struct phy_device *phy_attach(struct net_device *dev,
222
                const char *phy_id, u32 flags, phy_interface_t interface)
223
{
224
        struct bus_type *bus = &mdio_bus_type;
225
        struct phy_device *phydev;
226
        struct device *d;
227
 
228
        /* Search the list of PHY devices on the mdio bus for the
229
         * PHY with the requested name */
230
        d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
231
 
232
        if (d) {
233
                phydev = to_phy_device(d);
234
        } else {
235
                printk(KERN_ERR "%s not found\n", phy_id);
236
                return ERR_PTR(-ENODEV);
237
        }
238
 
239
        /* Assume that if there is no driver, that it doesn't
240
         * exist, and we should use the genphy driver. */
241
        if (NULL == d->driver) {
242
                int err;
243
                d->driver = &genphy_driver.driver;
244
 
245
                err = d->driver->probe(d);
246
                if (err >= 0)
247
                        err = device_bind_driver(d);
248
 
249
                if (err)
250
                        return ERR_PTR(err);
251
        }
252
 
253
        if (phydev->attached_dev) {
254
                printk(KERN_ERR "%s: %s already attached\n",
255
                                dev->name, phy_id);
256
                return ERR_PTR(-EBUSY);
257
        }
258
 
259
        phydev->attached_dev = dev;
260
 
261
        phydev->dev_flags = flags;
262
 
263
        phydev->interface = interface;
264
 
265
        /* Do initial configuration here, now that
266
         * we have certain key parameters
267
         * (dev_flags and interface) */
268
        if (phydev->drv->config_init) {
269
                int err;
270
 
271
                err = phydev->drv->config_init(phydev);
272
 
273
                if (err < 0)
274
                        return ERR_PTR(err);
275
        }
276
 
277
        return phydev;
278
}
279
EXPORT_SYMBOL(phy_attach);
280
 
281
/**
282
 * phy_detach - detach a PHY device from its network device
283
 * @phydev: target phy_device struct
284
 */
285
void phy_detach(struct phy_device *phydev)
286
{
287
        phydev->attached_dev = NULL;
288
 
289
        /* If the device had no specific driver before (i.e. - it
290
         * was using the generic driver), we unbind the device
291
         * from the generic driver so that there's a chance a
292
         * real driver could be loaded */
293
        if (phydev->dev.driver == &genphy_driver.driver)
294
                device_release_driver(&phydev->dev);
295
}
296
EXPORT_SYMBOL(phy_detach);
297
 
298
 
299
/* Generic PHY support and helper functions */
300
 
301
/**
302
 * genphy_config_advert - sanitize and advertise auto-negotation parameters
303
 * @phydev: target phy_device struct
304
 *
305
 * Description: Writes MII_ADVERTISE with the appropriate values,
306
 *   after sanitizing the values to make sure we only advertise
307
 *   what is supported.
308
 */
309
int genphy_config_advert(struct phy_device *phydev)
310
{
311
        u32 advertise;
312
        int adv;
313
        int err;
314
 
315
        /* Only allow advertising what
316
         * this PHY supports */
317
        phydev->advertising &= phydev->supported;
318
        advertise = phydev->advertising;
319
 
320
        /* Setup standard advertisement */
321
        adv = phy_read(phydev, MII_ADVERTISE);
322
 
323
        if (adv < 0)
324
                return adv;
325
 
326
        adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
327
                 ADVERTISE_PAUSE_ASYM);
328
        if (advertise & ADVERTISED_10baseT_Half)
329
                adv |= ADVERTISE_10HALF;
330
        if (advertise & ADVERTISED_10baseT_Full)
331
                adv |= ADVERTISE_10FULL;
332
        if (advertise & ADVERTISED_100baseT_Half)
333
                adv |= ADVERTISE_100HALF;
334
        if (advertise & ADVERTISED_100baseT_Full)
335
                adv |= ADVERTISE_100FULL;
336
        if (advertise & ADVERTISED_Pause)
337
                adv |= ADVERTISE_PAUSE_CAP;
338
        if (advertise & ADVERTISED_Asym_Pause)
339
                adv |= ADVERTISE_PAUSE_ASYM;
340
 
341
        err = phy_write(phydev, MII_ADVERTISE, adv);
342
 
343
        if (err < 0)
344
                return err;
345
 
346
        /* Configure gigabit if it's supported */
347
        if (phydev->supported & (SUPPORTED_1000baseT_Half |
348
                                SUPPORTED_1000baseT_Full)) {
349
                adv = phy_read(phydev, MII_CTRL1000);
350
 
351
                if (adv < 0)
352
                        return adv;
353
 
354
                adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
355
                if (advertise & SUPPORTED_1000baseT_Half)
356
                        adv |= ADVERTISE_1000HALF;
357
                if (advertise & SUPPORTED_1000baseT_Full)
358
                        adv |= ADVERTISE_1000FULL;
359
                err = phy_write(phydev, MII_CTRL1000, adv);
360
 
361
                if (err < 0)
362
                        return err;
363
        }
364
 
365
        return adv;
366
}
367
EXPORT_SYMBOL(genphy_config_advert);
368
 
369
/**
370
 * genphy_setup_forced - configures/forces speed/duplex from @phydev
371
 * @phydev: target phy_device struct
372
 *
373
 * Description: Configures MII_BMCR to force speed/duplex
374
 *   to the values in phydev. Assumes that the values are valid.
375
 *   Please see phy_sanitize_settings().
376
 */
377
int genphy_setup_forced(struct phy_device *phydev)
378
{
379
        int ctl = 0;
380
 
381
        phydev->pause = phydev->asym_pause = 0;
382
 
383
        if (SPEED_1000 == phydev->speed)
384
                ctl |= BMCR_SPEED1000;
385
        else if (SPEED_100 == phydev->speed)
386
                ctl |= BMCR_SPEED100;
387
 
388
        if (DUPLEX_FULL == phydev->duplex)
389
                ctl |= BMCR_FULLDPLX;
390
 
391
        ctl = phy_write(phydev, MII_BMCR, ctl);
392
 
393
        if (ctl < 0)
394
                return ctl;
395
 
396
        /* We just reset the device, so we'd better configure any
397
         * settings the PHY requires to operate */
398
        if (phydev->drv->config_init)
399
                ctl = phydev->drv->config_init(phydev);
400
 
401
        return ctl;
402
}
403
 
404
 
405
/**
406
 * genphy_restart_aneg - Enable and Restart Autonegotiation
407
 * @phydev: target phy_device struct
408
 */
409
int genphy_restart_aneg(struct phy_device *phydev)
410
{
411
        int ctl;
412
 
413
        ctl = phy_read(phydev, MII_BMCR);
414
 
415
        if (ctl < 0)
416
                return ctl;
417
 
418
        ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
419
 
420
        /* Don't isolate the PHY if we're negotiating */
421
        ctl &= ~(BMCR_ISOLATE);
422
 
423
        ctl = phy_write(phydev, MII_BMCR, ctl);
424
 
425
        return ctl;
426
}
427
 
428
 
429
/**
430
 * genphy_config_aneg - restart auto-negotiation or write BMCR
431
 * @phydev: target phy_device struct
432
 *
433
 * Description: If auto-negotiation is enabled, we configure the
434
 *   advertising, and then restart auto-negotiation.  If it is not
435
 *   enabled, then we write the BMCR.
436
 */
437
int genphy_config_aneg(struct phy_device *phydev)
438
{
439
        int err = 0;
440
 
441
        if (AUTONEG_ENABLE == phydev->autoneg) {
442
                err = genphy_config_advert(phydev);
443
 
444
                if (err < 0)
445
                        return err;
446
 
447
                err = genphy_restart_aneg(phydev);
448
        } else
449
                err = genphy_setup_forced(phydev);
450
 
451
        return err;
452
}
453
EXPORT_SYMBOL(genphy_config_aneg);
454
 
455
/**
456
 * genphy_update_link - update link status in @phydev
457
 * @phydev: target phy_device struct
458
 *
459
 * Description: Update the value in phydev->link to reflect the
460
 *   current link value.  In order to do this, we need to read
461
 *   the status register twice, keeping the second value.
462
 */
463
int genphy_update_link(struct phy_device *phydev)
464
{
465
        int status;
466
 
467
        /* Do a fake read */
468
        status = phy_read(phydev, MII_BMSR);
469
 
470
        if (status < 0)
471
                return status;
472
 
473
        /* Read link and autonegotiation status */
474
        status = phy_read(phydev, MII_BMSR);
475
 
476
        if (status < 0)
477
                return status;
478
 
479
        if ((status & BMSR_LSTATUS) == 0)
480
                phydev->link = 0;
481
        else
482
                phydev->link = 1;
483
 
484
        return 0;
485
}
486
EXPORT_SYMBOL(genphy_update_link);
487
 
488
/**
489
 * genphy_read_status - check the link status and update current link state
490
 * @phydev: target phy_device struct
491
 *
492
 * Description: Check the link, then figure out the current state
493
 *   by comparing what we advertise with what the link partner
494
 *   advertises.  Start by checking the gigabit possibilities,
495
 *   then move on to 10/100.
496
 */
497
int genphy_read_status(struct phy_device *phydev)
498
{
499
        int adv;
500
        int err;
501
        int lpa;
502
        int lpagb = 0;
503
 
504
        /* Update the link, but return if there
505
         * was an error */
506
        err = genphy_update_link(phydev);
507
        if (err)
508
                return err;
509
 
510
        if (AUTONEG_ENABLE == phydev->autoneg) {
511
                if (phydev->supported & (SUPPORTED_1000baseT_Half
512
                                        | SUPPORTED_1000baseT_Full)) {
513
                        lpagb = phy_read(phydev, MII_STAT1000);
514
 
515
                        if (lpagb < 0)
516
                                return lpagb;
517
 
518
                        adv = phy_read(phydev, MII_CTRL1000);
519
 
520
                        if (adv < 0)
521
                                return adv;
522
 
523
                        lpagb &= adv << 2;
524
                }
525
 
526
                lpa = phy_read(phydev, MII_LPA);
527
 
528
                if (lpa < 0)
529
                        return lpa;
530
 
531
                adv = phy_read(phydev, MII_ADVERTISE);
532
 
533
                if (adv < 0)
534
                        return adv;
535
 
536
                lpa &= adv;
537
 
538
                phydev->speed = SPEED_10;
539
                phydev->duplex = DUPLEX_HALF;
540
                phydev->pause = phydev->asym_pause = 0;
541
 
542
                if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
543
                        phydev->speed = SPEED_1000;
544
 
545
                        if (lpagb & LPA_1000FULL)
546
                                phydev->duplex = DUPLEX_FULL;
547
                } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
548
                        phydev->speed = SPEED_100;
549
 
550
                        if (lpa & LPA_100FULL)
551
                                phydev->duplex = DUPLEX_FULL;
552
                } else
553
                        if (lpa & LPA_10FULL)
554
                                phydev->duplex = DUPLEX_FULL;
555
 
556
                if (phydev->duplex == DUPLEX_FULL){
557
                        phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
558
                        phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
559
                }
560
        } else {
561
                int bmcr = phy_read(phydev, MII_BMCR);
562
                if (bmcr < 0)
563
                        return bmcr;
564
 
565
                if (bmcr & BMCR_FULLDPLX)
566
                        phydev->duplex = DUPLEX_FULL;
567
                else
568
                        phydev->duplex = DUPLEX_HALF;
569
 
570
                if (bmcr & BMCR_SPEED1000)
571
                        phydev->speed = SPEED_1000;
572
                else if (bmcr & BMCR_SPEED100)
573
                        phydev->speed = SPEED_100;
574
                else
575
                        phydev->speed = SPEED_10;
576
 
577
                phydev->pause = phydev->asym_pause = 0;
578
        }
579
 
580
        return 0;
581
}
582
EXPORT_SYMBOL(genphy_read_status);
583
 
584
static int genphy_config_init(struct phy_device *phydev)
585
{
586
        int val;
587
        u32 features;
588
 
589
        /* For now, I'll claim that the generic driver supports
590
         * all possible port types */
591
        features = (SUPPORTED_TP | SUPPORTED_MII
592
                        | SUPPORTED_AUI | SUPPORTED_FIBRE |
593
                        SUPPORTED_BNC);
594
 
595
        /* Do we support autonegotiation? */
596
        val = phy_read(phydev, MII_BMSR);
597
 
598
        if (val < 0)
599
                return val;
600
 
601
        if (val & BMSR_ANEGCAPABLE)
602
                features |= SUPPORTED_Autoneg;
603
 
604
        if (val & BMSR_100FULL)
605
                features |= SUPPORTED_100baseT_Full;
606
        if (val & BMSR_100HALF)
607
                features |= SUPPORTED_100baseT_Half;
608
        if (val & BMSR_10FULL)
609
                features |= SUPPORTED_10baseT_Full;
610
        if (val & BMSR_10HALF)
611
                features |= SUPPORTED_10baseT_Half;
612
 
613
        if (val & BMSR_ESTATEN) {
614
                val = phy_read(phydev, MII_ESTATUS);
615
 
616
                if (val < 0)
617
                        return val;
618
 
619
                if (val & ESTATUS_1000_TFULL)
620
                        features |= SUPPORTED_1000baseT_Full;
621
                if (val & ESTATUS_1000_THALF)
622
                        features |= SUPPORTED_1000baseT_Half;
623
        }
624
 
625
        phydev->supported = features;
626
        phydev->advertising = features;
627
 
628
        return 0;
629
}
630
 
631
 
632
/**
633
 * phy_probe - probe and init a PHY device
634
 * @dev: device to probe and init
635
 *
636
 * Description: Take care of setting up the phy_device structure,
637
 *   set the state to READY (the driver's init function should
638
 *   set it to STARTING if needed).
639
 */
640
static int phy_probe(struct device *dev)
641
{
642
        struct phy_device *phydev;
643
        struct phy_driver *phydrv;
644
        struct device_driver *drv;
645
        int err = 0;
646
 
647
        phydev = to_phy_device(dev);
648
 
649
        /* Make sure the driver is held.
650
         * XXX -- Is this correct? */
651
        drv = get_driver(phydev->dev.driver);
652
        phydrv = to_phy_driver(drv);
653
        phydev->drv = phydrv;
654
 
655
        /* Disable the interrupt if the PHY doesn't support it */
656
        if (!(phydrv->flags & PHY_HAS_INTERRUPT))
657
                phydev->irq = PHY_POLL;
658
 
659
        spin_lock_bh(&phydev->lock);
660
 
661
        /* Start out supporting everything. Eventually,
662
         * a controller will attach, and may modify one
663
         * or both of these values */
664
        phydev->supported = phydrv->features;
665
        phydev->advertising = phydrv->features;
666
 
667
        /* Set the state to READY by default */
668
        phydev->state = PHY_READY;
669
 
670
        if (phydev->drv->probe)
671
                err = phydev->drv->probe(phydev);
672
 
673
        spin_unlock_bh(&phydev->lock);
674
 
675
        return err;
676
 
677
}
678
 
679
static int phy_remove(struct device *dev)
680
{
681
        struct phy_device *phydev;
682
 
683
        phydev = to_phy_device(dev);
684
 
685
        spin_lock_bh(&phydev->lock);
686
        phydev->state = PHY_DOWN;
687
        spin_unlock_bh(&phydev->lock);
688
 
689
        if (phydev->drv->remove)
690
                phydev->drv->remove(phydev);
691
 
692
        put_driver(dev->driver);
693
        phydev->drv = NULL;
694
 
695
        return 0;
696
}
697
 
698
/**
699
 * phy_driver_register - register a phy_driver with the PHY layer
700
 * @new_driver: new phy_driver to register
701
 */
702
int phy_driver_register(struct phy_driver *new_driver)
703
{
704
        int retval;
705
 
706
        memset(&new_driver->driver, 0, sizeof(new_driver->driver));
707
        new_driver->driver.name = new_driver->name;
708
        new_driver->driver.bus = &mdio_bus_type;
709
        new_driver->driver.probe = phy_probe;
710
        new_driver->driver.remove = phy_remove;
711
 
712
        retval = driver_register(&new_driver->driver);
713
 
714
        if (retval) {
715
                printk(KERN_ERR "%s: Error %d in registering driver\n",
716
                                new_driver->name, retval);
717
 
718
                return retval;
719
        }
720
 
721
        pr_debug("%s: Registered new driver\n", new_driver->name);
722
 
723
        return 0;
724
}
725
EXPORT_SYMBOL(phy_driver_register);
726
 
727
void phy_driver_unregister(struct phy_driver *drv)
728
{
729
        driver_unregister(&drv->driver);
730
}
731
EXPORT_SYMBOL(phy_driver_unregister);
732
 
733
static struct phy_driver genphy_driver = {
734
        .phy_id         = 0xffffffff,
735
        .phy_id_mask    = 0xffffffff,
736
        .name           = "Generic PHY",
737
        .config_init    = genphy_config_init,
738
        .features       = 0,
739
        .config_aneg    = genphy_config_aneg,
740
        .read_status    = genphy_read_status,
741
        .driver         = {.owner= THIS_MODULE, },
742
};
743
 
744
static int __init phy_init(void)
745
{
746
        int rc;
747
 
748
        rc = mdio_bus_init();
749
        if (rc)
750
                return rc;
751
 
752
        rc = phy_driver_register(&genphy_driver);
753
        if (rc)
754
                mdio_bus_exit();
755
 
756
        return rc;
757
}
758
 
759
static void __exit phy_exit(void)
760
{
761
        phy_driver_unregister(&genphy_driver);
762
        mdio_bus_exit();
763
}
764
 
765
subsys_initcall(phy_init);
766
module_exit(phy_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.