net/phy: micrel: Add clock support for KSZ8021/KSZ8031
authorSascha Hauer <s.hauer@pengutronix.de>
Fri, 10 Oct 2014 07:48:05 +0000 (09:48 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 10 Oct 2014 19:35:13 +0000 (15:35 -0400)
The KSZ8021 and KSZ8031 support RMII reference input clocks of 25MHz
and 50MHz. Both PHYs differ in the default frequency they expect
after reset. If this differs from the actual input clock, then
register 0x1f bit 7 must be changed.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/devicetree/bindings/net/micrel.txt
drivers/net/phy/micrel.c
include/linux/micrel_phy.h

index 98a3e61f9ee825c3d37e7a0d1a848151b92dc468..e1d99b95c4ec984e2adbf80b808a4bb0f0f90f05 100644 (file)
@@ -16,3 +16,9 @@ Optional properties:
              KSZ8051: register 0x1f, bits 5..4
 
               See the respective PHY datasheet for the mode values.
+
+ - clocks, clock-names: contains clocks according to the common clock bindings.
+
+              supported clocks:
+             - KSZ8021, KSZ8031: "rmii-ref": The RMII refence input clock. Used
+               to determine the XI input clock.
index 011dbda2b2f1571e0e8241eb38ce3fc96f81a986..492435fce1d48d420872fef643141b1f0ddd848a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/phy.h>
 #include <linux/micrel_phy.h>
 #include <linux/of.h>
+#include <linux/clk.h>
 
 /* Operation Mode Strap Override */
 #define MII_KSZPHY_OMSO                                0x16
@@ -72,9 +73,12 @@ static int ksz_config_flags(struct phy_device *phydev)
 {
        int regval;
 
-       if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
+       if (phydev->dev_flags & (MICREL_PHY_50MHZ_CLK | MICREL_PHY_25MHZ_CLK)) {
                regval = phy_read(phydev, MII_KSZPHY_CTRL);
-               regval |= KSZ8051_RMII_50MHZ_CLK;
+               if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK)
+                       regval |= KSZ8051_RMII_50MHZ_CLK;
+               else
+                       regval &= ~KSZ8051_RMII_50MHZ_CLK;
                return phy_write(phydev, MII_KSZPHY_CTRL, regval);
        }
        return 0;
@@ -440,6 +444,27 @@ ksz9021_wr_mmd_phyreg(struct phy_device *phydev, int ptrad, int devnum,
 {
 }
 
+static int ksz8021_probe(struct phy_device *phydev)
+{
+       struct clk *clk;
+
+       clk = devm_clk_get(&phydev->dev, "rmii-ref");
+       if (!IS_ERR(clk)) {
+               unsigned long rate = clk_get_rate(clk);
+
+               if (rate > 24500000 && rate < 25500000) {
+                       phydev->dev_flags |= MICREL_PHY_25MHZ_CLK;
+               } else if (rate > 49500000 && rate < 50500000) {
+                       phydev->dev_flags |= MICREL_PHY_50MHZ_CLK;
+               } else {
+                       dev_err(&phydev->dev, "Clock rate out of range: %ld\n", rate);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 static struct phy_driver ksphy_driver[] = {
 {
        .phy_id         = PHY_ID_KS8737,
@@ -462,6 +487,7 @@ static struct phy_driver ksphy_driver[] = {
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .probe          = ksz8021_probe,
        .config_init    = ksz8021_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
@@ -477,6 +503,7 @@ static struct phy_driver ksphy_driver[] = {
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
                           SUPPORTED_Asym_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .probe          = ksz8021_probe,
        .config_init    = ksz8021_config_init,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
index 2e5b194b9b1900b9d5304cbdb52f14aac576b85e..53d33dee70e19a657571d97e773e35d63afa0153 100644 (file)
@@ -37,6 +37,7 @@
 
 /* struct phy_device dev_flags definitions */
 #define MICREL_PHY_50MHZ_CLK   0x00000001
+#define MICREL_PHY_25MHZ_CLK   0x00000002
 
 #define MICREL_KSZ9021_EXTREG_CTRL     0xB
 #define MICREL_KSZ9021_EXTREG_DATA_WRITE       0xC