Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
net
phy
bcm63xx.c
Go to the documentation of this file.
1
/*
2
* Driver for Broadcom 63xx SOCs integrated PHYs
3
*
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version
7
* 2 of the License, or (at your option) any later version.
8
*/
9
#include <linux/module.h>
10
#include <
linux/phy.h
>
11
12
#define MII_BCM63XX_IR 0x1a
/* interrupt register */
13
#define MII_BCM63XX_IR_EN 0x4000
/* global interrupt enable */
14
#define MII_BCM63XX_IR_DUPLEX 0x0800
/* duplex changed */
15
#define MII_BCM63XX_IR_SPEED 0x0400
/* speed changed */
16
#define MII_BCM63XX_IR_LINK 0x0200
/* link changed */
17
#define MII_BCM63XX_IR_GMASK 0x0100
/* global interrupt mask */
18
19
MODULE_DESCRIPTION
(
"Broadcom 63xx internal PHY driver"
);
20
MODULE_AUTHOR
(
"Maxime Bizon <
[email protected]
>"
);
21
MODULE_LICENSE
(
"GPL"
);
22
23
static
int
bcm63xx_config_init(
struct
phy_device
*phydev)
24
{
25
int
reg
,
err
;
26
27
reg =
phy_read
(phydev,
MII_BCM63XX_IR
);
28
if
(reg < 0)
29
return
reg
;
30
31
/* Mask interrupts globally. */
32
reg |=
MII_BCM63XX_IR_GMASK
;
33
err =
phy_write
(phydev,
MII_BCM63XX_IR
, reg);
34
if
(err < 0)
35
return
err
;
36
37
/* Unmask events we are interested in */
38
reg = ~(
MII_BCM63XX_IR_DUPLEX
|
39
MII_BCM63XX_IR_SPEED
|
40
MII_BCM63XX_IR_LINK
) |
41
MII_BCM63XX_IR_EN
;
42
return
phy_write
(phydev,
MII_BCM63XX_IR
, reg);
43
}
44
45
static
int
bcm63xx_ack_interrupt(
struct
phy_device
*phydev)
46
{
47
int
reg
;
48
49
/* Clear pending interrupts. */
50
reg =
phy_read
(phydev,
MII_BCM63XX_IR
);
51
if
(reg < 0)
52
return
reg
;
53
54
return
0;
55
}
56
57
static
int
bcm63xx_config_intr(
struct
phy_device
*phydev)
58
{
59
int
reg
,
err
;
60
61
reg =
phy_read
(phydev,
MII_BCM63XX_IR
);
62
if
(reg < 0)
63
return
reg
;
64
65
if
(phydev->
interrupts
==
PHY_INTERRUPT_ENABLED
)
66
reg &= ~
MII_BCM63XX_IR_GMASK
;
67
else
68
reg |=
MII_BCM63XX_IR_GMASK
;
69
70
err =
phy_write
(phydev,
MII_BCM63XX_IR
, reg);
71
return
err
;
72
}
73
74
static
struct
phy_driver
bcm63xx_driver[] = {
75
{
76
.phy_id = 0x00406000,
77
.phy_id_mask = 0xfffffc00,
78
.name =
"Broadcom BCM63XX (1)"
,
79
/* ASYM_PAUSE bit is marked RO in datasheet, so don't cheat */
80
.features = (
PHY_BASIC_FEATURES
|
SUPPORTED_Pause
),
81
.
flags
=
PHY_HAS_INTERRUPT
,
82
.
config_init
= bcm63xx_config_init,
83
.
config_aneg
=
genphy_config_aneg
,
84
.
read_status
=
genphy_read_status
,
85
.
ack_interrupt
= bcm63xx_ack_interrupt,
86
.
config_intr
= bcm63xx_config_intr,
87
.
driver
= { .owner =
THIS_MODULE
},
88
}, {
89
/* same phy as above, with just a different OUI */
90
.phy_id = 0x002bdc00,
91
.phy_id_mask = 0xfffffc00,
92
.name =
"Broadcom BCM63XX (2)"
,
93
.features = (
PHY_BASIC_FEATURES
|
SUPPORTED_Pause
),
94
.
flags
=
PHY_HAS_INTERRUPT
,
95
.
config_init
= bcm63xx_config_init,
96
.
config_aneg
=
genphy_config_aneg
,
97
.
read_status
=
genphy_read_status
,
98
.
ack_interrupt
= bcm63xx_ack_interrupt,
99
.
config_intr
= bcm63xx_config_intr,
100
.
driver
= { .owner =
THIS_MODULE
},
101
} };
102
103
static
int
__init
bcm63xx_phy_init(
void
)
104
{
105
return
phy_drivers_register
(bcm63xx_driver,
106
ARRAY_SIZE
(bcm63xx_driver));
107
}
108
109
static
void
__exit
bcm63xx_phy_exit(
void
)
110
{
111
phy_drivers_unregister
(bcm63xx_driver,
112
ARRAY_SIZE
(bcm63xx_driver));
113
}
114
115
module_init
(bcm63xx_phy_init);
116
module_exit
(bcm63xx_phy_exit);
117
118
static
struct
mdio_device_id
__maybe_unused
bcm63xx_tbl[] = {
119
{ 0x00406000, 0xfffffc00 },
120
{ 0x002bdc00, 0xfffffc00 },
121
{ }
122
};
123
124
MODULE_DEVICE_TABLE
(mdio, bcm63xx_tbl);
Generated on Thu Jan 10 2013 14:07:04 for Linux Kernel by
1.8.2