Skip to content

Commit

Permalink
net: stmmac: dwmac-rk: Add integrated PHY support
Browse files Browse the repository at this point in the history
To make integrated PHY work, need to configure the PHY clock,
PHY cru reset and related registers.

Signed-off-by: David Wu <david.wu@rock-chips.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David Wu authored and David S. Miller committed Aug 11, 2017
1 parent 2398506 commit fecd4d7
Showing 1 changed file with 95 additions and 4 deletions.
99 changes: 95 additions & 4 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct rk_gmac_ops {
void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
};

struct rk_priv_data {
Expand All @@ -52,6 +53,7 @@ struct rk_priv_data {

bool clk_enabled;
bool clock_input;
bool integrated_phy;

struct clk *clk_mac;
struct clk *gmac_clkin;
Expand All @@ -61,6 +63,9 @@ struct rk_priv_data {
struct clk *clk_mac_refout;
struct clk *aclk_mac;
struct clk *pclk_mac;
struct clk *clk_phy;

struct reset_control *phy_reset;

int tx_delay;
int rx_delay;
Expand Down Expand Up @@ -750,9 +755,55 @@ static const struct rk_gmac_ops rk3399_ops = {
.set_rmii_speed = rk3399_set_rmii_speed,
};

static int gmac_clk_init(struct rk_priv_data *bsp_priv)
#define RK_GRF_MACPHY_CON0 0xb00
#define RK_GRF_MACPHY_CON1 0xb04
#define RK_GRF_MACPHY_CON2 0xb08
#define RK_GRF_MACPHY_CON3 0xb0c

#define RK_MACPHY_ENABLE GRF_BIT(0)
#define RK_MACPHY_DISABLE GRF_CLR_BIT(0)
#define RK_MACPHY_CFG_CLK_50M GRF_BIT(14)
#define RK_GMAC2PHY_RMII_MODE (GRF_BIT(6) | GRF_CLR_BIT(7))
#define RK_GRF_CON2_MACPHY_ID HIWORD_UPDATE(0x1234, 0xffff, 0)
#define RK_GRF_CON3_MACPHY_ID HIWORD_UPDATE(0x35, 0x3f, 0)

static void rk_gmac_integrated_phy_powerup(struct rk_priv_data *priv)
{
if (priv->ops->integrated_phy_powerup)
priv->ops->integrated_phy_powerup(priv);

regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_CFG_CLK_50M);
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_GMAC2PHY_RMII_MODE);

regmap_write(priv->grf, RK_GRF_MACPHY_CON2, RK_GRF_CON2_MACPHY_ID);
regmap_write(priv->grf, RK_GRF_MACPHY_CON3, RK_GRF_CON3_MACPHY_ID);

if (priv->phy_reset) {
/* PHY needs to be disabled before trying to reset it */
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
if (priv->phy_reset)
reset_control_assert(priv->phy_reset);
usleep_range(10, 20);
if (priv->phy_reset)
reset_control_deassert(priv->phy_reset);
usleep_range(10, 20);
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_ENABLE);
msleep(30);
}
}

static void rk_gmac_integrated_phy_powerdown(struct rk_priv_data *priv)
{
regmap_write(priv->grf, RK_GRF_MACPHY_CON0, RK_MACPHY_DISABLE);
if (priv->phy_reset)
reset_control_assert(priv->phy_reset);
}

static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat)
{
struct rk_priv_data *bsp_priv = plat->bsp_priv;
struct device *dev = &bsp_priv->pdev->dev;
int ret;

bsp_priv->clk_enabled = false;

Expand Down Expand Up @@ -803,6 +854,16 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv)
clk_set_rate(bsp_priv->clk_mac, 50000000);
}

if (plat->phy_node && bsp_priv->integrated_phy) {
bsp_priv->clk_phy = of_clk_get(plat->phy_node, 0);
if (IS_ERR(bsp_priv->clk_phy)) {
ret = PTR_ERR(bsp_priv->clk_phy);
dev_err(dev, "Cannot get PHY clock: %d\n", ret);
return -EINVAL;
}
clk_set_rate(bsp_priv->clk_phy, 50000000);
}

return 0;
}

Expand All @@ -826,6 +887,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
bsp_priv->clk_mac_refout);
}

if (!IS_ERR(bsp_priv->clk_phy))
clk_prepare_enable(bsp_priv->clk_phy);

if (!IS_ERR(bsp_priv->aclk_mac))
clk_prepare_enable(bsp_priv->aclk_mac);

Expand Down Expand Up @@ -858,6 +922,9 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
bsp_priv->clk_mac_refout);
}

if (!IS_ERR(bsp_priv->clk_phy))
clk_disable_unprepare(bsp_priv->clk_phy);

if (!IS_ERR(bsp_priv->aclk_mac))
clk_disable_unprepare(bsp_priv->aclk_mac);

Expand Down Expand Up @@ -902,6 +969,7 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
}

static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
struct plat_stmmacenet_data *plat,
const struct rk_gmac_ops *ops)
{
struct rk_priv_data *bsp_priv;
Expand Down Expand Up @@ -964,9 +1032,22 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,

bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,grf");
bsp_priv->pdev = pdev;

gmac_clk_init(bsp_priv);
if (plat->phy_node) {
bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
"phy-is-integrated");
if (bsp_priv->integrated_phy) {
bsp_priv->phy_reset = of_reset_control_get(plat->phy_node, NULL);
if (IS_ERR(bsp_priv->phy_reset)) {
dev_err(&pdev->dev, "No PHY reset control found.\n");
bsp_priv->phy_reset = NULL;
}
}
}
dev_info(dev, "integrated PHY? (%s).\n",
bsp_priv->integrated_phy ? "yes" : "no");

bsp_priv->pdev = pdev;

return bsp_priv;
}
Expand Down Expand Up @@ -1014,13 +1095,19 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);

if (bsp_priv->integrated_phy)
rk_gmac_integrated_phy_powerup(bsp_priv);

return 0;
}

static void rk_gmac_powerdown(struct rk_priv_data *gmac)
{
struct device *dev = &gmac->pdev->dev;

if (gmac->integrated_phy)
rk_gmac_integrated_phy_powerdown(gmac);

pm_runtime_put_sync(dev);
pm_runtime_disable(dev);

Expand Down Expand Up @@ -1072,12 +1159,16 @@ static int rk_gmac_probe(struct platform_device *pdev)
plat_dat->has_gmac = true;
plat_dat->fix_mac_speed = rk_fix_speed;

plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data);
if (IS_ERR(plat_dat->bsp_priv)) {
ret = PTR_ERR(plat_dat->bsp_priv);
goto err_remove_config_dt;
}

ret = rk_gmac_clk_init(plat_dat);
if (ret)
return ret;

ret = rk_gmac_powerup(plat_dat->bsp_priv);
if (ret)
goto err_remove_config_dt;
Expand Down

0 comments on commit fecd4d7

Please sign in to comment.