aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/fixed_phy.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-08-31 17:48:03 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-31 17:48:03 -0400
commit684511ac2eeb015b7a9a46c575543566e1b1fb7c (patch)
treee755ec8c049139469d67a5f239002ec68c743113 /drivers/net/phy/fixed_phy.c
parent6ea3c9d5b042edf14eac1e21af21c41f81f3491e (diff)
parentbc0f4a87fc7e45642455682f281de2131cde9695 (diff)
Merge branch 'dsa-port-config'
Andrew Lunn says: ==================== DSA port configuration and status This patchset allows various switch port settings to be configured and port status to be sampled. Some of these patches have been posted before. The first three patches provide infrastructure for configuring a switch ports link speed and duplex from a fixed_link phy. Patch four then uses this infrastructure to allow the CPU and DSA ports of a switch to be configured using a fixed-link property in the device tree. Patches five and six allow a phy-mode property to be specified in the device tree, and allow this to be used for configuring RGMII delays. Patches seven through nine allow link status, for example that of an SFP module, to be read from a gpio. Changes since v1: Rewrite 9/9 so that it hopefully does not regression on 868a4215be9a6d80 ("net: phy: fixed_phy: handle link-down case") ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
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) {