Browse Source

stmmac: MDC clock dynamically based on the csr clock input

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>
Giuseppe CAVALLARO 13 years ago
parent
commit
cd7201f477

+ 1 - 1
Documentation/networking/stmmac.txt

@@ -137,7 +137,7 @@ Where:
  o pbl: the Programmable Burst Length is maximum number of beats to
  o pbl: the Programmable Burst Length is maximum number of beats to
        be transferred in one DMA transaction.
        be transferred in one DMA transaction.
        GMAC also enables the 4xPBL by default.
        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 has_gmac: uses the GMAC core.
  o enh_desc: if sets the MAC will use the enhanced descriptor structure.
  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.
  o tx_coe: core is able to perform the tx csum in HW.

+ 10 - 0
drivers/net/ethernet/stmicro/stmmac/common.h

@@ -97,6 +97,16 @@ struct stmmac_extra_stats {
 	unsigned long normal_irq_n;
 	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 HASH_TABLE_SIZE 64
 #define PAUSE_TIME 0x200
 #define PAUSE_TIME 0x200
 
 

+ 1 - 0
drivers/net/ethernet/stmicro/stmmac/stmmac.h

@@ -84,6 +84,7 @@ struct stmmac_priv {
 #ifdef CONFIG_HAVE_CLK
 #ifdef CONFIG_HAVE_CLK
 	struct clk *stmmac_clk;
 	struct clk *stmmac_clk;
 #endif
 #endif
+	int clk_csr;
 };
 };
 
 
 extern int phyaddr;
 extern int phyaddr;

+ 40 - 0
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

@@ -163,6 +163,35 @@ static void stmmac_verify_args(void)
 		pause = PAUSE_TIME;
 		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)
 #if defined(STMMAC_XMIT_DEBUG) || defined(STMMAC_RX_DEBUG)
 static void print_pkt(unsigned char *buf, int len)
 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))
 	if (stmmac_clk_get(priv))
 		goto error;
 		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;
 	return priv;
 
 
 error:
 error:

+ 2 - 2
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c

@@ -70,7 +70,7 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
 	int data;
 	int data;
 	u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
 	u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
 			((phyreg << 6) & (0x000007C0)));
 			((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))
 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
 		return -EBUSY;
 		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)))
 	    (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
 	    | MII_WRITE;
 	    | 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 */
 	/* Wait until any existing MII operation is complete */
 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))