swconfig: add (PHY) generic helper setting port link
authorRafał Miłecki <zajec5@gmail.com>
Wed, 3 Feb 2016 09:33:38 +0000 (09:33 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Wed, 3 Feb 2016 09:33:38 +0000 (09:33 +0000)
It's quite common for switches to have PHY per port so adding a generic
helper setting link state will help many drivers. It just needs an API
to access PHYs which this patch also adds.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 48621

target/linux/generic/files/drivers/net/phy/swconfig.c
target/linux/generic/files/include/linux/switch.h

index 4bfe64fbd0dc62a3007802eaeb1b4fef8e6cc956..68ddd246addab8897dde186484c08be138db9a00 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/switch.h>
 #include <linux/of.h>
 #include <linux/version.h>
+#include <uapi/linux/mii.h>
 
 #define SWCONFIG_DEVNAME       "switch%d"
 
@@ -1168,6 +1169,41 @@ unregister_switch(struct switch_dev *dev)
 }
 EXPORT_SYMBOL_GPL(unregister_switch);
 
+int
+switch_generic_set_link(struct switch_dev *dev, int port,
+                       struct switch_port_link *link)
+{
+       if (WARN_ON(!dev->ops->phy_write16))
+               return -ENOTSUPP;
+
+       /* Generic implementation */
+       if (link->aneg) {
+               dev->ops->phy_write16(dev, port, MII_BMCR, 0x0000);
+               dev->ops->phy_write16(dev, port, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
+       } else {
+               u16 bmcr = 0;
+
+               if (link->duplex)
+                       bmcr |= BMCR_FULLDPLX;
+
+               switch (link->speed) {
+               case SWITCH_PORT_SPEED_10:
+                       break;
+               case SWITCH_PORT_SPEED_100:
+                       bmcr |= BMCR_SPEED100;
+                       break;
+               case SWITCH_PORT_SPEED_1000:
+                       bmcr |= BMCR_SPEED1000;
+                       break;
+               default:
+                       return -ENOTSUPP;
+               }
+
+               dev->ops->phy_write16(dev, port, MII_BMCR, bmcr);
+       }
+
+       return 0;
+}
 
 static int __init
 swconfig_init(void)
index 4ada0e5d33a0f4ecd524aa4000c75148b40871bc..0c4cce7fa5ba0d3590b75d3c298ce1444207e0b4 100644 (file)
@@ -99,6 +99,9 @@ struct switch_dev_ops {
                             struct switch_port_link *link);
        int (*get_port_stats)(struct switch_dev *dev, int port,
                              struct switch_port_stats *stats);
+
+       int (*phy_read16)(struct switch_dev *dev, int addr, u8 reg, u16 *value);
+       int (*phy_write16)(struct switch_dev *dev, int addr, u8 reg, u16 value);
 };
 
 struct switch_dev {
@@ -170,4 +173,7 @@ struct switch_attr {
        int max;
 };
 
+int switch_generic_set_link(struct switch_dev *dev, int port,
+                           struct switch_port_link *link);
+
 #endif /* _LINUX_SWITCH_H */