ath79: ag71xx: Rework mdio clock settings
authorChuanhong Guo <gch981213@gmail.com>
Tue, 17 Jul 2018 09:09:14 +0000 (17:09 +0800)
committerJohn Crispin <john@phrozen.org>
Mon, 30 Jul 2018 08:43:34 +0000 (10:43 +0200)
Allow specifying desired mdio clock frequency in dts.
Use default frequency around 5MHz for builtin switch and 2MHz for other mdio bus.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
target/linux/ath79/dts/ar9330.dtsi
target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c

index 4649262..a902712 100644 (file)
 
 &mdio1 {
        status = "okay";
+       compatible = "qca,ar9330-mdio";
 
        resets = <&rst 23>;
        reset-names = "mdio";
index baaa33e..0bfc154 100644 (file)
@@ -84,14 +84,62 @@ static int ag71xx_mdio_mii_write(struct mii_bus *bus, int addr, int reg, u16 val
        return 0;
 }
 
-static int ar934x_mdio_clock_div(unsigned int rate)
+static const u32 ar71xx_mdio_div_table[] = {
+       4, 4, 6, 8, 10, 14, 20, 28,
+};
+
+static const u32 ar7240_mdio_div_table[] = {
+       2, 2, 4, 6, 8, 12, 18, 26, 32, 40, 48, 56, 62, 70, 78, 96,
+};
+
+static const u32 ar933x_mdio_div_table[] = {
+       4, 4, 6, 8, 10, 14, 20, 28, 34, 42, 50, 58, 66, 74, 82, 98,
+};
+
+static int ag71xx_mdio_get_divider(struct device_node *np, u32 *div)
 {
-       if (rate == 100 * 1000 * 1000)
-               return 6; /* 100 MHz clock divided by 20 => 5 MHz */
-       else if (rate == 25 * 1000 * 1000)
-               return 0; /* 25 MHz clock divided by 4 => 6.25 MHz */
-       else
-               return 3; /* 40 MHz clock divided by 8 => 5 MHz */
+       struct clk *ref_clk = of_clk_get(np, 0);
+       unsigned long ref_clock;
+       u32 mdio_clock;
+       const u32 *table;
+       int ndivs, i;
+
+       if (IS_ERR(ref_clk))
+               return -EINVAL;
+
+       ref_clock = clk_get_rate(ref_clk);
+       clk_put(ref_clk);
+
+       if(of_property_read_u32(np, "qca,mdio-max-frequency", &mdio_clock)) {
+               if (of_property_read_bool(np, "builtin-switch"))
+                       mdio_clock = 5000000;
+               else
+                       mdio_clock = 2000000;
+       }
+
+       if (of_device_is_compatible(np, "qca,ar9330-mdio") ||
+               of_device_is_compatible(np, "qca,ar9340-mdio")) {
+               table = ar933x_mdio_div_table;
+               ndivs = ARRAY_SIZE(ar933x_mdio_div_table);
+       } else if (of_device_is_compatible(np, "qca,ar7240-mdio")) {
+               table = ar7240_mdio_div_table;
+               ndivs = ARRAY_SIZE(ar7240_mdio_div_table);
+       } else {
+               table = ar71xx_mdio_div_table;
+               ndivs = ARRAY_SIZE(ar71xx_mdio_div_table);
+       }
+
+       for (i = 0; i < ndivs; i++) {
+               unsigned long t;
+
+               t = ref_clock / table[i];
+               if (t <= mdio_clock) {
+                       *div = i;
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
 }
 
 static int ag71xx_mdio_reset(struct mii_bus *bus)
@@ -103,26 +151,13 @@ static int ag71xx_mdio_reset(struct mii_bus *bus)
 
        builtin_switch = of_property_read_bool(np, "builtin-switch");
 
-       if (of_device_is_compatible(np, "qca,ar7240-mdio"))
-               t = MII_CFG_CLK_DIV_6;
-       else if (of_device_is_compatible(np, "qca,ar9340-mdio"))
-               t = MII_CFG_CLK_DIV_58;
-       else if (builtin_switch)
-               t = MII_CFG_CLK_DIV_10;
-       else
-               t = MII_CFG_CLK_DIV_28;
-
-       if (builtin_switch && of_device_is_compatible(np, "qca,ar9340-mdio")) {
-               struct clk *ref_clk = of_clk_get(np, 0);
-               int clock_rate;
-
-               if (WARN_ON_ONCE(!ref_clk))
-                       clock_rate = 40 * 1000 * 1000;
+       if (ag71xx_mdio_get_divider(np, &t)) {
+               if (of_device_is_compatible(np, "qca,ar9340-mdio"))
+                       t = MII_CFG_CLK_DIV_58;
+               else if (builtin_switch)
+                       t = MII_CFG_CLK_DIV_10;
                else
-                       clock_rate = clk_get_rate(ref_clk);
-
-               t = ar934x_mdio_clock_div(clock_rate);
-               clk_put(ref_clk);
+                       t = MII_CFG_CLK_DIV_28;
        }
 
        regmap_write(am->mii_regmap, AG71XX_REG_MII_CFG, t | MII_CFG_RESET);
@@ -200,6 +235,7 @@ static int ag71xx_mdio_remove(struct platform_device *pdev)
 
 static const struct of_device_id ag71xx_mdio_match[] = {
        { .compatible = "qca,ar7240-mdio" },
+       { .compatible = "qca,ar9330-mdio" },
        { .compatible = "qca,ar9340-mdio" },
        { .compatible = "qca,ath79-mdio" },
        {}