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.c26
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
43static struct platform_device *pdev; 45static 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,
215EXPORT_SYMBOL(fixed_phy_update_state); 220EXPORT_SYMBOL(fixed_phy_update_state);
216 221
217int fixed_phy_add(unsigned int irq, int phy_addr, 222int 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
257err_gpio:
258 if (gpio_is_valid(fp->link_gpio))
259 gpio_free(fp->link_gpio);
243err_regs: 260err_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
267struct phy_device *fixed_phy_register(unsigned int irq, 286struct 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