diff options
author | Giuseppe CAVALLARO <peppe.cavallaro@st.com> | 2012-04-04 04:33:27 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-04 18:39:24 -0400 |
commit | cd7201f477b965f6c0220b798813c7000bc603c5 (patch) | |
tree | 0b5ac87d64a90efc1ddfca8620019c13fd0acad8 /drivers | |
parent | 18f05d64ec36e27892cc0f55be707762aae053a1 (diff) | |
download | blackbird-op-linux-cd7201f477b965f6c0220b798813c7000bc603c5.tar.gz blackbird-op-linux-cd7201f477b965f6c0220b798813c7000bc603c5.zip |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 40 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 4 |
4 files changed, 53 insertions, 2 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index b14829f8085d..9e42b5d32cff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -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 diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 7182f159c2c9..ddd07691cef1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -84,6 +84,7 @@ struct stmmac_priv { #ifdef CONFIG_HAVE_CLK struct clk *stmmac_clk; #endif + int clk_csr; }; extern int phyaddr; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ddb47e147f70..90d5c4c75d25 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -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: diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 1a420142f6ac..ade108232048 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/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; 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)) |