aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/devicetree/bindings/net/fixed-link.txt14
-rw-r--r--Documentation/networking/stmmac.txt2
-rw-r--r--arch/m68k/coldfire/m5272.c2
-rw-r--r--arch/mips/ar7/platform.c5
-rw-r--r--arch/mips/bcm47xx/setup.c2
-rw-r--r--drivers/net/dsa/mv88e6123_61_65.c1
-rw-r--r--drivers/net/dsa/mv88e6131.c1
-rw-r--r--drivers/net/dsa/mv88e6171.c1
-rw-r--r--drivers/net/dsa/mv88e6352.c1
-rw-r--r--drivers/net/dsa/mv88e6xxx.c73
-rw-r--r--drivers/net/dsa/mv88e6xxx.h4
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c2
-rw-r--r--drivers/net/phy/fixed_phy.c110
-rw-r--r--drivers/of/of_mdio.c13
-rw-r--r--include/linux/phy.h12
-rw-r--r--include/linux/phy_fixed.h8
-rw-r--r--net/dsa/dsa.c43
17 files changed, 255 insertions, 39 deletions
diff --git a/Documentation/devicetree/bindings/net/fixed-link.txt b/Documentation/devicetree/bindings/net/fixed-link.txt
index 82bf7e0f47b6..ec5d889fe3d8 100644
--- a/Documentation/devicetree/bindings/net/fixed-link.txt
+++ b/Documentation/devicetree/bindings/net/fixed-link.txt
@@ -17,6 +17,8 @@ properties:
17 enabled. 17 enabled.
18* 'asym-pause' (boolean, optional), to indicate that asym_pause should 18* 'asym-pause' (boolean, optional), to indicate that asym_pause should
19 be enabled. 19 be enabled.
20* 'link-gpios' ('gpio-list', optional), to indicate if a gpio can be read
21 to determine if the link is up.
20 22
21Old, deprecated 'fixed-link' binding: 23Old, deprecated 'fixed-link' binding:
22 24
@@ -30,7 +32,7 @@ Old, deprecated 'fixed-link' binding:
30 - e: asymmetric pause configuration: 0 for no asymmetric pause, 1 for 32 - e: asymmetric pause configuration: 0 for no asymmetric pause, 1 for
31 asymmetric pause 33 asymmetric pause
32 34
33Example: 35Examples:
34 36
35ethernet@0 { 37ethernet@0 {
36 ... 38 ...
@@ -40,3 +42,13 @@ ethernet@0 {
40 }; 42 };
41 ... 43 ...
42}; 44};
45
46ethernet@1 {
47 ...
48 fixed-link {
49 speed = <1000>;
50 pause;
51 link-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
52 };
53 ...
54};
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 2903b1cf4d70..d64a14714236 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -254,7 +254,7 @@ static struct fixed_phy_status stmmac0_fixed_phy_status = {
254 254
255During the board's device_init we can configure the first 255During the board's device_init we can configure the first
256MAC for fixed_link by calling: 256MAC for fixed_link by calling:
257 fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status));) 257 fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status, -1);
258and the second one, with a real PHY device attached to the bus, 258and the second one, with a real PHY device attached to the bus,
259by using the stmmac_mdio_bus_data structure (to provide the id, the 259by using the stmmac_mdio_bus_data structure (to provide the id, the
260reset procedure etc). 260reset procedure etc).
diff --git a/arch/m68k/coldfire/m5272.c b/arch/m68k/coldfire/m5272.c
index b15219ed22bf..c525e4c08f84 100644
--- a/arch/m68k/coldfire/m5272.c
+++ b/arch/m68k/coldfire/m5272.c
@@ -126,7 +126,7 @@ static struct fixed_phy_status nettel_fixed_phy_status __initdata = {
126static int __init init_BSP(void) 126static int __init init_BSP(void)
127{ 127{
128 m5272_uarts_init(); 128 m5272_uarts_init();
129 fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status); 129 fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status, -1);
130 return 0; 130 return 0;
131} 131}
132 132
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index be9ff1673ded..298b97715d5f 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -679,7 +679,8 @@ static int __init ar7_register_devices(void)
679 } 679 }
680 680
681 if (ar7_has_high_cpmac()) { 681 if (ar7_has_high_cpmac()) {
682 res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status); 682 res = fixed_phy_add(PHY_POLL, cpmac_high.id,
683 &fixed_phy_status, -1);
683 if (!res) { 684 if (!res) {
684 cpmac_get_mac(1, cpmac_high_data.dev_addr); 685 cpmac_get_mac(1, cpmac_high_data.dev_addr);
685 686
@@ -692,7 +693,7 @@ static int __init ar7_register_devices(void)
692 } else 693 } else
693 cpmac_low_data.phy_mask = 0xffffffff; 694 cpmac_low_data.phy_mask = 0xffffffff;
694 695
695 res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status); 696 res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status, -1);
696 if (!res) { 697 if (!res) {
697 cpmac_get_mac(0, cpmac_low_data.dev_addr); 698 cpmac_get_mac(0, cpmac_low_data.dev_addr);
698 res = platform_device_register(&cpmac_low); 699 res = platform_device_register(&cpmac_low);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 98c075f81795..17503a05938e 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -263,7 +263,7 @@ static int __init bcm47xx_register_bus_complete(void)
263 bcm47xx_leds_register(); 263 bcm47xx_leds_register();
264 bcm47xx_workarounds(); 264 bcm47xx_workarounds();
265 265
266 fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status); 266 fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status, -1);
267 return 0; 267 return 0;
268} 268}
269device_initcall(bcm47xx_register_bus_complete); 269device_initcall(bcm47xx_register_bus_complete);
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index 71a29a7ce538..3de2a6d73fdc 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -129,6 +129,7 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = {
129 .get_strings = mv88e6xxx_get_strings, 129 .get_strings = mv88e6xxx_get_strings,
130 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 130 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
131 .get_sset_count = mv88e6xxx_get_sset_count, 131 .get_sset_count = mv88e6xxx_get_sset_count,
132 .adjust_link = mv88e6xxx_adjust_link,
132#ifdef CONFIG_NET_DSA_HWMON 133#ifdef CONFIG_NET_DSA_HWMON
133 .get_temp = mv88e6xxx_get_temp, 134 .get_temp = mv88e6xxx_get_temp,
134#endif 135#endif
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 32f4a08e9bc9..3e8386529965 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -182,6 +182,7 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
182 .get_strings = mv88e6xxx_get_strings, 182 .get_strings = mv88e6xxx_get_strings,
183 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 183 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
184 .get_sset_count = mv88e6xxx_get_sset_count, 184 .get_sset_count = mv88e6xxx_get_sset_count,
185 .adjust_link = mv88e6xxx_adjust_link,
185}; 186};
186 187
187MODULE_ALIAS("platform:mv88e6085"); 188MODULE_ALIAS("platform:mv88e6085");
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 735f04cd83ee..d54b7400e8d8 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -108,6 +108,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
108 .get_strings = mv88e6xxx_get_strings, 108 .get_strings = mv88e6xxx_get_strings,
109 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 109 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
110 .get_sset_count = mv88e6xxx_get_sset_count, 110 .get_sset_count = mv88e6xxx_get_sset_count,
111 .adjust_link = mv88e6xxx_adjust_link,
111#ifdef CONFIG_NET_DSA_HWMON 112#ifdef CONFIG_NET_DSA_HWMON
112 .get_temp = mv88e6xxx_get_temp, 113 .get_temp = mv88e6xxx_get_temp,
113#endif 114#endif
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 14b71779df99..1f5129c105fb 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -328,6 +328,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
328 .get_strings = mv88e6xxx_get_strings, 328 .get_strings = mv88e6xxx_get_strings,
329 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, 329 .get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
330 .get_sset_count = mv88e6xxx_get_sset_count, 330 .get_sset_count = mv88e6xxx_get_sset_count,
331 .adjust_link = mv88e6xxx_adjust_link,
331 .set_eee = mv88e6xxx_set_eee, 332 .set_eee = mv88e6xxx_set_eee,
332 .get_eee = mv88e6xxx_get_eee, 333 .get_eee = mv88e6xxx_get_eee,
333#ifdef CONFIG_NET_DSA_HWMON 334#ifdef CONFIG_NET_DSA_HWMON
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 3774f53d28d7..6f13f7206762 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -14,6 +14,7 @@
14#include <linux/debugfs.h> 14#include <linux/debugfs.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/etherdevice.h> 16#include <linux/etherdevice.h>
17#include <linux/ethtool.h>
17#include <linux/if_bridge.h> 18#include <linux/if_bridge.h>
18#include <linux/jiffies.h> 19#include <linux/jiffies.h>
19#include <linux/list.h> 20#include <linux/list.h>
@@ -394,6 +395,7 @@ void mv88e6xxx_poll_link(struct dsa_switch *ds)
394 for (i = 0; i < DSA_MAX_PORTS; i++) { 395 for (i = 0; i < DSA_MAX_PORTS; i++) {
395 struct net_device *dev; 396 struct net_device *dev;
396 int uninitialized_var(port_status); 397 int uninitialized_var(port_status);
398 int pcs_ctrl;
397 int link; 399 int link;
398 int speed; 400 int speed;
399 int duplex; 401 int duplex;
@@ -403,6 +405,10 @@ void mv88e6xxx_poll_link(struct dsa_switch *ds)
403 if (dev == NULL) 405 if (dev == NULL)
404 continue; 406 continue;
405 407
408 pcs_ctrl = mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_PCS_CTRL);
409 if (pcs_ctrl < 0 || pcs_ctrl & PORT_PCS_CTRL_FORCE_LINK)
410 continue;
411
406 link = 0; 412 link = 0;
407 if (dev->flags & IFF_UP) { 413 if (dev->flags & IFF_UP) {
408 port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 414 port_status = mv88e6xxx_reg_read(ds, REG_PORT(i),
@@ -560,6 +566,73 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
560 return false; 566 return false;
561} 567}
562 568
569/* We expect the switch to perform auto negotiation if there is a real
570 * phy. However, in the case of a fixed link phy, we force the port
571 * settings from the fixed link settings.
572 */
573void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
574 struct phy_device *phydev)
575{
576 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
577 u32 ret, reg;
578
579 if (!phy_is_pseudo_fixed_link(phydev))
580 return;
581
582 mutex_lock(&ps->smi_mutex);
583
584 ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
585 if (ret < 0)
586 goto out;
587
588 reg = ret & ~(PORT_PCS_CTRL_LINK_UP |
589 PORT_PCS_CTRL_FORCE_LINK |
590 PORT_PCS_CTRL_DUPLEX_FULL |
591 PORT_PCS_CTRL_FORCE_DUPLEX |
592 PORT_PCS_CTRL_UNFORCED);
593
594 reg |= PORT_PCS_CTRL_FORCE_LINK;
595 if (phydev->link)
596 reg |= PORT_PCS_CTRL_LINK_UP;
597
598 if (mv88e6xxx_6065_family(ds) && phydev->speed > SPEED_100)
599 goto out;
600
601 switch (phydev->speed) {
602 case SPEED_1000:
603 reg |= PORT_PCS_CTRL_1000;
604 break;
605 case SPEED_100:
606 reg |= PORT_PCS_CTRL_100;
607 break;
608 case SPEED_10:
609 reg |= PORT_PCS_CTRL_10;
610 break;
611 default:
612 pr_info("Unknown speed");
613 goto out;
614 }
615
616 reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
617 if (phydev->duplex == DUPLEX_FULL)
618 reg |= PORT_PCS_CTRL_DUPLEX_FULL;
619
620 if ((mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds)) &&
621 (port >= ps->num_ports - 2)) {
622 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
623 reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
624 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
625 reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
626 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
627 reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
628 PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
629 }
630 _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_PCS_CTRL, reg);
631
632out:
633 mutex_unlock(&ps->smi_mutex);
634}
635
563/* Must be called with SMI mutex held */ 636/* Must be called with SMI mutex held */
564static int _mv88e6xxx_stats_wait(struct dsa_switch *ds) 637static int _mv88e6xxx_stats_wait(struct dsa_switch *ds)
565{ 638{
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index 72ca887feb0d..9b6f3d9d5ae1 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -46,6 +46,8 @@
46#define PORT_STATUS_TX_PAUSED BIT(5) 46#define PORT_STATUS_TX_PAUSED BIT(5)
47#define PORT_STATUS_FLOW_CTRL BIT(4) 47#define PORT_STATUS_FLOW_CTRL BIT(4)
48#define PORT_PCS_CTRL 0x01 48#define PORT_PCS_CTRL 0x01
49#define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15)
50#define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14)
49#define PORT_PCS_CTRL_FC BIT(7) 51#define PORT_PCS_CTRL_FC BIT(7)
50#define PORT_PCS_CTRL_FORCE_FC BIT(6) 52#define PORT_PCS_CTRL_FORCE_FC BIT(6)
51#define PORT_PCS_CTRL_LINK_UP BIT(5) 53#define PORT_PCS_CTRL_LINK_UP BIT(5)
@@ -446,6 +448,8 @@ void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
446 uint64_t *data); 448 uint64_t *data);
447int mv88e6xxx_get_sset_count(struct dsa_switch *ds); 449int mv88e6xxx_get_sset_count(struct dsa_switch *ds);
448int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds); 450int mv88e6xxx_get_sset_count_basic(struct dsa_switch *ds);
451void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
452 struct phy_device *phydev);
449int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port); 453int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
450void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, 454void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
451 struct ethtool_regs *regs, void *_p); 455 struct ethtool_regs *regs, void *_p);
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index b3679ad1c1c7..c8affad76f36 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -585,7 +585,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
585 .asym_pause = 0, 585 .asym_pause = 0,
586 }; 586 };
587 587
588 phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); 588 phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
589 if (!phydev || IS_ERR(phydev)) { 589 if (!phydev || IS_ERR(phydev)) {
590 dev_err(kdev, "failed to register fixed PHY device\n"); 590 dev_err(kdev, "failed to register fixed PHY device\n");
591 return -ENODEV; 591 return -ENODEV;
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) {
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 7c8c23cc6896..1350fa25cdb0 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -16,6 +16,7 @@
16#include <linux/phy.h> 16#include <linux/phy.h>
17#include <linux/phy_fixed.h> 17#include <linux/phy_fixed.h>
18#include <linux/of.h> 18#include <linux/of.h>
19#include <linux/of_gpio.h>
19#include <linux/of_irq.h> 20#include <linux/of_irq.h>
20#include <linux/of_mdio.h> 21#include <linux/of_mdio.h>
21#include <linux/module.h> 22#include <linux/module.h>
@@ -294,6 +295,7 @@ int of_phy_register_fixed_link(struct device_node *np)
294 struct fixed_phy_status status = {}; 295 struct fixed_phy_status status = {};
295 struct device_node *fixed_link_node; 296 struct device_node *fixed_link_node;
296 const __be32 *fixed_link_prop; 297 const __be32 *fixed_link_prop;
298 int link_gpio;
297 int len, err; 299 int len, err;
298 struct phy_device *phy; 300 struct phy_device *phy;
299 const char *managed; 301 const char *managed;
@@ -302,7 +304,7 @@ int of_phy_register_fixed_link(struct device_node *np)
302 if (err == 0) { 304 if (err == 0) {
303 if (strcmp(managed, "in-band-status") == 0) { 305 if (strcmp(managed, "in-band-status") == 0) {
304 /* status is zeroed, namely its .link member */ 306 /* status is zeroed, namely its .link member */
305 phy = fixed_phy_register(PHY_POLL, &status, np); 307 phy = fixed_phy_register(PHY_POLL, &status, -1, np);
306 return IS_ERR(phy) ? PTR_ERR(phy) : 0; 308 return IS_ERR(phy) ? PTR_ERR(phy) : 0;
307 } 309 }
308 } 310 }
@@ -318,8 +320,13 @@ int of_phy_register_fixed_link(struct device_node *np)
318 status.pause = of_property_read_bool(fixed_link_node, "pause"); 320 status.pause = of_property_read_bool(fixed_link_node, "pause");
319 status.asym_pause = of_property_read_bool(fixed_link_node, 321 status.asym_pause = of_property_read_bool(fixed_link_node,
320 "asym-pause"); 322 "asym-pause");
323 link_gpio = of_get_named_gpio_flags(fixed_link_node,
324 "link-gpios", 0, NULL);
321 of_node_put(fixed_link_node); 325 of_node_put(fixed_link_node);
322 phy = fixed_phy_register(PHY_POLL, &status, np); 326 if (link_gpio == -EPROBE_DEFER)
327 return -EPROBE_DEFER;
328
329 phy = fixed_phy_register(PHY_POLL, &status, link_gpio, np);
323 return IS_ERR(phy) ? PTR_ERR(phy) : 0; 330 return IS_ERR(phy) ? PTR_ERR(phy) : 0;
324 } 331 }
325 332
@@ -331,7 +338,7 @@ int of_phy_register_fixed_link(struct device_node *np)
331 status.speed = be32_to_cpu(fixed_link_prop[2]); 338 status.speed = be32_to_cpu(fixed_link_prop[2]);
332 status.pause = be32_to_cpu(fixed_link_prop[3]); 339 status.pause = be32_to_cpu(fixed_link_prop[3]);
333 status.asym_pause = be32_to_cpu(fixed_link_prop[4]); 340 status.asym_pause = be32_to_cpu(fixed_link_prop[4]);
334 phy = fixed_phy_register(PHY_POLL, &status, np); 341 phy = fixed_phy_register(PHY_POLL, &status, -1, np);
335 return IS_ERR(phy) ? PTR_ERR(phy) : 0; 342 return IS_ERR(phy) ? PTR_ERR(phy) : 0;
336 } 343 }
337 344
diff --git a/include/linux/phy.h b/include/linux/phy.h
index e5fb1d415961..962387a192f1 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -330,6 +330,7 @@ struct phy_c45_device_ids {
330 * c45_ids: 802.3-c45 Device Identifers if is_c45. 330 * c45_ids: 802.3-c45 Device Identifers if is_c45.
331 * is_c45: Set to true if this phy uses clause 45 addressing. 331 * is_c45: Set to true if this phy uses clause 45 addressing.
332 * is_internal: Set to true if this phy is internal to a MAC. 332 * is_internal: Set to true if this phy is internal to a MAC.
333 * is_pseudo_fixed_link: Set to true if this phy is an Ethernet switch, etc.
333 * has_fixups: Set to true if this phy has fixups/quirks. 334 * has_fixups: Set to true if this phy has fixups/quirks.
334 * suspended: Set to true if this phy has been suspended successfully. 335 * suspended: Set to true if this phy has been suspended successfully.
335 * state: state of the PHY for management purposes 336 * state: state of the PHY for management purposes
@@ -368,6 +369,7 @@ struct phy_device {
368 struct phy_c45_device_ids c45_ids; 369 struct phy_c45_device_ids c45_ids;
369 bool is_c45; 370 bool is_c45;
370 bool is_internal; 371 bool is_internal;
372 bool is_pseudo_fixed_link;
371 bool has_fixups; 373 bool has_fixups;
372 bool suspended; 374 bool suspended;
373 375
@@ -688,6 +690,16 @@ static inline bool phy_interface_is_rgmii(struct phy_device *phydev)
688{ 690{
689 return phydev->interface >= PHY_INTERFACE_MODE_RGMII && 691 return phydev->interface >= PHY_INTERFACE_MODE_RGMII &&
690 phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID; 692 phydev->interface <= PHY_INTERFACE_MODE_RGMII_TXID;
693};
694
695/*
696 * phy_is_pseudo_fixed_link - Convenience function for testing if this
697 * PHY is the CPU port facing side of an Ethernet switch, or similar.
698 * @phydev: the phy_device struct
699 */
700static inline bool phy_is_pseudo_fixed_link(struct phy_device *phydev)
701{
702 return phydev->is_pseudo_fixed_link;
691} 703}
692 704
693/** 705/**
diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
index fe5732d53eda..2400d2ea4f34 100644
--- a/include/linux/phy_fixed.h
+++ b/include/linux/phy_fixed.h
@@ -13,9 +13,11 @@ struct device_node;
13 13
14#if IS_ENABLED(CONFIG_FIXED_PHY) 14#if IS_ENABLED(CONFIG_FIXED_PHY)
15extern int fixed_phy_add(unsigned int irq, int phy_id, 15extern int fixed_phy_add(unsigned int irq, int phy_id,
16 struct fixed_phy_status *status); 16 struct fixed_phy_status *status,
17 int link_gpio);
17extern struct phy_device *fixed_phy_register(unsigned int irq, 18extern struct phy_device *fixed_phy_register(unsigned int irq,
18 struct fixed_phy_status *status, 19 struct fixed_phy_status *status,
20 int link_gpio,
19 struct device_node *np); 21 struct device_node *np);
20extern void fixed_phy_del(int phy_addr); 22extern void fixed_phy_del(int phy_addr);
21extern int fixed_phy_set_link_update(struct phy_device *phydev, 23extern int fixed_phy_set_link_update(struct phy_device *phydev,
@@ -26,12 +28,14 @@ extern int fixed_phy_update_state(struct phy_device *phydev,
26 const struct fixed_phy_status *changed); 28 const struct fixed_phy_status *changed);
27#else 29#else
28static inline int fixed_phy_add(unsigned int irq, int phy_id, 30static inline int fixed_phy_add(unsigned int irq, int phy_id,
29 struct fixed_phy_status *status) 31 struct fixed_phy_status *status,
32 int link_gpio)
30{ 33{
31 return -ENODEV; 34 return -ENODEV;
32} 35}
33static inline struct phy_device *fixed_phy_register(unsigned int irq, 36static inline struct phy_device *fixed_phy_register(unsigned int irq,
34 struct fixed_phy_status *status, 37 struct fixed_phy_status *status,
38 int gpio_link,
35 struct device_node *np) 39 struct device_node *np)
36{ 40{
37 return ERR_PTR(-ENODEV); 41 return ERR_PTR(-ENODEV);
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 053eb2b8e682..76e3800765f8 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -176,6 +176,41 @@ __ATTRIBUTE_GROUPS(dsa_hwmon);
176#endif /* CONFIG_NET_DSA_HWMON */ 176#endif /* CONFIG_NET_DSA_HWMON */
177 177
178/* basic switch operations **************************************************/ 178/* basic switch operations **************************************************/
179static int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct net_device *master)
180{
181 struct dsa_chip_data *cd = ds->pd;
182 struct device_node *port_dn;
183 struct phy_device *phydev;
184 int ret, port, mode;
185
186 for (port = 0; port < DSA_MAX_PORTS; port++) {
187 if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
188 continue;
189
190 port_dn = cd->port_dn[port];
191 if (of_phy_is_fixed_link(port_dn)) {
192 ret = of_phy_register_fixed_link(port_dn);
193 if (ret) {
194 netdev_err(master,
195 "failed to register fixed PHY\n");
196 return ret;
197 }
198 phydev = of_phy_find_device(port_dn);
199
200 mode = of_get_phy_mode(port_dn);
201 if (mode < 0)
202 mode = PHY_INTERFACE_MODE_NA;
203 phydev->interface = mode;
204
205 genphy_config_init(phydev);
206 genphy_read_status(phydev);
207 if (ds->drv->adjust_link)
208 ds->drv->adjust_link(ds, port, phydev);
209 }
210 }
211 return 0;
212}
213
179static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent) 214static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
180{ 215{
181 struct dsa_switch_driver *drv = ds->drv; 216 struct dsa_switch_driver *drv = ds->drv;
@@ -297,6 +332,14 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
297 } 332 }
298 } 333 }
299 334
335 /* Perform configuration of the CPU and DSA ports */
336 ret = dsa_cpu_dsa_setup(ds, dst->master_netdev);
337 if (ret < 0) {
338 netdev_err(dst->master_netdev, "[%d] : can't configure CPU and DSA ports\n",
339 index);
340 ret = 0;
341 }
342
300#ifdef CONFIG_NET_DSA_HWMON 343#ifdef CONFIG_NET_DSA_HWMON
301 /* If the switch provides a temperature sensor, 344 /* If the switch provides a temperature sensor,
302 * register with hardware monitoring subsystem. 345 * register with hardware monitoring subsystem.