ethernet: support GMAC driver for RK3128
authorroger <cz@rock-chips.com>
Fri, 8 Aug 2014 12:57:19 +0000 (20:57 +0800)
committerroger <cz@rock-chips.com>
Fri, 8 Aug 2014 12:57:19 +0000 (20:57 +0800)
arch/arm/boot/dts/rk3128-box.dts
arch/arm/boot/dts/rk312x-clocks.dtsi
arch/arm/boot/dts/rk312x-pinctrl.dtsi
arch/arm/boot/dts/rk312x.dtsi
drivers/net/ethernet/rockchip/gmac/stmmac.h
drivers/net/ethernet/rockchip/gmac/stmmac_main.c
drivers/net/ethernet/rockchip/gmac/stmmac_platform.c

index 5b997bbed008f39d570d44080b0212d2221e8f5e..65d03c406780109f77fefd0f37faf43cdd54bfbb 100755 (executable)
        status = "disabled";
 };
 
-
+&gmac {
+       //pmu_regulator = "act_ldo5";
+       //pmu_enable_level = <1>; //1->HIGH, 0->LOW
+       //power-gpio = <&gpio0 GPIO_A6 GPIO_ACTIVE_HIGH>;
+       reset-gpio = <&gpio2 GPIO_D0 GPIO_ACTIVE_LOW>;
+};
index e7b95493a7329959ae9656e19a717e454879548a..97f15d4f0ccfbb026a46079ec10d4d06c07b24e6 100755 (executable)
                                #clock-cells = <0>;
                        };
 
-                       gmac_clkin: rmii_clkin {
+                       gmac_clkin: gmac_clkin {
                                compatible = "rockchip,rk-fixed-clock";
                                clock-output-names = "gmac_clkin";
-                               clock-frequency = <0>;
+                               clock-frequency = <125000000>;
                                #clock-cells = <0>;
                        };
 
index 8dec9bc2cc67961267585cc0ca122e7cb56d083b..61e0628b6661458d2ed322acc156e8778c051b48 100755 (executable)
                                rockchip,pins = <GMAC_COL>;
                                rockchip,pull = <VALUE_PULL_DEFAULT>;
                        };
-                       
+
+                       gmac_col_gpio:gmac-col-gpio {
+                               rockchip,pins = <GPIO2_D0>;
+                               rockchip,pull = <VALUE_PULL_DEFAULT>;
+                       };
+               
                        gmac_mdc:gmac-mdc {
                                rockchip,pins = <GMAC_MDC>;
                                rockchip,pull = <VALUE_PULL_DEFAULT>;
index ecdc3dc45908a0615da1201df0b9a893e2f27604..99501b2e488c9ab8e1c34869d33b96a916f736db 100755 (executable)
                status = "disabled";
        };
 
+       gmac: eth@2008c000 {
+               compatible = "rockchip,gmac";
+               reg = <0x2008c000 0x4000>;
+               interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;  /*irq=88*/
+               interrupt-names = "macirq";
+               clocks = <&clk_mac_ref>, <&clk_gates2 6>,
+                       <&clk_gates2 7>, <&clk_gates2 4>,
+                       <&clk_gates2 5>,
+                       <&clk_gates10 11>;
+               clock-names = "clk_mac", "mac_clk_rx",
+                       "mac_clk_tx", "clk_mac_ref",
+                       "clk_mac_refout",
+                       "pclk_mac";
+               //phy-mode = "rmii";
+               phy-mode = "rgmii";
+               pinctrl-names = "default";
+               pinctrl-0 = <&gmac_rxdv &gmac_txclk &gmac_crs &gmac_rxclk &gmac_mdio &gmac_txen &gmac_clk &gmac_rxer &gmac_rxd1 &gmac_rxd0 &gmac_txd1 &gmac_txd0 &gmac_rxd3 &gmac_rxd2 &gmac_txd2 &gmac_txd3 &gmac_col_gpio &gmac_mdc>;
+       };
+
        fiq-debugger {
                compatible = "rockchip,fiq-debugger";
                rockchip,serial-id = <2>;
                        <&aclk_vio0_pre 300000000>, <&hclk_vio_pre 150000000>,
                        <&aclk_vio1_pre 300000000>, <&clk_vepu 300000000>,
                        <&clk_vdpu 300000000>, <&clk_hevc_core 200000000>,
-                       <&clk_mac_ref 50000000>;
+                       <&clk_mac_ref 125000000>;
        /*      rockchip,clocks-uboot-has-init =
                        <&aclk_vio1>;*/
        };
