Merge branch 'micrel-next'
authorDavid S. Miller <davem@davemloft.net>
Wed, 12 Nov 2014 18:55:41 +0000 (13:55 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 12 Nov 2014 18:55:41 +0000 (13:55 -0500)
Johan Hovold says:

====================
net: phy: micrel: refactoring and KSZ8081/KSZ8091 features

This series cleans up and refactors parts of the micrel PHY driver, and
adds support for broadcast-address-disable and led-mode configuration
for KSZ8081 and KSZ8091 PHYs.

Specifically, this enables dual KSZ8081 setups (which are limited to
using address 0 and 3).

A follow up series will add device-type abstraction which will allow for
further refactoring and shared initialisation code.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/devicetree/bindings/net/micrel.txt
Documentation/devicetree/bindings/net/phy.txt
drivers/net/phy/micrel.c

index e1d99b95c4ec984e2adbf80b808a4bb0f0f90f05..30062fae5623b58fa80f9ea4b1d8756b1b123303 100644 (file)
@@ -14,6 +14,8 @@ Optional properties:
              KSZ8021: register 0x1f, bits 5..4
              KSZ8031: register 0x1f, bits 5..4
              KSZ8051: register 0x1f, bits 5..4
+             KSZ8081: register 0x1f, bits 5..4
+             KSZ8091: register 0x1f, bits 5..4
 
               See the respective PHY datasheet for the mode values.
 
index 5b8c5890307773cf52b62eded7c1869a9b7aa2a3..40831fbaff72102d6ff608ae06c1ddf4bedcdbae 100644 (file)
@@ -19,7 +19,6 @@ Optional Properties:
   specifications. If neither of these are specified, the default is to
   assume clause 22. The compatible list may also contain other
   elements.
-- max-speed: Maximum PHY supported speed (10, 100, 1000...)
 
   If the phy's identifier is known then the list may contain an entry
   of the form: "ethernet-phy-idAAAA.BBBB" where
@@ -29,6 +28,8 @@ Optional Properties:
             4 hex digits. This is the chip vendor OUI bits 19:24,
             followed by 10 bits of a vendor specific ID.
 
+- max-speed: Maximum PHY supported speed (10, 100, 1000...)
+
 Example:
 
 ethernet-phy@0 {
index bcc6c0ea75faf8724b77ffe00db9540cdffdd471..30e894d6ffbdb5ab08c654d3e8892044ea5f97cc 100644 (file)
 
 /* Operation Mode Strap Override */
 #define MII_KSZPHY_OMSO                                0x16
-#define KSZPHY_OMSO_B_CAST_OFF                 (1 << 9)
-#define KSZPHY_OMSO_RMII_OVERRIDE              (1 << 1)
-#define KSZPHY_OMSO_MII_OVERRIDE               (1 << 0)
+#define KSZPHY_OMSO_B_CAST_OFF                 BIT(9)
+#define KSZPHY_OMSO_RMII_OVERRIDE              BIT(1)
+#define KSZPHY_OMSO_MII_OVERRIDE               BIT(0)
 
 /* general Interrupt control/status reg in vendor specific block. */
 #define MII_KSZPHY_INTCS                       0x1B
-#define        KSZPHY_INTCS_JABBER                     (1 << 15)
-#define        KSZPHY_INTCS_RECEIVE_ERR                (1 << 14)
-#define        KSZPHY_INTCS_PAGE_RECEIVE               (1 << 13)
-#define        KSZPHY_INTCS_PARELLEL                   (1 << 12)
-#define        KSZPHY_INTCS_LINK_PARTNER_ACK           (1 << 11)
-#define        KSZPHY_INTCS_LINK_DOWN                  (1 << 10)
-#define        KSZPHY_INTCS_REMOTE_FAULT               (1 << 9)
-#define        KSZPHY_INTCS_LINK_UP                    (1 << 8)
+#define        KSZPHY_INTCS_JABBER                     BIT(15)
+#define        KSZPHY_INTCS_RECEIVE_ERR                BIT(14)
+#define        KSZPHY_INTCS_PAGE_RECEIVE               BIT(13)
+#define        KSZPHY_INTCS_PARELLEL                   BIT(12)
+#define        KSZPHY_INTCS_LINK_PARTNER_ACK           BIT(11)
+#define        KSZPHY_INTCS_LINK_DOWN                  BIT(10)
+#define        KSZPHY_INTCS_REMOTE_FAULT               BIT(9)
+#define        KSZPHY_INTCS_LINK_UP                    BIT(8)
 #define        KSZPHY_INTCS_ALL                        (KSZPHY_INTCS_LINK_UP |\
                                                KSZPHY_INTCS_LINK_DOWN)
 
-/* general PHY control reg in vendor specific block. */
-#define        MII_KSZPHY_CTRL                 0x1F
+/* PHY Control 1 */
+#define        MII_KSZPHY_CTRL_1                       0x1e
+
+/* PHY Control 2 / PHY Control (if no PHY Control 1) */
+#define        MII_KSZPHY_CTRL_2                       0x1f
+#define        MII_KSZPHY_CTRL                         MII_KSZPHY_CTRL_2
 /* bitmap of PHY register to set interrupt mode */
-#define KSZPHY_CTRL_INT_ACTIVE_HIGH            (1 << 9)
-#define KSZ9021_CTRL_INT_ACTIVE_HIGH           (1 << 14)
-#define KS8737_CTRL_INT_ACTIVE_HIGH            (1 << 14)
-#define KSZ8051_RMII_50MHZ_CLK                 (1 << 7)
+#define KSZPHY_CTRL_INT_ACTIVE_HIGH            BIT(9)
+#define KSZ9021_CTRL_INT_ACTIVE_HIGH           BIT(14)
+#define KS8737_CTRL_INT_ACTIVE_HIGH            BIT(14)
+#define KSZ8051_RMII_50MHZ_CLK                 BIT(7)
 
 /* Write/read to/from extended registers */
 #define MII_KSZPHY_EXTREG                       0x0b
@@ -122,6 +126,8 @@ static int kszphy_config_intr(struct phy_device *phydev)
 
        /* set the interrupt pin active low */
        temp = phy_read(phydev, MII_KSZPHY_CTRL);
+       if (temp < 0)
+               return temp;
        temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH;
        phy_write(phydev, MII_KSZPHY_CTRL, temp);
        rc = kszphy_set_interrupt(phydev);
@@ -134,6 +140,8 @@ static int ksz9021_config_intr(struct phy_device *phydev)
 
        /* set the interrupt pin active low */
        temp = phy_read(phydev, MII_KSZPHY_CTRL);
+       if (temp < 0)
+               return temp;
        temp &= ~KSZ9021_CTRL_INT_ACTIVE_HIGH;
        phy_write(phydev, MII_KSZPHY_CTRL, temp);
        rc = kszphy_set_interrupt(phydev);
@@ -146,19 +154,20 @@ static int ks8737_config_intr(struct phy_device *phydev)
 
        /* set the interrupt pin active low */
        temp = phy_read(phydev, MII_KSZPHY_CTRL);
+       if (temp < 0)
+               return temp;
        temp &= ~KS8737_CTRL_INT_ACTIVE_HIGH;
        phy_write(phydev, MII_KSZPHY_CTRL, temp);
        rc = kszphy_set_interrupt(phydev);
        return rc < 0 ? rc : 0;
 }
 
