#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;
}
* 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))
return stmmac_ptp_register(priv);
}
-
+*/
static void stmmac_release_ptp(struct stmmac_priv *priv)
{
stmmac_ptp_unregister(priv);
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)
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)) {
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
#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)
#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))
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;
}
int stmmc_pltfr_init(struct platform_device *pdev) {
- //struct pinctrl_state *gmac_state;
int phy_iface;
int err;
struct bsp_priv *bsp_priv;
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);
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) {
}
}
- } 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: {
{
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);
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;