index d736777358cacc75b7357b6d5e289f8f569a4f13..66b4410bd4f1c208d037ed9fc8decdab38596582 100755 (executable)
@@ -91,17 +91,7 @@ struct stmmac_priv {
        u32 msg_enable;
        int wolopts;
        int wol_irq;
-       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;
-       struct clk *clk_mac_refout;
-       struct clk *aclk_mac;
-       struct clk *pclk_mac;
-       bool clk_enable;
        int clk_csr;
        struct timer_list eee_ctrl_timer;
        int lpi_irq;
@@ -129,7 +119,20 @@ struct bsp_priv {
        int reset_io;
        int reset_io_level;
        int phy_iface;
-       int (*phy_power_on)(struct plat_stmmacenet_data *plat, int enable);
+
+       struct clk *clk_mac;
+       struct clk *clk_mac_pll;
+       struct clk *gmac_clkin;
+       struct clk *mac_clk_rx;
+       struct clk *mac_clk_tx;
+       struct clk *clk_mac_ref;
+       struct clk *clk_mac_refout;
+       struct clk *aclk_mac;
+       struct clk *pclk_mac;
+       bool clk_enable;
+
+       int (*phy_power_on)(bool enable);
+       int (*gmac_clk_enable)(bool enable);
 };
 
 extern int phyaddr;
index 04e71c29ce062e84f814069361eb32b867c9f6bd..98a14b3c924e7abe7ffa69d4c0d4a14041052207 100755 (executable)
@@ -148,61 +148,6 @@ 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) {
-       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) {
-               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) {
-       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) {
-               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;
-       }
-       
-       return 0;
-}
-
 /**
  * stmmac_verify_args - verify the driver parameters.
  * Description: it verifies if some wrong parameter is passed to the driver.
@@ -858,6 +803,79 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
        }
 }
 
+static int gPhyReg;
+
+static ssize_t show_phy_reg(struct device *dev,
+                               struct device_attribute *attr, char *buf) {
+       int ret = snprintf(buf, PAGE_SIZE, "current phy reg = 0x%x\n", gPhyReg);
+       return ret;
+}
+
+static ssize_t set_phy_reg(struct device *dev,struct device_attribute *attr,
+                               const char *buf, size_t count) {
+       int ovl;
+       int r = kstrtoint(buf, 0, &ovl);
+       if (r) printk("kstrtoint failed\n");
+       gPhyReg = ovl;
+       printk("%s----ovl=0x%x\n", __FUNCTION__, ovl);
+       return count;
+}
+
+static ssize_t show_phy_regValue(struct device *dev,
+                                       struct device_attribute *attr, char *buf) {
+       struct phy_device *phy_dev = dev_get_drvdata(dev);
+       int ret = 0;
+       int val;
+#if 0
+       val = phy_read(phy_dev, gPhyReg);
+       ret = snprintf(buf, PAGE_SIZE, "phy reg 0x%x = 0x%x\n", gPhyReg, val);
+#else
+       int i=0;
+
+       for (i=0; i<32; i++) {
+               printk("%d: 0x%x\n", i, phy_read(phy_dev, i));
+       }
+
+       val = phy_read(phy_dev, gPhyReg);
+       ret = snprintf(buf, PAGE_SIZE, "phy reg 0x%x = 0x%x\n", gPhyReg, val);
+#endif
+       return ret;
+}
+
+static ssize_t set_phy_regValue(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count) {
+       int ovl;
+       int ret;
+
+       struct phy_device *phy_dev = dev_get_drvdata(dev);
+       ret = kstrtoint(buf, 0, &ovl);
+       printk("%s----reg 0x%x: ovl=0x%x\n", __FUNCTION__, gPhyReg, ovl);
+       phy_write(phy_dev, gPhyReg, ovl);
+       return count;
+}
+
+static struct device_attribute phy_reg_attrs[] = {
+       __ATTR(phy_reg, S_IRUGO | S_IWUSR, show_phy_reg, set_phy_reg),
+       __ATTR(phy_regValue, S_IRUGO | S_IWUSR, show_phy_regValue, set_phy_regValue)
+};
+
+int gmac_create_sysfs(struct phy_device * phy_dev) {
+       int r;
+       int t;
+
+       dev_set_drvdata(&phy_dev->dev, phy_dev);
+       for (t = 0; t < ARRAY_SIZE(phy_reg_attrs); t++) {
+               r = device_create_file(&phy_dev->dev,&phy_reg_attrs[t]);
+               if (r) {
+                       dev_err(&phy_dev->dev, "failed to create sysfs file\n");
+                       return r;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * stmmac_init_phy - PHY initialization
  * @dev: net device structure
@@ -917,6 +935,8 @@ static int stmmac_init_phy(struct net_device *dev)
 
        priv->phydev = phydev;
 
+       gmac_create_sysfs(phydev);
+
        return 0;
 }
 
@@ -1625,32 +1645,33 @@ static int stmmac_open(struct net_device *dev)
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret;
 
-       clk_prepare_enable(priv->stmmac_clk);
-       gmac_clk_enable(priv);
-
        if ((priv->plat) && (priv->plat->bsp_priv)) {
                struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
-               if ((bsp_priv) && (bsp_priv->phy_power_on)) {
-                       bsp_priv->phy_power_on(priv->plat, 1);
+               if (bsp_priv) { 
+                       if (bsp_priv->phy_power_on) {
+                               bsp_priv->phy_power_on(true);
+                       }
+                       if (bsp_priv->gmac_clk_enable) {
+                               bsp_priv->gmac_clk_enable(true);
+                       }
                }
        }
 
        stmmac_check_ether_addr(priv);
 
-       if (priv->pcs != STMMAC_PCS_SGMII && priv->pcs != STMMAC_PCS_TBI &&
-           priv->pcs != STMMAC_PCS_RTBI && !priv->mdio_registered) {
-               /* MDIO bus Registration */
-               ret = stmmac_mdio_register(priv->dev);
-               if (ret < 0) {
-                       pr_debug("%s: MDIO bus (id: %d) registration failed",
-                                __func__, priv->plat->bus_id);
-                       goto open_error;
-               }
-               priv->mdio_registered = true;
-       }       
 
        if (priv->pcs != STMMAC_PCS_SGMII && priv->pcs != STMMAC_PCS_TBI &&
            priv->pcs != STMMAC_PCS_RTBI) {
+               if(!priv->mdio_registered) {
+                       /* MDIO bus Registration */
+                       ret = stmmac_mdio_register(priv->dev);
+                       if (ret < 0) {
+                               pr_debug("%s: MDIO bus (id: %d) registration failed",
+                                       __func__, priv->plat->bus_id);
+                               goto open_error;
+                       }
+                       priv->mdio_registered = true;
+               }
                ret = stmmac_init_phy(dev);
                if (ret) {
                        pr_err("%s: Cannot attach to PHY (error: %d)\n",
@@ -1778,8 +1799,12 @@ open_error:
        if (priv->phydev)
                phy_disconnect(priv->phydev);
 
-       clk_disable_unprepare(priv->stmmac_clk);
-       gmac_clk_disable(priv);
+       if ((priv->plat) && (priv->plat->bsp_priv)) {
+               struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
+               if ((bsp_priv) && (bsp_priv->gmac_clk_enable)) {
+                       bsp_priv->gmac_clk_enable(false);
+               }
+       }
 
        return ret;
 }
@@ -1832,15 +1857,18 @@ static int stmmac_release(struct net_device *dev)
 #ifdef CONFIG_GMAC_DEBUG_FS
        stmmac_exit_fs();
 #endif
-       clk_disable_unprepare(priv->stmmac_clk);
-       gmac_clk_disable(priv);
 
        stmmac_release_ptp(priv);
 
        if ((priv->plat) && (priv->plat->bsp_priv)) {
                struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
-               if ((bsp_priv) && (bsp_priv->phy_power_on)) {
-                       bsp_priv->phy_power_on(priv->plat, 0);
+               if (bsp_priv) { 
+                       if (bsp_priv->phy_power_on) {
+                               bsp_priv->phy_power_on(false);
+                       }
+                       if (bsp_priv->gmac_clk_enable) {
+                               bsp_priv->gmac_clk_enable(false);
+                       }
                }
        }
 
@@ -2789,69 +2817,13 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
        }
 
        priv->mdio_registered = false;
-       priv->clk_enable = false;
-
-       priv->mac_clk_rx = clk_get(priv->device,"mac_clk_rx");
-       if (IS_ERR(priv->mac_clk_rx)) {
-               pr_warn("%s: warning: cannot get mac_clk_rx clock\n", __func__);
-               goto error_clk_get;
-       }
-
-       priv->mac_clk_tx = clk_get(priv->device,"mac_clk_tx");
-       if (IS_ERR(priv->mac_clk_tx)) {
-               pr_warn("%s: warning: cannot get mac_clk_tx clock\n", __func__);
-               goto error_clk_get;
-       }
-
-       priv->clk_mac_ref = clk_get(priv->device,"clk_mac_ref");
-       if (IS_ERR(priv->clk_mac_ref)) {
-               pr_warn("%s: warning: cannot get clk_mac_ref clock\n", __func__);
-               goto error_clk_get;
-       }
-
-       priv->clk_mac_refout = clk_get(priv->device,"clk_mac_refout");
-       if (IS_ERR(priv->clk_mac_refout)) {
-               pr_warn("%s: warning: cannot get clk_mac_refout clock\n", __func__);
-               goto error_clk_get;
-       }
-
-       priv->aclk_mac = clk_get(priv->device,"aclk_mac");
-       if (IS_ERR(priv->aclk_mac)) {
-               pr_warn("%s: warning: cannot get aclk_mac clock\n", __func__);
-               goto error_clk_get;
-       }
-
-       priv->pclk_mac = clk_get(priv->device,"pclk_mac");
-       if (IS_ERR(priv->pclk_mac)) {
-               pr_warn("%s: warning: cannot get pclk_mac clock\n", __func__);
-               goto error_clk_get;
-       }
-
-       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");
 
+       priv->stmmac_clk = ((struct bsp_priv *)(priv->plat->bsp_priv))->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
@@ -2864,18 +2836,23 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
                priv->clk_csr = priv->plat->clk_csr;
 
        stmmac_check_pcs_mode(priv);
-
+#if 0
+       if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
+           priv->pcs != STMMAC_PCS_RTBI) {
+               /* MDIO bus Registration */
+               ret = stmmac_mdio_register(ndev);
+               if (ret < 0) {
+                       pr_debug("%s: MDIO bus (id: %d) registration failed",
+                                __func__, priv->plat->bus_id);
+                       goto error_mdio_register;
+               }
+       }
+#endif
        return priv;
-
-/*error_mdio_register:
+#if 0
+error_mdio_register:
        clk_put(priv->stmmac_clk);
-       clk_put(priv->clk_mac);
-       clk_put(priv->mac_clk_rx);
-       clk_put(priv->mac_clk_tx);
-       clk_put(priv->clk_mac_ref);
-       clk_put(priv->clk_mac_refout);
-       clk_put(priv->aclk_mac);
-       clk_put(priv->pclk_mac);*/
+#endif
 error_clk_get:
        unregister_netdev(ndev);
 error_netdev_register:
@@ -2943,8 +2920,13 @@ int stmmac_suspend(struct net_device *ndev)
        else {
                stmmac_set_mac(priv->ioaddr, false);
                /* Disable clock in case of PWM is off */
-               clk_disable_unprepare(priv->stmmac_clk);
-               gmac_clk_disable(priv);
+       if ((priv->plat) && (priv->plat->bsp_priv)) {
+               struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
+               if ((bsp_priv) && (bsp_priv->gmac_clk_enable)) {
+                       bsp_priv->gmac_clk_enable(false);
+               }
+       }
+
        }
        spin_unlock_irqrestore(&priv->lock, flags);
        return 0;
@@ -2970,8 +2952,12 @@ int stmmac_resume(struct net_device *ndev)
                priv->hw->mac->pmt(priv->ioaddr, 0);
        else {
                /* enable the clk prevously disabled */
-               clk_prepare_enable(priv->stmmac_clk);
-               gmac_clk_enable(priv);
+               if ((priv->plat) && (priv->plat->bsp_priv)) {
+                       struct bsp_priv * bsp_priv = priv->plat->bsp_priv;
+                       if ((bsp_priv) && (bsp_priv->gmac_clk_enable)) {
+                               bsp_priv->gmac_clk_enable(true);
+                       }
+               }
        }
 
        netif_device_attach(ndev);
index 471bfe71b70e70a9bee3d9ef8d44570fa380a0bb..23171af80beb351a82e3148811c210e93da32094 100755 (executable)
@@ -38,7 +38,8 @@
 #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)
 
-// RK3288_GRF_SOC_CON1
+//RK3288_GRF_SOC_CON1
+//RK3128_GRF_MAC_CON1
 #define GMAC_PHY_INTF_SEL_RGMII ((0x01C0 << 16) | (0x0040))
 #define GMAC_PHY_INTF_SEL_RMII  ((0x01C0 << 16) | (0x0100))
 #define GMAC_FLOW_CTRL          ((0x0200 << 16) | (0x0200))
 #define GMAC_RMII_MODE          ((0x4000 << 16) | (0x4000))
 #define GMAC_RMII_MODE_CLR      ((0x4000 << 16) | (0x0000))
 
-// RK3288_GRF_SOC_CON3
+//RK3288_GRF_SOC_CON3
+//RK3128_GRF_MAC_CON0
 #define GMAC_TXCLK_DLY_ENABLE   ((0x4000 << 16) | (0x4000))
 #define GMAC_TXCLK_DLY_DISABLE  ((0x4000 << 16) | (0x0000))
 #define GMAC_RXCLK_DLY_ENABLE   ((0x8000 << 16) | (0x8000))
 #define GMAC_RXCLK_DLY_DISABLE  ((0x8000 << 16) | (0x0000))
-#if 0
-#define GMAC_CLK_RX_DL_CFG     ((0x3F80 << 16) | (0x0800))
-#define GMAC_CLK_TX_DL_CFG     ((0x007F << 16) | (0x0040))
-#else
 #define GMAC_CLK_RX_DL_CFG(val) ((0x3F80 << 16) | (val<<7))        // 7bit
 #define GMAC_CLK_TX_DL_CFG(val) ((0x007F << 16) | (val))           // 7bit
+
+
+#if 0 //3288
+#define SET_RGMII      {       \
+                               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(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);     \
+                       }
+
+#define SET_RMII       {       \
+                               grf_writel(GMAC_PHY_INTF_SEL_RMII, RK3288_GRF_SOC_CON1);        \
+                               grf_writel(GMAC_RMII_MODE, RK3288_GRF_SOC_CON1);        \
+                       }
+
+#define SET_RGMII_10M  {       \
+                               grf_writel(GMAC_CLK_2_5M, RK3288_GRF_SOC_CON1); \
+                       }
+
+#define SET_RGMII_100M {       \
+                               grf_writel(GMAC_CLK_25M, RK3288_GRF_SOC_CON1);  \
+                       }
+
+#define SET_RGMII_1000M        {       \
+                               grf_writel(GMAC_CLK_125M, RK3288_GRF_SOC_CON1); \
+                       }
+
+#define SET_RMII_10M   {       \
+                               grf_writel(GMAC_RMII_CLK_2_5M, RK3288_GRF_SOC_CON1);    \
+                               grf_writel(GMAC_SPEED_10M, RK3288_GRF_SOC_CON1);        \
+                       }
+
+#define SET_RMII_100M  {       \
+                               grf_writel(GMAC_RMII_CLK_25M, RK3288_GRF_SOC_CON1);     \
+                               grf_writel(GMAC_SPEED_100M, RK3288_GRF_SOC_CON1);       \
+                       }
+#else //3128
+#define SET_RGMII      {       \
+                               grf_writel(GMAC_PHY_INTF_SEL_RGMII, RK312X_GRF_MAC_CON1);       \
+                               grf_writel(GMAC_RMII_MODE_CLR, RK312X_GRF_MAC_CON1);            \
+                               grf_writel(GMAC_RXCLK_DLY_ENABLE, RK312X_GRF_MAC_CON0);         \
+                               grf_writel(GMAC_TXCLK_DLY_ENABLE, RK312X_GRF_MAC_CON0);         \
+                               grf_writel(GMAC_CLK_RX_DL_CFG(0x10), RK312X_GRF_MAC_CON0);      \
+                               grf_writel(GMAC_CLK_TX_DL_CFG(0x30), RK312X_GRF_MAC_CON0);      \
+                       }
+
+#define SET_RMII       {       \
+                               grf_writel(GMAC_PHY_INTF_SEL_RMII, RK312X_GRF_MAC_CON1);        \
+                               grf_writel(GMAC_RMII_MODE, RK312X_GRF_MAC_CON1);        \
+                       }
+
+#define SET_RGMII_10M  {       \
+                               grf_writel(GMAC_CLK_2_5M, RK312X_GRF_MAC_CON1); \
+                       }
+
+#define SET_RGMII_100M {       \
+                               grf_writel(GMAC_CLK_25M, RK312X_GRF_MAC_CON1);  \
+                       }
+
+#define SET_RGMII_1000M        {       \
+                               grf_writel(GMAC_CLK_125M, RK312X_GRF_MAC_CON1); \
+                       }
+
+#define SET_RMII_10M   {       \
+                               grf_writel(GMAC_RMII_CLK_2_5M, RK312X_GRF_MAC_CON1);    \
+                               grf_writel(GMAC_SPEED_10M, RK312X_GRF_MAC_CON1);        \
+                       }
+
+#define SET_RMII_100M  {       \
+                               grf_writel(GMAC_RMII_CLK_25M, RK312X_GRF_MAC_CON1);     \
+                               grf_writel(GMAC_SPEED_100M, RK312X_GRF_MAC_CON1);       \
+                       }
+
 #endif
