diff options
Diffstat (limited to 'drivers/net/phy/fixed_phy.c')
-rw-r--r-- | drivers/net/phy/fixed_phy.c | 110 |
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 | ||
43 | static struct platform_device *pdev; | 45 | static 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 | ||
109 | done: | ||
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, | |||
215 | EXPORT_SYMBOL(fixed_phy_update_state); | 243 | EXPORT_SYMBOL(fixed_phy_update_state); |
216 | 244 | ||
217 | int fixed_phy_add(unsigned int irq, int phy_addr, | 245 | int 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 | ||
280 | err_gpio: | ||
281 | if (gpio_is_valid(fp->link_gpio)) | ||
282 | gpio_free(fp->link_gpio); | ||
243 | err_regs: | 283 | err_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 | ||
267 | struct phy_device *fixed_phy_register(unsigned int irq, | 309 | struct 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) { |