rk32: gmac: better support 1000M
author郭毅 <gy@rock-chips.com>
Mon, 21 Jul 2014 07:54:38 +0000 (15:54 +0800)
committer郭毅 <gy@rock-chips.com>
Mon, 21 Jul 2014 08:30:46 +0000 (16:30 +0800)
arch/arm/boot/dts/rk3288-clocks.dtsi
drivers/net/ethernet/rockchip/gmac/Kconfig
drivers/net/ethernet/rockchip/gmac/stmmac.h
drivers/net/ethernet/rockchip/gmac/stmmac_main.c
drivers/net/ethernet/rockchip/gmac/stmmac_platform.c

index 93612c6bdf2bea04d448acde37c30b2234303628..2eaf3f54177d36ed997cbdd9430308ff58ed6bbc 100755 (executable)
@@ -84,7 +84,7 @@
                                compatible = "rockchip,rk-fixed-clock";
                                #clock-cells = <0>;
                                clock-output-names = "gmac_clkin";
-                               clock-frequency = <0>;
+                               clock-frequency = <125000000>;
                        };
 
                        clk_hsadc_ext: clk_hsadc_ext {
index 957a46bdbc1823c5243876fc3c5d3ecc2b8243ce..93f4a86b8dce646f0791cbbd10175968b4ab2291 100755 (executable)
@@ -10,6 +10,13 @@ config RK_GMAC_ETH
          Rockchip 10/100/1000 Ethernet driver.
 
 if RK_GMAC_ETH
+config GMAC_CLK_IN
+       bool "Clock input from PHY"
+       default y
+
+config GMAC_PHY_RMII
+       bool "GMAC interface set to RMII"
+       default n
 
 config GMAC_DEBUG_FS
        bool "Enable monitoring via sysFS "
index 0f965cecce8543e5545b8f3de93c6fc5d58f9c97..d736777358cacc75b7357b6d5e289f8f569a4f13 100755 (executable)
@@ -91,8 +91,10 @@ struct stmmac_priv {
        u32 msg_enable;
        int wolopts;
        int wol_irq;
-       struct clk *stmmac_clk;
        struct clk *clk_mac;
+       struct clk *stmmac_clk;
+       struct clk *clk_mac_pll;
+       struct clk *gmac_clkin;
        struct clk *mac_clk_rx;
        struct clk *mac_clk_tx;
        struct clk *clk_mac_ref;
@@ -119,7 +121,9 @@ struct stmmac_priv {
 };
 
 struct bsp_priv {
-       char pwr_ctl_by[8];
+       bool power_ctrl_by_pmu;
+       char pmu_regulator[32];
+       int pmu_enable_level;
        int power_io;
        int power_io_level;
        int reset_io;
index 775379ba3b5398b96cff470559754ed783ecb9f4..04e71c29ce062e84f814069361eb32b867c9f6bd 100755 (executable)
@@ -148,32 +148,55 @@ static void stmmac_exit_fs(void);
 
 #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
 
-static int gmac_clk_enable(struct stmmac_priv *priv)
-{
+static int gmac_clk_enable(struct stmmac_priv *priv) {
+       int phy_iface = -1;
+
+       if ((priv->plat) && (priv->plat->bsp_priv)) {
+               struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
+               phy_iface = bsp_priv->phy_iface;
+       } else {
+               pr_err("%s:get PHY interface type failed!", __func__);
+       }
+
        if (!priv->clk_enable) {
-               clk_prepare_enable(priv->clk_mac);
-               clk_prepare_enable(priv->mac_clk_rx);
-               clk_prepare_enable(priv->mac_clk_tx);
-               clk_prepare_enable(priv->clk_mac_ref);
-               clk_prepare_enable(priv->clk_mac_refout);
+               if (phy_iface == PHY_INTERFACE_MODE_RMII) {
+                       clk_set_rate(priv->stmmac_clk, 50000000);
+                       clk_prepare_enable(priv->mac_clk_rx);
+                       clk_prepare_enable(priv->clk_mac_ref);
+                       clk_prepare_enable(priv->clk_mac_refout);
+               }
+
                clk_prepare_enable(priv->aclk_mac);
                clk_prepare_enable(priv->pclk_mac);
+               clk_prepare_enable(priv->mac_clk_tx);
+
                priv->clk_enable = true;
        }
        
        return 0;
 }
 
-static int gmac_clk_disable(struct stmmac_priv *priv)
-{
+static int gmac_clk_disable(struct stmmac_priv *priv) {
+       int phy_iface = -1;
+
+       if ((priv->plat) && (priv->plat->bsp_priv)) {
+               struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
+               phy_iface = bsp_priv->phy_iface;
+       } else {
+               pr_err("%s:get PHY interface type failed!", __func__);
+       }
+
        if (priv->clk_enable) {
-               clk_disable_unprepare(priv->clk_mac);
-               clk_disable_unprepare(priv->mac_clk_rx);
-               clk_disable_unprepare(priv->mac_clk_tx);
-               clk_disable_unprepare(priv->clk_mac_ref);
-               clk_disable_unprepare(priv->clk_mac_refout);
+               if (phy_iface == PHY_INTERFACE_MODE_RMII) {
+                       clk_disable_unprepare(priv->mac_clk_rx);
+                       clk_disable_unprepare(priv->clk_mac_ref);
+                       clk_disable_unprepare(priv->clk_mac_refout);
+               }
+
                clk_disable_unprepare(priv->aclk_mac);
                clk_disable_unprepare(priv->pclk_mac);
+               clk_disable_unprepare(priv->mac_clk_tx);
+
                priv->clk_enable = false;
        }
        
@@ -683,6 +706,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
  * This is done by looking at the HW cap. register.
  * Also it registers the ptp driver.
  */
+/*
 static int stmmac_init_ptp(struct stmmac_priv *priv)
 {
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
@@ -706,7 +730,7 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
 
        return stmmac_ptp_register(priv);
 }
-
+*/
 static void stmmac_release_ptp(struct stmmac_priv *priv)
 {
        stmmac_ptp_unregister(priv);
@@ -1700,11 +1724,11 @@ static int stmmac_open(struct net_device *dev)
        priv->xstats.threshold = tc;
 
        stmmac_mmc_setup(priv);
-
+/*
        ret = stmmac_init_ptp(priv);
        if (ret)
                pr_warn("%s: failed PTP initialisation\n", __func__);
-
+*/
 #ifdef CONFIG_GMAC_DEBUG_FS
        ret = stmmac_init_fs(dev);
        if (ret < 0)
@@ -2766,12 +2790,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
 
        priv->mdio_registered = false;
        priv->clk_enable = false;
-       
-       priv->clk_mac = clk_get(priv->device,"clk_mac");
-       if (IS_ERR(priv->clk_mac)) {
-               pr_warn("%s: warning: cannot get clk_mac clock\n", __func__);
-               goto error_clk_get;
-       }
 
        priv->mac_clk_rx = clk_get(priv->device,"mac_clk_rx");
        if (IS_ERR(priv->mac_clk_rx)) {
@@ -2809,12 +2827,31 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
                goto error_clk_get;
        }
 
-       priv->stmmac_clk = clk_get(priv->device, "clk_mac"/*STMMAC_RESOURCE_NAME*/);
+       priv->clk_mac_pll = clk_get(priv->device,"clk_mac_pll");
+       if (IS_ERR(priv->clk_mac_pll)) {
+               pr_warn("%s: warning: cannot get clk_mac_pll clock\n", __func__);
+               goto error_clk_get;
+       }
+
+       priv->gmac_clkin = clk_get(priv->device,"gmac_clkin");
+       if (IS_ERR(priv->gmac_clkin)) {
+               pr_warn("%s: warning: cannot get gmac_clkin clock\n", __func__);
+               goto error_clk_get;
+       }
+
+       priv->stmmac_clk = clk_get(priv->device, "clk_mac");
+
        if (IS_ERR(priv->stmmac_clk)) {
                pr_warn("%s: warning: cannot get CSR clock\n", __func__);
                goto error_clk_get;
        }
 
+#ifdef CONFIG_GMAC_CLK_IN
+       clk_set_parent(priv->stmmac_clk, priv->gmac_clkin);
+#else
+       clk_set_parent(priv->stmmac_clk, priv->clk_mac_pll);
+#endif
+
        /* 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
index c1085196c2f971be354037b50999e53d1e3400ef..471bfe71b70e70a9bee3d9ef8d44570fa380a0bb 100755 (executable)
@@ -33,6 +33,7 @@
 #include "stmmac.h"
 #include <linux/rockchip/iomap.h>
 #include <linux/rockchip/grf.h>
+#include <linux/regulator/consumer.h>
 
 #define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
 #define grf_writel(v, offset)  do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
@@ -42,8 +43,8 @@
 #define GMAC_PHY_INTF_SEL_RMII  ((0x01C0 << 16) | (0x0100))
 #define GMAC_FLOW_CTRL          ((0x0200 << 16) | (0x0200))
 #define GMAC_FLOW_CTRL_CLR      ((0x0200 << 16) | (0x0000))
-#define GMAC_SPEED_10M          ((0x0400 << 16) | (0x0400))
-#define GMAC_SPEED_100M         ((0x0400 << 16) | (0x0000))
+#define GMAC_SPEED_10M          ((0x0400 << 16) | (0x0000))
+#define GMAC_SPEED_100M         ((0x0400 << 16) | (0x0400))
 #define GMAC_RMII_CLK_25M       ((0x0800 << 16) | (0x0800))
 #define GMAC_RMII_CLK_2_5M      ((0x0800 << 16) | (0x0000))
 #define GMAC_CLK_125M           ((0x3000 << 16) | (0x0000))
@@ -69,8 +70,9 @@ struct bsp_priv g_bsp_priv;
 static int phy_power_on(struct plat_stmmacenet_data *plat, int enable)
 {
        struct bsp_priv * bsp_priv;
+       //int ret;
 
-       pr_info("%s: enable = %d \n", __func__, enable);
+       printk("%s: enable = %d \n", __func__, enable);
 
        if ((plat) && (plat->bsp_priv)) {
                bsp_priv = plat->bsp_priv;
@@ -108,7 +110,6 @@ static int phy_power_on(struct plat_stmmacenet_data *plat, int enable)
 }
 
 int stmmc_pltfr_init(struct platform_device *pdev) {
-       //struct pinctrl_state *gmac_state;
        int phy_iface;
        int err;
        struct bsp_priv *bsp_priv;
@@ -134,35 +135,38 @@ int stmmc_pltfr_init(struct platform_device *pdev) {
        if (!gpio_is_valid(bsp_priv->power_io)) {
                pr_err("%s: ERROR: Get power-gpio failed.\n", __func__);
                //return -EINVAL;
-       }
-
-       err = gpio_request(bsp_priv->power_io, "gmac_phy_power");
-       if (err) {
-               pr_err("%s: ERROR: Request gmac phy power pin failed.\n", __func__);
-               //return -EINVAL;
+       } else {
+               err = gpio_request(bsp_priv->power_io, "gmac_phy_power");
+               if (err) {
+                       pr_err("%s: ERROR: Request gmac phy power pin failed.\n", __func__);
+                       //return -EINVAL;
+               }
        }
 
        if (!gpio_is_valid(bsp_priv->reset_io)) {
                pr_err("%s: ERROR: Get reset-gpio failed.\n", __func__);
                //return -EINVAL;
+       } else {
+               err = gpio_request(bsp_priv->reset_io, "gmac_phy_reset");
+               if (err) {
+                       pr_err("%s: ERROR: Request gmac phy reset pin failed.\n", __func__);
+                       //return -EINVAL;
+               }
        }
-
-       err = gpio_request(bsp_priv->reset_io, "gmac_phy_reset");
-       if (err) {
-               pr_err("%s: ERROR: Request gmac phy reset pin failed.\n", __func__);
-               //return -EINVAL;
-       }
-
 //rmii or rgmii
-       if (phy_iface & PHY_INTERFACE_MODE_RGMII) {
+       if (phy_iface == PHY_INTERFACE_MODE_RGMII) {
                pr_info("%s: init for RGMII\n", __func__);
                grf_writel(GMAC_PHY_INTF_SEL_RGMII, RK3288_GRF_SOC_CON1);
                grf_writel(GMAC_RMII_MODE_CLR, RK3288_GRF_SOC_CON1);
                grf_writel(GMAC_RXCLK_DLY_ENABLE, RK3288_GRF_SOC_CON3);
                grf_writel(GMAC_TXCLK_DLY_ENABLE, RK3288_GRF_SOC_CON3);
                grf_writel(GMAC_CLK_RX_DL_CFG(0x10), RK3288_GRF_SOC_CON3);
-               grf_writel(GMAC_CLK_TX_DL_CFG(0x40), RK3288_GRF_SOC_CON3);
-       } else if (phy_iface & PHY_INTERFACE_MODE_RMII) {
+               grf_writel(GMAC_CLK_TX_DL_CFG(0x30), RK3288_GRF_SOC_CON3);
+               grf_writel(0xffffffff,RK3288_GRF_GPIO3D_E);
+               grf_writel(grf_readl(RK3288_GRF_GPIO4B_E) | 0x3<<2<<16 | 0x3<<2, RK3288_GRF_GPIO4B_E);
+               grf_writel(0xffffffff,RK3288_GRF_GPIO4A_E);
+
+       } else if (phy_iface == PHY_INTERFACE_MODE_RMII) {
                pr_info("%s: init for RMII\n", __func__);
                grf_writel(GMAC_PHY_INTF_SEL_RMII, RK3288_GRF_SOC_CON1);
                grf_writel(GMAC_RMII_MODE, RK3288_GRF_SOC_CON1);
@@ -183,7 +187,7 @@ void stmmc_pltfr_fix_mac_speed(void *priv, unsigned int speed){
                interface = bsp_priv->phy_iface;
        }
 
-       if (interface & PHY_INTERFACE_MODE_RGMII) {
+       if (interface == PHY_INTERFACE_MODE_RGMII) {
                pr_info("%s: fix speed for RGMII\n", __func__);
 
                switch (speed) {
@@ -204,15 +208,17 @@ void stmmc_pltfr_fix_mac_speed(void *priv, unsigned int speed){
                        }
                }
 
-       } else if (interface & PHY_INTERFACE_MODE_RMII) {
+       } else if (interface == PHY_INTERFACE_MODE_RMII) {
                pr_info("%s: fix speed for RMII\n", __func__);
                switch (speed) {
                        case 10: {
                                grf_writel(GMAC_RMII_CLK_2_5M, RK3288_GRF_SOC_CON1);
+                               grf_writel(GMAC_SPEED_10M, RK3288_GRF_SOC_CON1);
                                break;
                        }
                        case 100: {
                                grf_writel(GMAC_RMII_CLK_25M, RK3288_GRF_SOC_CON1);
+                               grf_writel(GMAC_SPEED_100M, RK3288_GRF_SOC_CON1);
                                break;
                        }
                        default: {
@@ -232,12 +238,22 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
 {
        struct device_node *np = pdev->dev.of_node;
        enum of_gpio_flags flags;
+       int ret;
+       const char * strings = NULL;
+       int value;
 
        if (!np)
                return -ENODEV;
 
        *mac = of_get_mac_address(np);
        plat->interface = of_get_phy_mode(np);
+       //don't care about the return value of of_get_phy_mode(np)
+#ifdef CONFIG_GMAC_PHY_RMII
+       plat->interface = PHY_INTERFACE_MODE_RMII;
+#else
+       plat->interface = PHY_INTERFACE_MODE_RGMII;
+#endif
+
        plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
                                           sizeof(struct stmmac_mdio_bus_data),
                                           GFP_KERNEL);
@@ -245,6 +261,25 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
        plat->init = stmmc_pltfr_init;
        plat->fix_mac_speed = stmmc_pltfr_fix_mac_speed;
 
+       ret = of_property_read_string(np, "pmu_regulator", &strings);
+       if (ret) {
+               pr_err("%s: Can not read property: pmu_regulator.\n", __func__);
+               g_bsp_priv.power_ctrl_by_pmu = false;
+       } else {
+               pr_info("%s: ethernet phy power controled by pmu(%s).\n", __func__, strings);
+               g_bsp_priv.power_ctrl_by_pmu = true;
+               strcpy(g_bsp_priv.pmu_regulator, strings);
+       }
+       ret = of_property_read_u32(np, "pmu_enable_level", &value);
+       if (ret) {
+               pr_err("%s: Can not read property: pmu_enable_level.\n", __func__);
+               g_bsp_priv.power_ctrl_by_pmu = false;
+       } else {
+               pr_info("%s: ethernet phy power controled by pmu(level = %s).\n", __func__, (value == 1)?"HIGH":"LOW");
+               g_bsp_priv.power_ctrl_by_pmu = true;
+               g_bsp_priv.pmu_enable_level = value;
+       }
+
        g_bsp_priv.reset_io = 
                        of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
        g_bsp_priv.reset_io_level = (flags == GPIO_ACTIVE_HIGH) ? 1 : 0;