+
 struct bsp_priv g_bsp_priv;
 
-static int phy_power_on(struct plat_stmmacenet_data *plat, int enable)
+int gmac_clk_init(struct device *device)
 {
-       struct bsp_priv * bsp_priv;
-       //int ret;
+       struct bsp_priv * bsp_priv = &g_bsp_priv;
 
-       printk("%s: enable = %d \n", __func__, enable);
+       bsp_priv->clk_enable = false;
+
+       bsp_priv->mac_clk_rx = clk_get(device,"mac_clk_rx");
+       if (IS_ERR(bsp_priv->mac_clk_rx)) {
+               pr_warn("%s: warning: cannot get mac_clk_rx clock\n", __func__);
+       }
+
+       bsp_priv->mac_clk_tx = clk_get(device,"mac_clk_tx");
+       if (IS_ERR(bsp_priv->mac_clk_tx)) {
+               pr_warn("%s: warning: cannot get mac_clk_tx clock\n", __func__);
+       }
+
+       bsp_priv->clk_mac_ref = clk_get(device,"clk_mac_ref");
+       if (IS_ERR(bsp_priv->clk_mac_ref)) {
+               pr_warn("%s: warning: cannot get clk_mac_ref clock\n", __func__);
+       }
+
+       bsp_priv->clk_mac_refout = clk_get(device,"clk_mac_refout");
+       if (IS_ERR(bsp_priv->clk_mac_refout)) {
+               pr_warn("%s: warning: cannot get clk_mac_refout clock\n", __func__);
+       }
+
+       bsp_priv->aclk_mac = clk_get(device,"aclk_mac");
+       if (IS_ERR(bsp_priv->aclk_mac)) {
+               pr_warn("%s: warning: cannot get aclk_mac clock\n", __func__);
+       }
+
+       bsp_priv->pclk_mac = clk_get(device,"pclk_mac");
+       if (IS_ERR(bsp_priv->pclk_mac)) {
+               pr_warn("%s: warning: cannot get pclk_mac clock\n", __func__);
+       }
 
-       if ((plat) && (plat->bsp_priv)) {
-               bsp_priv = plat->bsp_priv;
+       bsp_priv->clk_mac_pll = clk_get(device,"clk_mac_pll");
+       if (IS_ERR(bsp_priv->clk_mac_pll)) {
+               pr_warn("%s: warning: cannot get clk_mac_pll clock\n", __func__);
+       }
+
+       bsp_priv->gmac_clkin = clk_get(device,"gmac_clkin");
+       if (IS_ERR(bsp_priv->gmac_clkin)) {
+               pr_warn("%s: warning: cannot get gmac_clkin clock\n", __func__);
+       }
+
+       bsp_priv->clk_mac = clk_get(device, "clk_mac");
+       if (IS_ERR(bsp_priv->clk_mac)) {
+               pr_warn("%s: warning: cannot get clk_mac clock\n", __func__);
+       }
+
+#ifdef CONFIG_GMAC_CLK_IN
+       clk_set_parent(bsp_priv->clk_mac, bsp_priv->gmac_clkin);
+#else
+       clk_set_parent(bsp_priv->clk_mac, bsp_priv->clk_mac_pll);
+#endif
+       return 0;
+}
+
+static int gmac_clk_enable(bool enable) {
+       int phy_iface = -1;
+       struct bsp_priv * bsp_priv = &g_bsp_priv;
+       phy_iface = bsp_priv->phy_iface;
+
+       if (enable) {
+               if (!bsp_priv->clk_enable) {
+                       if (phy_iface == PHY_INTERFACE_MODE_RMII) {
+                               if (!IS_ERR(bsp_priv->clk_mac))
+                                       clk_set_rate(bsp_priv->clk_mac, 50000000);
+
+                               if (!IS_ERR(bsp_priv->mac_clk_rx))
+                                       clk_prepare_enable(bsp_priv->mac_clk_rx);
+
+                               if (!IS_ERR(bsp_priv->clk_mac_ref))
+                                       clk_prepare_enable(bsp_priv->clk_mac_ref);
+
+                               if (!IS_ERR(bsp_priv->clk_mac_refout))
+                                       clk_prepare_enable(bsp_priv->clk_mac_refout);
+                       }
+
+                       if (!IS_ERR(bsp_priv->aclk_mac))
+                               clk_prepare_enable(bsp_priv->aclk_mac);
+
+                       if (!IS_ERR(bsp_priv->pclk_mac))
+                               clk_prepare_enable(bsp_priv->pclk_mac);
+
+                       if (!IS_ERR(bsp_priv->mac_clk_tx))
+                               clk_prepare_enable(bsp_priv->mac_clk_tx);
+
+                       if (!IS_ERR(bsp_priv->clk_mac))
+                               clk_prepare_enable(bsp_priv->clk_mac);
+
+
+                       bsp_priv->clk_enable = true;
+               }
        } else {
-               pr_err("%s: ERROR: platform data or private data is NULL.\n", __FUNCTION__);
+               if (bsp_priv->clk_enable) {
+                       if (phy_iface == PHY_INTERFACE_MODE_RMII) {
+                               if (!IS_ERR(bsp_priv->mac_clk_rx))
+                                       clk_disable_unprepare(bsp_priv->mac_clk_rx);
+
+                               if (!IS_ERR(bsp_priv->clk_mac_ref))
+                                       clk_disable_unprepare(bsp_priv->clk_mac_ref);
+
+                               if (!IS_ERR(bsp_priv->clk_mac_refout))
+                                       clk_disable_unprepare(bsp_priv->clk_mac_refout);
+                       }
+
+                       if (!IS_ERR(bsp_priv->aclk_mac))
+                               clk_disable_unprepare(bsp_priv->aclk_mac);
+
+                       if (!IS_ERR(bsp_priv->pclk_mac))
+                               clk_disable_unprepare(bsp_priv->pclk_mac);
+
+                       if (!IS_ERR(bsp_priv->mac_clk_tx))
+                               clk_disable_unprepare(bsp_priv->mac_clk_tx);
+
+                       if (!IS_ERR(bsp_priv->clk_mac))
+                               clk_disable_unprepare(bsp_priv->clk_mac);
+
+                       bsp_priv->clk_enable = false;
+               }
+       }
+
+       return 0;
+}
+
+static int power_on_by_pmu(bool enable) {
+       struct bsp_priv * bsp_priv = &g_bsp_priv;
+       struct regulator * ldo;
+       char * ldostr = bsp_priv->pmu_regulator;
+       int ret;
+
+       if (ldostr == NULL) {
+               pr_err("%s: no ldo found\n", __func__);
                return -1;
        }
 
+       ldo = regulator_get(NULL, ldostr);
+       if (ldo == NULL) {
+               pr_err("\n%s get ldo %s failed\n", __func__, ldostr);
+       } else {
+               if (enable) {
+                       if(!regulator_is_enabled(ldo)) {
+                               regulator_set_voltage(ldo, 3300000, 3300000);
+                               ret = regulator_enable(ldo);
+                               if(ret != 0){
+                                       pr_err("%s: faild to enable %s\n", __func__, ldostr);
+                               } else {
+                                       pr_info("turn on ldo done.\n");
+                               }
+                       } else {
+                               pr_warn("%s is enabled before enable", ldostr);
+                       }
+               } else {
+                       if(regulator_is_enabled(ldo)) {
+                               ret = regulator_disable(ldo);
+                               if(ret != 0){
+                                       pr_err("%s: faild to disable %s\n", __func__, ldostr);
+                               } else {
+                                       pr_info("turn off ldo done.\n");
+                               }
+                       } else {
+                               pr_warn("%s is disabled before disable", ldostr);
+                       }
+               }
+               regulator_put(ldo);
+               msleep(100);
+
+               if (enable) {
+                       //reset
+                       if (gpio_is_valid(bsp_priv->reset_io)) {
+                               gpio_direction_output(bsp_priv->reset_io, bsp_priv->reset_io_level);
+                               msleep(10);
+                               gpio_direction_output(bsp_priv->reset_io, !bsp_priv->reset_io_level);
+                       }
+
+                       msleep(100);
+               } else {
+                       //pull up reset
+                       if (gpio_is_valid(bsp_priv->reset_io)) {
+                               gpio_direction_output(bsp_priv->reset_io, !bsp_priv->reset_io_level);
+                       }
+               }
+
+       }
+
+       return 0;
+}
+
+static int power_on_by_gpio(bool enable) {
+       struct bsp_priv * bsp_priv = &g_bsp_priv;
        if (enable) {
                //power on
                if (gpio_is_valid(bsp_priv->power_io)) {
-                       gpio_direction_output(bsp_priv->power_io, !bsp_priv->power_io_level);
-                       msleep(10);
                        gpio_direction_output(bsp_priv->power_io, bsp_priv->power_io_level);
-                       //gpio_set_value(bsp_priv->power_io, 1);
                }
 
                //reset
                if (gpio_is_valid(bsp_priv->reset_io)) {
                        gpio_direction_output(bsp_priv->reset_io, bsp_priv->reset_io_level);
-                       //gpio_set_value(bsp_priv->reset_io, 0);
                        msleep(10);
                        gpio_direction_output(bsp_priv->reset_io, !bsp_priv->reset_io_level);
                }
@@ -102,13 +353,28 @@ static int phy_power_on(struct plat_stmmacenet_data *plat, int enable)
                //power off
                if (gpio_is_valid(bsp_priv->power_io)) {
                        gpio_direction_output(bsp_priv->power_io, !bsp_priv->power_io_level);
-                       //gpio_set_value(bsp_priv->power_io, 0);
+               }
+               //pull down reset
+               if (gpio_is_valid(bsp_priv->reset_io)) {
+                       gpio_direction_output(bsp_priv->reset_io, !bsp_priv->reset_io_level);
                }
        }
 
        return 0;
 }
 
+static int phy_power_on(bool enable)
+{
+       struct bsp_priv *bsp_priv = &g_bsp_priv;
+       printk("%s: enable = %d \n", __func__, enable);
+
+       if (bsp_priv->power_ctrl_by_pmu) {
+               return power_on_by_pmu(enable);
+       } else {
+               return power_on_by_gpio(enable);
+       }
+}
+
 int stmmc_pltfr_init(struct platform_device *pdev) {
        int phy_iface;
        int err;
@@ -134,42 +400,28 @@ int stmmc_pltfr_init(struct platform_device *pdev) {
 //power
        if (!gpio_is_valid(bsp_priv->power_io)) {
                pr_err("%s: ERROR: Get power-gpio 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;
                }
        }
 //rmii or 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(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);
-
+               SET_RGMII
        } 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);
+               SET_RMII
        } else {
                pr_err("%s: ERROR: NO interface defined!\n", __func__);
        }
