aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/icplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/icplus.c')
-rw-r--r--drivers/net/phy/icplus.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index c81f136ae670..0856e1b7a849 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -30,16 +30,16 @@
30#include <asm/irq.h> 30#include <asm/irq.h>
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32 32
33MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IC1001 PHY drivers"); 33MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers");
34MODULE_AUTHOR("Michael Barkowski"); 34MODULE_AUTHOR("Michael Barkowski");
35MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
36 36
37/* IP101A/IP1001 */ 37/* IP101A/G - IP1001 */
38#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */ 38#define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */
39#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */ 39#define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */
40#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */ 40#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */
41#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ 41#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
42#define IP101A_APS_ON 2 /* IP101A APS Mode bit */ 42#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
43 43
44static int ip175c_config_init(struct phy_device *phydev) 44static int ip175c_config_init(struct phy_device *phydev)
45{ 45{
@@ -98,20 +98,24 @@ static int ip175c_config_init(struct phy_device *phydev)
98 98
99static int ip1xx_reset(struct phy_device *phydev) 99static int ip1xx_reset(struct phy_device *phydev)
100{ 100{
101 int err, bmcr; 101 int bmcr;
102 102
103 /* Software Reset PHY */ 103 /* Software Reset PHY */
104 bmcr = phy_read(phydev, MII_BMCR); 104 bmcr = phy_read(phydev, MII_BMCR);
105 if (bmcr < 0)
106 return bmcr;
105 bmcr |= BMCR_RESET; 107 bmcr |= BMCR_RESET;
106 err = phy_write(phydev, MII_BMCR, bmcr); 108 bmcr = phy_write(phydev, MII_BMCR, bmcr);
107 if (err < 0) 109 if (bmcr < 0)
108 return err; 110 return bmcr;
109 111
110 do { 112 do {
111 bmcr = phy_read(phydev, MII_BMCR); 113 bmcr = phy_read(phydev, MII_BMCR);
114 if (bmcr < 0)
115 return bmcr;
112 } while (bmcr & BMCR_RESET); 116 } while (bmcr & BMCR_RESET);
113 117
114 return err; 118 return 0;
115} 119}
116 120
117static int ip1001_config_init(struct phy_device *phydev) 121static int ip1001_config_init(struct phy_device *phydev)
@@ -124,7 +128,10 @@ static int ip1001_config_init(struct phy_device *phydev)
124 128
125 /* Enable Auto Power Saving mode */ 129 /* Enable Auto Power Saving mode */
126 c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2); 130 c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2);
131 if (c < 0)
132 return c;
127 c |= IP1001_APS_ON; 133 c |= IP1001_APS_ON;
134 c = phy_write(phydev, IP1001_SPEC_CTRL_STATUS_2, c);
128 if (c < 0) 135 if (c < 0)
129 return c; 136 return c;
130 137
@@ -132,14 +139,19 @@ static int ip1001_config_init(struct phy_device *phydev)
132 /* Additional delay (2ns) used to adjust RX clock phase 139 /* Additional delay (2ns) used to adjust RX clock phase
133 * at RGMII interface */ 140 * at RGMII interface */
134 c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 141 c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
142 if (c < 0)
143 return c;
144
135 c |= IP1001_PHASE_SEL_MASK; 145 c |= IP1001_PHASE_SEL_MASK;
136 c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 146 c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
147 if (c < 0)
148 return c;
137 } 149 }
138 150
139 return c; 151 return 0;
140} 152}
141 153
142static int ip101a_config_init(struct phy_device *phydev) 154static int ip101a_g_config_init(struct phy_device *phydev)
143{ 155{
144 int c; 156 int c;
145 157
@@ -149,7 +161,7 @@ static int ip101a_config_init(struct phy_device *phydev)
149 161
150 /* Enable Auto Power Saving mode */ 162 /* Enable Auto Power Saving mode */
151 c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 163 c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
152 c |= IP101A_APS_ON; 164 c |= IP101A_G_APS_ON;
153 return c; 165 return c;
154} 166}
155 167
@@ -191,6 +203,7 @@ static struct phy_driver ip1001_driver = {
191 .phy_id_mask = 0x0ffffff0, 203 .phy_id_mask = 0x0ffffff0,
192 .features = PHY_GBIT_FEATURES | SUPPORTED_Pause | 204 .features = PHY_GBIT_FEATURES | SUPPORTED_Pause |
193 SUPPORTED_Asym_Pause, 205 SUPPORTED_Asym_Pause,
206 .flags = PHY_HAS_INTERRUPT,
194 .config_init = &ip1001_config_init, 207 .config_init = &ip1001_config_init,
195 .config_aneg = &genphy_config_aneg, 208 .config_aneg = &genphy_config_aneg,
196 .read_status = &genphy_read_status, 209 .read_status = &genphy_read_status,
@@ -199,13 +212,14 @@ static struct phy_driver ip1001_driver = {
199 .driver = { .owner = THIS_MODULE,}, 212 .driver = { .owner = THIS_MODULE,},
200}; 213};
201 214
202static struct phy_driver ip101a_driver = { 215static struct phy_driver ip101a_g_driver = {
203 .phy_id = 0x02430c54, 216 .phy_id = 0x02430c54,
204 .name = "ICPlus IP101A", 217 .name = "ICPlus IP101A/G",
205 .phy_id_mask = 0x0ffffff0, 218 .phy_id_mask = 0x0ffffff0,
206 .features = PHY_BASIC_FEATURES | SUPPORTED_Pause | 219 .features = PHY_BASIC_FEATURES | SUPPORTED_Pause |
207 SUPPORTED_Asym_Pause, 220 SUPPORTED_Asym_Pause,
208 .config_init = &ip101a_config_init, 221 .flags = PHY_HAS_INTERRUPT,
222 .config_init = &ip101a_g_config_init,
209 .config_aneg = &genphy_config_aneg, 223 .config_aneg = &genphy_config_aneg,
210 .read_status = &genphy_read_status, 224 .read_status = &genphy_read_status,
211 .suspend = genphy_suspend, 225 .suspend = genphy_suspend,
@@ -221,7 +235,7 @@ static int __init icplus_init(void)
221 if (ret < 0) 235 if (ret < 0)
222 return -ENODEV; 236 return -ENODEV;
223 237
224 ret = phy_driver_register(&ip101a_driver); 238 ret = phy_driver_register(&ip101a_g_driver);
225 if (ret < 0) 239 if (ret < 0)
226 return -ENODEV; 240 return -ENODEV;
227 241
@@ -231,7 +245,7 @@ static int __init icplus_init(void)
231static void __exit icplus_exit(void) 245static void __exit icplus_exit(void)
232{ 246{
233 phy_driver_unregister(&ip1001_driver); 247 phy_driver_unregister(&ip1001_driver);
234 phy_driver_unregister(&ip101a_driver); 248 phy_driver_unregister(&ip101a_g_driver);
235 phy_driver_unregister(&ip175c_driver); 249 phy_driver_unregister(&ip175c_driver);
236} 250}
237 251
@@ -241,6 +255,7 @@ module_exit(icplus_exit);
241static struct mdio_device_id __maybe_unused icplus_tbl[] = { 255static struct mdio_device_id __maybe_unused icplus_tbl[] = {
242 { 0x02430d80, 0x0ffffff0 }, 256 { 0x02430d80, 0x0ffffff0 },
243 { 0x02430d90, 0x0ffffff0 }, 257 { 0x02430d90, 0x0ffffff0 },
258 { 0x02430c54, 0x0ffffff0 },
244 { } 259 { }
245}; 260};
246 261