diff options
Diffstat (limited to 'drivers/net/phy/fixed_phy.c')
-rw-r--r-- | drivers/net/phy/fixed_phy.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index 2f9457f05a2e..1bb70e3cc03e 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,6 +54,9 @@ 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 | ||
57 | if (gpio_is_valid(fp->link_gpio)) | ||
58 | fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); | ||
59 | |||
55 | if (!fp->status.link) | 60 | if (!fp->status.link) |
56 | goto done; | 61 | goto done; |
57 | bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; | 62 | bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; |
@@ -215,7 +220,8 @@ int fixed_phy_update_state(struct phy_device *phydev, | |||
215 | EXPORT_SYMBOL(fixed_phy_update_state); | 220 | EXPORT_SYMBOL(fixed_phy_update_state); |
216 | 221 | ||
217 | int fixed_phy_add(unsigned int irq, int phy_addr, | 222 | int fixed_phy_add(unsigned int irq, int phy_addr, |
218 | struct fixed_phy_status *status) | 223 | struct fixed_phy_status *status, |
224 | int link_gpio) | ||
219 | { | 225 | { |
220 | int ret; | 226 | int ret; |
221 | struct fixed_mdio_bus *fmb = &platform_fmb; | 227 | struct fixed_mdio_bus *fmb = &platform_fmb; |
@@ -231,15 +237,26 @@ int fixed_phy_add(unsigned int irq, int phy_addr, | |||
231 | 237 | ||
232 | fp->addr = phy_addr; | 238 | fp->addr = phy_addr; |
233 | fp->status = *status; | 239 | fp->status = *status; |
240 | fp->link_gpio = link_gpio; | ||
241 | |||
242 | if (gpio_is_valid(fp->link_gpio)) { | ||
243 | ret = gpio_request_one(fp->link_gpio, GPIOF_DIR_IN, | ||
244 | "fixed-link-gpio-link"); | ||
245 | if (ret) | ||
246 | goto err_regs; | ||
247 | } | ||
234 | 248 | ||
235 | ret = fixed_phy_update_regs(fp); | 249 | ret = fixed_phy_update_regs(fp); |
236 | if (ret) | 250 | if (ret) |
237 | goto err_regs; | 251 | goto err_gpio; |
238 | 252 | ||
239 | list_add_tail(&fp->node, &fmb->phys); | 253 | list_add_tail(&fp->node, &fmb->phys); |
240 | 254 | ||
241 | return 0; | 255 | return 0; |
242 | 256 | ||
257 | err_gpio: | ||
258 | if (gpio_is_valid(fp->link_gpio)) | ||
259 | gpio_free(fp->link_gpio); | ||
243 | err_regs: | 260 | err_regs: |
244 | kfree(fp); | 261 | kfree(fp); |
245 | return ret; | 262 | return ret; |
@@ -254,6 +271,8 @@ void fixed_phy_del(int phy_addr) | |||
254 | list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { | 271 | list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { |
255 | if (fp->addr == phy_addr) { | 272 | if (fp->addr == phy_addr) { |
256 | list_del(&fp->node); | 273 | list_del(&fp->node); |
274 | if (gpio_is_valid(fp->link_gpio)) | ||
275 | gpio_free(fp->link_gpio); | ||
257 | kfree(fp); | 276 | kfree(fp); |
258 | return; | 277 | return; |
259 | } | 278 | } |
@@ -266,6 +285,7 @@ static DEFINE_SPINLOCK(phy_fixed_addr_lock); | |||
266 | 285 | ||
267 | struct phy_device *fixed_phy_register(unsigned int irq, | 286 | struct phy_device *fixed_phy_register(unsigned int irq, |
268 | struct fixed_phy_status *status, | 287 | struct fixed_phy_status *status, |
288 | int link_gpio, | ||
269 | struct device_node *np) | 289 | struct device_node *np) |
270 | { | 290 | { |
271 | struct fixed_mdio_bus *fmb = &platform_fmb; | 291 | struct fixed_mdio_bus *fmb = &platform_fmb; |
@@ -282,7 +302,7 @@ struct phy_device *fixed_phy_register(unsigned int irq, | |||
282 | phy_addr = phy_fixed_addr++; | 302 | phy_addr = phy_fixed_addr++; |
283 | spin_unlock(&phy_fixed_addr_lock); | 303 | spin_unlock(&phy_fixed_addr_lock); |
284 | 304 | ||
285 | ret = fixed_phy_add(PHY_POLL, phy_addr, status); | 305 | ret = fixed_phy_add(PHY_POLL, phy_addr, status, link_gpio); |
286 | if (ret < 0) | 306 | if (ret < 0) |
287 | return ERR_PTR(ret); | 307 | return ERR_PTR(ret); |
288 | 308 | ||