@@ -192,15 +444,15 @@ void stmmc_pltfr_fix_mac_speed(void *priv, unsigned int speed){
 
                switch (speed) {
                        case 10: {
-                               grf_writel(GMAC_CLK_2_5M, RK3288_GRF_SOC_CON1);
+                               SET_RGMII_10M
                                break;
                        }
                        case 100: {
-                               grf_writel(GMAC_CLK_25M, RK3288_GRF_SOC_CON1);
+                               SET_RGMII_100M
                                break;
                        }
                        case 1000: {
-                               grf_writel(GMAC_CLK_125M, RK3288_GRF_SOC_CON1);
+                               SET_RGMII_1000M
                                break;
                        }
                        default: {
@@ -212,13 +464,11 @@ void stmmc_pltfr_fix_mac_speed(void *priv, unsigned int speed){
                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);
+                               SET_RMII_10M
                                break;
                        }
                        case 100: {
-                               grf_writel(GMAC_RMII_CLK_25M, RK3288_GRF_SOC_CON1);
-                               grf_writel(GMAC_SPEED_100M, RK3288_GRF_SOC_CON1);
+                               SET_RMII_100M
                                break;
                        }
                        default: {
@@ -247,7 +497,7 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
 
        *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)
+//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
@@ -289,6 +539,7 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
 
        g_bsp_priv.phy_iface = plat->interface;
        g_bsp_priv.phy_power_on = phy_power_on;
+       g_bsp_priv.gmac_clk_enable = gmac_clk_enable;
 
        plat->bsp_priv = &g_bsp_priv;
 
@@ -349,7 +600,7 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
 
                ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
                if (ret) {
-                       pr_err("%s: ERROR: main dt probe failed", __func__);
+                       pr_err("%s: main dt probe failed", __func__);
                        return ret;
                }
        } else {
@@ -363,12 +614,15 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
                        return ret;
        }
 
+       gmac_clk_init(&(pdev->dev));
+
        priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
        if (!priv) {
-               pr_err("%s: ERROR: main driver probe failed", __func__);
+               pr_err("%s: main driver probe failed", __func__);
                return -ENODEV;
        }
 
+
        /* Get MAC address if available (DT) */
        if (mac)
                memcpy(priv->dev->dev_addr, mac, ETH_ALEN);