diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2010-12-08 18:05:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-12-10 18:48:43 -0500 |
commit | 377ecca9ba6d98f31517e2322075e94d1be94561 (patch) | |
tree | f29578587457734c1579395740ee7034779d3b51 /drivers/net | |
parent | d9ca676bcb26e1fdff9265a3e70f697cd381c889 (diff) |
phy: add the IC+ IP1001 driver
This patch adds the IC+ IP1001 (Gigabit Ethernet Transceiver) driver.
I've had to add an additional delay (2ns) to adjust RX clock phase at
GMII/ RGMII interface (according to the PHY data-sheet). This helps to
have the RGMII working on some ST platforms.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/phy/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/phy/icplus.c | 59 |
2 files changed, 55 insertions, 6 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index cb3d13e4e074..35fda5ac8120 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
@@ -64,7 +64,7 @@ config BCM63XX_PHY | |||
64 | config ICPLUS_PHY | 64 | config ICPLUS_PHY |
65 | tristate "Drivers for ICPlus PHYs" | 65 | tristate "Drivers for ICPlus PHYs" |
66 | ---help--- | 66 | ---help--- |
67 | Currently supports the IP175C PHY. | 67 | Currently supports the IP175C and IP1001 PHYs. |
68 | 68 | ||
69 | config REALTEK_PHY | 69 | config REALTEK_PHY |
70 | tristate "Drivers for Realtek PHYs" | 70 | tristate "Drivers for Realtek PHYs" |
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index c1d2d251fe8b..9a09e24c30bc 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | 32 | ||
33 | MODULE_DESCRIPTION("ICPlus IP175C PHY driver"); | 33 | MODULE_DESCRIPTION("ICPlus IP175C/IC1001 PHY drivers"); |
34 | MODULE_AUTHOR("Michael Barkowski"); | 34 | MODULE_AUTHOR("Michael Barkowski"); |
35 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
36 | 36 | ||
@@ -89,6 +89,33 @@ static int ip175c_config_init(struct phy_device *phydev) | |||
89 | return 0; | 89 | return 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | static int ip1001_config_init(struct phy_device *phydev) | ||
93 | { | ||
94 | int err, value; | ||
95 | |||
96 | /* Software Reset PHY */ | ||
97 | value = phy_read(phydev, MII_BMCR); | ||
98 | value |= BMCR_RESET; | ||
99 | err = phy_write(phydev, MII_BMCR, value); | ||
100 | if (err < 0) | ||
101 | return err; | ||
102 | |||
103 | do { | ||
104 | value = phy_read(phydev, MII_BMCR); | ||
105 | } while (value & BMCR_RESET); | ||
106 | |||
107 | /* Additional delay (2ns) used to adjust RX clock phase | ||
108 | * at GMII/ RGMII interface */ | ||
109 | value = phy_read(phydev, 16); | ||
110 | value |= 0x3; | ||
111 | |||
112 | err = phy_write(phydev, 16, value); | ||
113 | if (err < 0) | ||
114 | return err; | ||
115 | |||
116 | return err; | ||
117 | } | ||
118 | |||
92 | static int ip175c_read_status(struct phy_device *phydev) | 119 | static int ip175c_read_status(struct phy_device *phydev) |
93 | { | 120 | { |
94 | if (phydev->addr == 4) /* WAN port */ | 121 | if (phydev->addr == 4) /* WAN port */ |
@@ -121,21 +148,43 @@ static struct phy_driver ip175c_driver = { | |||
121 | .driver = { .owner = THIS_MODULE,}, | 148 | .driver = { .owner = THIS_MODULE,}, |
122 | }; | 149 | }; |
123 | 150 | ||
124 | static int __init ip175c_init(void) | 151 | static struct phy_driver ip1001_driver = { |
152 | .phy_id = 0x02430d90, | ||
153 | .name = "ICPlus IP1001", | ||
154 | .phy_id_mask = 0x0ffffff0, | ||
155 | .features = PHY_GBIT_FEATURES | SUPPORTED_Pause | | ||
156 | SUPPORTED_Asym_Pause, | ||
157 | .config_init = &ip1001_config_init, | ||
158 | .config_aneg = &genphy_config_aneg, | ||
159 | .read_status = &genphy_read_status, | ||
160 | .suspend = genphy_suspend, | ||
161 | .resume = genphy_resume, | ||
162 | .driver = { .owner = THIS_MODULE,}, | ||
163 | }; | ||
164 | |||
165 | static int __init icplus_init(void) | ||
125 | { | 166 | { |
167 | int ret = 0; | ||
168 | |||
169 | ret = phy_driver_register(&ip1001_driver); | ||
170 | if (ret < 0) | ||
171 | return -ENODEV; | ||
172 | |||
126 | return phy_driver_register(&ip175c_driver); | 173 | return phy_driver_register(&ip175c_driver); |
127 | } | 174 | } |
128 | 175 | ||
129 | static void __exit ip175c_exit(void) | 176 | static void __exit icplus_exit(void) |
130 | { | 177 | { |
178 | phy_driver_unregister(&ip1001_driver); | ||
131 | phy_driver_unregister(&ip175c_driver); | 179 | phy_driver_unregister(&ip175c_driver); |
132 | } | 180 | } |
133 | 181 | ||
134 | module_init(ip175c_init); | 182 | module_init(icplus_init); |
135 | module_exit(ip175c_exit); | 183 | module_exit(icplus_exit); |
136 | 184 | ||
137 | static struct mdio_device_id __maybe_unused icplus_tbl[] = { | 185 | static struct mdio_device_id __maybe_unused icplus_tbl[] = { |
138 | { 0x02430d80, 0x0ffffff0 }, | 186 | { 0x02430d80, 0x0ffffff0 }, |
187 | { 0x02430d90, 0x0ffffff0 }, | ||
139 | { } | 188 | { } |
140 | }; | 189 | }; |
141 | 190 | ||