-static int kszphy_setup_led(struct phy_device *phydev,
-                           unsigned int reg, unsigned int shift)
+static int kszphy_setup_led(struct phy_device *phydev, u32 reg)
 {
 
        struct device *dev = &phydev->dev;
        struct device_node *of_node = dev->of_node;
-       int rc, temp;
+       int rc, temp, shift;
        u32 val;
 
        if (!of_node && dev->parent->of_node)
@@ -167,15 +176,55 @@ static int kszphy_setup_led(struct phy_device *phydev,
        if (of_property_read_u32(of_node, "micrel,led-mode", &val))
                return 0;
 
+       if (val > 3) {
+               dev_err(&phydev->dev, "invalid led mode: 0x%02x\n", val);
+               return -EINVAL;
+       }
+
+       switch (reg) {
+       case MII_KSZPHY_CTRL_1:
+               shift = 14;
+               break;
+       case MII_KSZPHY_CTRL_2:
+               shift = 4;
+               break;
+       default:
+               return -EINVAL;
+       }
+
        temp = phy_read(phydev, reg);
-       if (temp < 0)
-               return temp;
+       if (temp < 0) {
+               rc = temp;
+               goto out;
+       }
 
        temp &= ~(3 << shift);
        temp |= val << shift;
        rc = phy_write(phydev, reg, temp);
+out:
+       if (rc < 0)
+               dev_err(&phydev->dev, "failed to set led mode\n");
 
-       return rc < 0 ? rc : 0;
+       return rc;
+}
+
+/* Disable PHY address 0 as the broadcast address, so that it can be used as a
+ * unique (non-broadcast) address on a shared bus.
+ */
+static int kszphy_broadcast_disable(struct phy_device *phydev)
+{
+       int ret;
+
+       ret = phy_read(phydev, MII_KSZPHY_OMSO);
+       if (ret < 0)
+               goto out;
+
+       ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF);
+out:
+       if (ret)
+               dev_err(&phydev->dev, "failed to disable broadcast address\n");
+
+       return ret;
 }
 
 static int kszphy_config_init(struct phy_device *phydev)
