stmmac: MDC clock dynamically based on the csr clock input
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>
Wed, 4 Apr 2012 04:33:27 +0000 (04:33 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Apr 2012 22:39:24 +0000 (18:39 -0400)
If a specific clk_csr value is passed from the platform
this means that the CSR Clock Range selection cannot be
changed at run-time and it is fixed (as reported in the driver
documentation). Viceversa the driver will try to set the MDC
clock dynamically according to the actual clock input.

Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Reviewed-by: Francesco Virlinzi <francesco.virlinzi@st.com>
Reviewed-by: David Laight <david.laight@aculab.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/stmmac.txt
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c

index eacb640..ab1e8d7 100644 (file)
@@ -137,7 +137,7 @@ Where:
  o pbl: the Programmable Burst Length is maximum number of beats to
        be transferred in one DMA transaction.
        GMAC also enables the 4xPBL by default.
- o clk_csr: CSR Clock range selection.
+ o clk_csr: fixed CSR Clock range selection.
  o has_gmac: uses the GMAC core.
  o enh_desc: if sets the MAC will use the enhanced descriptor structure.
  o tx_coe: core is able to perform the tx csum in HW.
index b14829f..9e42b5d 100644 (file)
@@ -97,6 +97,16 @@ struct stmmac_extra_stats {
        unsigned long normal_irq_n;
 };
 
+/* CSR Frequency Access Defines*/
+#define CSR_F_35M      35000000
+#define CSR_F_60M      60000000
+#define CSR_F_100M     100000000
+#define CSR_F_150M     150000000
+#define CSR_F_250M     250000000
+#define CSR_F_300M     300000000
+
+#define        MAC_CSR_H_FRQ_MASK      0x20
+
 #define HASH_TABLE_SIZE 64
 #define PAUSE_TIME 0x200
 
index 7182f15..ddd0769 100644 (file)
@@ -84,6 +84,7 @@ struct stmmac_priv {
 #ifdef CONFIG_HAVE_CLK
        struct clk *stmmac_clk;
 #endif
+       int clk_csr;
 };
 
 extern int phyaddr;
index ddb47e1..90d5c4c 100644 (file)
@@ -163,6 +163,35 @@ static void stmmac_verify_args(void)
                pause = PAUSE_TIME;
 }
 
+static void stmmac_clk_csr_set(struct stmmac_priv *priv)
+{
+#ifdef CONFIG_HAVE_CLK
+       u32 clk_rate;
+
+       clk_rate = clk_get_rate(priv->stmmac_clk);
+
+       /* Platform provided default clk_csr would be assumed valid
+        * for all other cases except for the below mentioned ones. */
+       if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
+               if (clk_rate < CSR_F_35M)
+                       priv->clk_csr = STMMAC_CSR_20_35M;
+               else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
+                       priv->clk_csr = STMMAC_CSR_35_60M;
+               else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
+                       priv->clk_csr = STMMAC_CSR_60_100M;
+               else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
+                       priv->clk_csr = STMMAC_CSR_100_150M;
+               else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
+                       priv->clk_csr = STMMAC_CSR_150_250M;
+               else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
+                       priv->clk_csr = STMMAC_CSR_250_300M;
+       } /* For values higher than the IEEE 802.3 specified frequency
+          * we can not estimate the proper divider as it is not known
+          * the frequency of clk_csr_i. So we do not change the default
+          * divider. */
+#endif
+}
+
 #if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG)
 static void print_pkt(unsigned char *buf, int len)
 {
@@ -1890,6 +1919,17 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
        if (stmmac_clk_get(priv))
                goto error;
 
+       /* If a specific clk_csr value is passed from the platform
+        * this means that the CSR Clock Range selection cannot be
+        * changed at run-time and it is fixed. Viceversa the driver'll try to
+        * set the MDC clock dynamically according to the csr actual
+        * clock input.
+        */
+       if (!priv->plat->clk_csr)
+               stmmac_clk_csr_set(priv);
+       else
+               priv->clk_csr = priv->plat->clk_csr;
+
        return priv;
 
 error:
index 1a42014..ade1082 100644 (file)
@@ -70,7 +70,7 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
        int data;
        u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
                        ((phyreg << 6) & (0x000007C0)));
-       regValue |= MII_BUSY | ((priv->plat->clk_csr & 0xF) << 2);
+       regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
 
        if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
                return -EBUSY;
@@ -106,7 +106,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
            (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
            | MII_WRITE;
 
-       value |= MII_BUSY | ((priv->plat->clk_csr & 0xF) << 2);
+       value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
 
        /* Wait until any existing MII operation is complete */
        if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))