aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/fixed_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/fixed_phy.c')
-rw-r--r--drivers/net/phy/fixed_phy.c110
1 files changed, 83 insertions, 27 deletions
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index 99d9bc19c94a..12c7eb2c604e 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -22,6 +22,7 @@
22#include <linux/err.h> 22#include <linux/err.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/gpio.h>
25 26
26#define MII_REGS_NUM 29 27#define MII_REGS_NUM 29
27 28
@@ -38,6 +39,7 @@ struct fixed_phy {
38 struct fixed_phy_status status; 39 struct fixed_phy_status status;
39 int (*link_update)(struct net_device *, struct fixed_phy_status *); 40 int (*link_update)(struct net_device *, struct fixed_phy_status *);
40 struct list_head node; 41 struct list_head node;
42 int link_gpio;
41}; 43};
42 44
43static struct platform_device *pdev; 45static struct platform_device *pdev;
@@ -52,61 +54,87 @@ static int fixed_phy_update_regs(struct fixed_phy *fp)
52 u16 lpagb = 0; 54 u16 lpagb = 0;
53 u16 lpa = 0; 55 u16 lpa = 0;
54 56
55 if (!fp->status.link) 57 if (gpio_is_valid(fp->link_gpio))
56 goto done; 58 fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio);
57 bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
58 59
59 if (fp->status.duplex) { 60 if (fp->status.duplex) {
60 bmcr |= BMCR_FULLDPLX;
61
62 switch (fp->status.speed) { 61 switch (fp->status.speed) {
63 case 1000: 62 case 1000:
64 bmsr |= BMSR_ESTATEN; 63 bmsr |= BMSR_ESTATEN;
65 bmcr |= BMCR_SPEED1000;
66 lpagb |= LPA_1000FULL;
67 break; 64 break;
68 case 100: 65 case 100:
69 bmsr |= BMSR_100FULL; 66 bmsr |= BMSR_100FULL;
70 bmcr |= BMCR_SPEED100;
71 lpa |= LPA_100FULL;
72 break; 67 break;
73 case 10: 68 case 10:
74 bmsr |= BMSR_10FULL; 69 bmsr |= BMSR_10FULL;
75 lpa |= LPA_10FULL;
76 break; 70 break;
77 default: 71 default:
78 pr_warn("fixed phy: unknown speed\n"); 72 break;
79 return -EINVAL;
80 } 73 }
81 } else { 74 } else {
82 switch (fp->status.speed) { 75 switch (fp->status.speed) {
83 case 1000: 76 case 1000:
84 bmsr |= BMSR_ESTATEN; 77 bmsr |= BMSR_ESTATEN;
85 bmcr |= BMCR_SPEED1000;
86 lpagb |= LPA_1000HALF;
87 break; 78 break;
88 case 100: 79 case 100:
89 bmsr |= BMSR_100HALF; 80 bmsr |= BMSR_100HALF;
90 bmcr |= BMCR_SPEED100;
91 lpa |= LPA_100HALF;
92 break; 81 break;
93 case 10: 82 case 10:
94 bmsr |= BMSR_10HALF; 83 bmsr |= BMSR_10HALF;
95 lpa |= LPA_10HALF;
96 break; 84 break;
97 default: 85 default:
98 pr_warn("fixed phy: unknown speed\n"); 86 break;
99 return -EINVAL;
100 } 87 }
101 } 88 }
102 89
103 if (fp->status.pause) 90 if (fp->status.link) {
104 lpa |= LPA_PAUSE_CAP; 91 bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
92
93 if (fp->status.duplex) {
94 bmcr |= BMCR_FULLDPLX;
95
96 switch (fp->status.speed) {
97 case 1000:
98 bmcr |= BMCR_SPEED1000;
99 lpagb |= LPA_1000FULL;
100 break;
101 case 100:
102 bmcr |= BMCR_SPEED100;
103 lpa |= LPA_100FULL;
104 break;
105 case 10:
106 lpa |= LPA_10FULL;
107 break;
108 default:
109 pr_warn("fixed phy: unknown speed\n");
110 return -EINVAL;
111 }
112 } else {
113 switch (fp->status.speed) {
114 case 1000:
115 bmcr |= BMCR_SPEED1000;
116 lpagb |= LPA_1000HALF;
117 break;
118 case 100:
119 bmcr |= BMCR_SPEED100;
120 lpa |= LPA_100HALF;
121 break;
122 case 10:
123 lpa |= LPA_10HALF;
124 break;
125 default:
126 pr_warn("fixed phy: unknown speed\n");
127 return -EINVAL;
128 }
129 }
130
131 if (fp->status.pause)
132 lpa |= LPA_PAUSE_CAP;
105 133
106 if (fp->status.asym_pause) 134 if (fp->status.asym_pause)
107 lpa |= LPA_PAUSE_ASYM; 135 lpa |= LPA_PAUSE_ASYM;
136 }
108 137
109done:
110 fp->regs[MII_PHYSID1] = 0; 138 fp->regs[MII_PHYSID1] = 0;
111 fp->regs[MII_PHYSID2] = 0; 139 fp->regs[MII_PHYSID2] = 0;
112 140
@@ -215,7 +243,8 @@ int fixed_phy_update_state(struct phy_device *phydev,
215EXPORT_SYMBOL(fixed_phy_update_state); 243EXPORT_SYMBOL(fixed_phy_update_state);
216 244
217int fixed_phy_add(unsigned int irq, int phy_addr, 245int fixed_phy_add(unsigned int irq, int phy_addr,
218 struct fixed_phy_status *status) 246 struct fixed_phy_status *status,
247 int link_gpio)
219{ 248{
220 int ret; 249 int ret;
221 struct fixed_mdio_bus *fmb = &platform_fmb; 250 struct fixed_mdio_bus *fmb = &platform_fmb;
@@ -231,15 +260,26 @@ int fixed_phy_add(unsigned int irq, int phy_addr,
231 260
232 fp->addr = phy_addr; 261 fp->addr = phy_addr;
233 fp->status = *status; 262 fp->status = *status;
263 fp->link_gpio = link_gpio;
264
265 if (gpio_is_valid(fp->link_gpio)) {
266 ret = gpio_request_one(fp->link_gpio, GPIOF_DIR_IN,
267 "fixed-link-gpio-link");
268 if (ret)
269 goto err_regs;
270 }
234 271
235 ret = fixed_phy_update_regs(fp); 272 ret = fixed_phy_update_regs(fp);
236 if (ret) 273 if (ret)
237 goto err_regs; 274 goto err_gpio;
238 275
239 list_add_tail(&fp->node, &fmb->phys); 276 list_add_tail(&fp->node, &fmb->phys);
240 277
241 return 0; 278 return 0;
242 279
280err_gpio:
281 if (gpio_is_valid(fp->link_gpio))
282 gpio_free(fp->link_gpio);
243err_regs: 283err_regs:
244 kfree(fp); 284 kfree(fp);
245 return ret; 285 return ret;
@@ -254,6 +294,8 @@ void fixed_phy_del(int phy_addr)
254 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { 294 list_for_each_entry_safe(fp, tmp, &fmb->phys, node) {
255 if (fp->addr == phy_addr) { 295 if (fp->addr == phy_addr) {
256 list_del(&fp->node); 296 list_del(&fp->node);
297 if (gpio_is_valid(fp->link_gpio))
298 gpio_free(fp->link_gpio);
257 kfree(fp); 299 kfree(fp);
258 return; 300 return;
259 } 301 }
@@ -266,6 +308,7 @@ static DEFINE_SPINLOCK(phy_fixed_addr_lock);
266 308
267struct phy_device *fixed_phy_register(unsigned int irq, 309struct phy_device *fixed_phy_register(unsigned int irq,
268 struct fixed_phy_status *status, 310 struct fixed_phy_status *status,
311 int link_gpio,
269 struct device_node *np) 312 struct device_node *np)
270{ 313{
271 struct fixed_mdio_bus *fmb = &platform_fmb; 314 struct fixed_mdio_bus *fmb = &platform_fmb;
@@ -282,7 +325,7 @@ struct phy_device *fixed_phy_register(unsigned int irq,
282 phy_addr = phy_fixed_addr++; 325 phy_addr = phy_fixed_addr++;
283 spin_unlock(&phy_fixed_addr_lock); 326 spin_unlock(&phy_fixed_addr_lock);
284 327
285 ret = fixed_phy_add(PHY_POLL, phy_addr, status); 328 ret = fixed_phy_add(PHY_POLL, phy_addr, status, link_gpio);
286 if (ret < 0) 329 if (ret < 0)
287 return ERR_PTR(ret); 330 return ERR_PTR(ret);
288 331
@@ -303,6 +346,19 @@ struct phy_device *fixed_phy_register(unsigned int irq,
303 346
304 of_node_get(np); 347 of_node_get(np);
305 phy->dev.of_node = np; 348 phy->dev.of_node = np;
349 phy->is_pseudo_fixed_link = true;
350
351 switch (status->speed) {
352 case SPEED_1000:
353 phy->supported = PHY_1000BT_FEATURES;
354 break;
355 case SPEED_100:
356 phy->supported = PHY_100BT_FEATURES;
357 break;
358 case SPEED_10:
359 default:
360 phy->supported = PHY_10BT_FEATURES;
361 }
306 362
307 ret = phy_device_register(phy); 363 ret = phy_device_register(phy);
308 if (ret) { 364 if (ret) {