@@ -185,23 +234,21 @@ static int kszphy_config_init(struct phy_device *phydev)
 
 static int kszphy_config_init_led8041(struct phy_device *phydev)
 {
-       /* single led control, register 0x1e bits 15..14 */
-       return kszphy_setup_led(phydev, 0x1e, 14);
+       return kszphy_setup_led(phydev, MII_KSZPHY_CTRL_1);
 }
 
 static int ksz8021_config_init(struct phy_device *phydev)
 {
-       const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
        int rc;
 
-       rc = kszphy_setup_led(phydev, 0x1f, 4);
-       if (rc)
-               dev_err(&phydev->dev, "failed to set led mode\n");
+       kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2);
 
        rc = ksz_config_flags(phydev);
        if (rc < 0)
                return rc;
-       rc = phy_write(phydev, MII_KSZPHY_OMSO, val);
+
+       rc = kszphy_broadcast_disable(phydev);
+
        return rc < 0 ? rc : 0;
 }
 
@@ -209,14 +256,20 @@ static int ks8051_config_init(struct phy_device *phydev)
 {
        int rc;
 
-       rc = kszphy_setup_led(phydev, 0x1f, 4);
-       if (rc)
-               dev_err(&phydev->dev, "failed to set led mode\n");
+       kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2);
 
        rc = ksz_config_flags(phydev);
        return rc < 0 ? rc : 0;
 }
 
+static int ksz8081_config_init(struct phy_device *phydev)
+{
+       kszphy_broadcast_disable(phydev);
+       kszphy_setup_led(phydev, MII_KSZPHY_CTRL_2);
+
+       return 0;
+}
+
 static int ksz9021_load_values_from_of(struct phy_device *phydev,
                                       struct device_node *of_node, u16 reg,
                                       char *field1, char *field2,
@@ -394,8 +447,8 @@ static int ksz9031_config_init(struct phy_device *phydev)
 }
 
 #define KSZ8873MLL_GLOBAL_CONTROL_4    0x06
-#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX     (1 << 6)
-#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED      (1 << 4)
+#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX     BIT(6)
+#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED      BIT(4)
 static int ksz8873mll_read_status(struct phy_device *phydev)
 {
        int regval;
@@ -579,7 +632,7 @@ static struct phy_driver ksphy_driver[] = {
        .phy_id_mask    = 0x00fffff0,
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-       .config_init    = kszphy_config_init,
+       .config_init    = ksz8081_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,