net: ethernet: stmmac: dwmac-rk: rework optional clock handling
[ Upstream commit ea449f7fa0bf3fcd02e04a770b9ff707bf5e8f96 ]
The clock requesting code is quite repetitive. Fix this by requesting
the clocks via devm_clk_bulk_get_optional. The optional variant has been
used, since this is effectively what the old code did. The exact clocks
required depend on the platform and configuration. As a side effect
this change adds correct -EPROBE_DEFER handling.
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Fixes: 7ad269ea1a
("GMAC: add driver for Rockchip RK3288 SoCs integrated GMAC")
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
e6f1ef4a53
commit
c649bf43a2
@ -39,6 +39,24 @@ struct rk_gmac_ops {
|
||||
u32 regs[];
|
||||
};
|
||||
|
||||
static const char * const rk_clocks[] = {
|
||||
"aclk_mac", "pclk_mac", "mac_clk_tx", "clk_mac_speed",
|
||||
};
|
||||
|
||||
static const char * const rk_rmii_clocks[] = {
|
||||
"mac_clk_rx", "clk_mac_ref", "clk_mac_refout",
|
||||
};
|
||||
|
||||
enum rk_clocks_index {
|
||||
RK_ACLK_MAC = 0,
|
||||
RK_PCLK_MAC,
|
||||
RK_MAC_CLK_TX,
|
||||
RK_CLK_MAC_SPEED,
|
||||
RK_MAC_CLK_RX,
|
||||
RK_CLK_MAC_REF,
|
||||
RK_CLK_MAC_REFOUT,
|
||||
};
|
||||
|
||||
struct rk_priv_data {
|
||||
struct platform_device *pdev;
|
||||
phy_interface_t phy_iface;
|
||||
@ -51,15 +69,9 @@ struct rk_priv_data {
|
||||
bool clock_input;
|
||||
bool integrated_phy;
|
||||
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
struct clk *clk_mac;
|
||||
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 *clk_mac_speed;
|
||||
struct clk *aclk_mac;
|
||||
struct clk *pclk_mac;
|
||||
struct clk *clk_phy;
|
||||
|
||||
struct reset_control *phy_reset;
|
||||
@ -104,10 +116,11 @@ static void px30_set_to_rmii(struct rk_priv_data *bsp_priv)
|
||||
|
||||
static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
{
|
||||
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(bsp_priv->clk_mac_speed)) {
|
||||
if (!clk_mac_speed) {
|
||||
dev_err(dev, "%s: Missing clk_mac_speed clock\n", __func__);
|
||||
return;
|
||||
}
|
||||
@ -116,7 +129,7 @@ static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
|
||||
PX30_GMAC_SPEED_10M);
|
||||
|
||||
ret = clk_set_rate(bsp_priv->clk_mac_speed, 2500000);
|
||||
ret = clk_set_rate(clk_mac_speed, 2500000);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: set clk_mac_speed rate 2500000 failed: %d\n",
|
||||
__func__, ret);
|
||||
@ -124,7 +137,7 @@ static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1,
|
||||
PX30_GMAC_SPEED_100M);
|
||||
|
||||
ret = clk_set_rate(bsp_priv->clk_mac_speed, 25000000);
|
||||
ret = clk_set_rate(clk_mac_speed, 25000000);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: set clk_mac_speed rate 25000000 failed: %d\n",
|
||||
__func__, ret);
|
||||
@ -1066,6 +1079,7 @@ static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv)
|
||||
|
||||
static void rk3568_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
{
|
||||
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
@ -1085,7 +1099,7 @@ static void rk3568_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(bsp_priv->clk_mac_speed, rate);
|
||||
ret = clk_set_rate(clk_mac_speed, rate);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n",
|
||||
__func__, rate, ret);
|
||||
@ -1371,6 +1385,7 @@ static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv)
|
||||
|
||||
static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
{
|
||||
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
@ -1390,7 +1405,7 @@ static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(bsp_priv->clk_mac_speed, rate);
|
||||
ret = clk_set_rate(clk_mac_speed, rate);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n",
|
||||
__func__, rate, ret);
|
||||
@ -1398,6 +1413,7 @@ static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
|
||||
static void rv1126_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
{
|
||||
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
|
||||
struct device *dev = &bsp_priv->pdev->dev;
|
||||
unsigned long rate;
|
||||
int ret;
|
||||
@ -1414,7 +1430,7 @@ static void rv1126_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(bsp_priv->clk_mac_speed, rate);
|
||||
ret = clk_set_rate(clk_mac_speed, rate);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n",
|
||||
__func__, rate, ret);
|
||||
@ -1475,68 +1491,50 @@ 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;
|
||||
int phy_iface = bsp_priv->phy_iface;
|
||||
int i, j, ret;
|
||||
|
||||
bsp_priv->clk_enabled = false;
|
||||
|
||||
bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
|
||||
if (IS_ERR(bsp_priv->mac_clk_rx))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"mac_clk_rx");
|
||||
bsp_priv->num_clks = ARRAY_SIZE(rk_clocks);
|
||||
if (phy_iface == PHY_INTERFACE_MODE_RMII)
|
||||
bsp_priv->num_clks += ARRAY_SIZE(rk_rmii_clocks);
|
||||
|
||||
bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
|
||||
if (IS_ERR(bsp_priv->mac_clk_tx))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"mac_clk_tx");
|
||||
bsp_priv->clks = devm_kcalloc(dev, bsp_priv->num_clks,
|
||||
sizeof(*bsp_priv->clks), GFP_KERNEL);
|
||||
if (!bsp_priv->clks)
|
||||
return -ENOMEM;
|
||||
|
||||
bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
|
||||
if (IS_ERR(bsp_priv->aclk_mac))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"aclk_mac");
|
||||
for (i = 0; i < ARRAY_SIZE(rk_clocks); i++)
|
||||
bsp_priv->clks[i].id = rk_clocks[i];
|
||||
|
||||
bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
|
||||
if (IS_ERR(bsp_priv->pclk_mac))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"pclk_mac");
|
||||
|
||||
bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
|
||||
if (IS_ERR(bsp_priv->clk_mac))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"stmmaceth");
|
||||
|
||||
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
|
||||
bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
|
||||
if (IS_ERR(bsp_priv->clk_mac_ref))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"clk_mac_ref");
|
||||
|
||||
if (!bsp_priv->clock_input) {
|
||||
bsp_priv->clk_mac_refout =
|
||||
devm_clk_get(dev, "clk_mac_refout");
|
||||
if (IS_ERR(bsp_priv->clk_mac_refout))
|
||||
dev_err(dev, "cannot get clock %s\n",
|
||||
"clk_mac_refout");
|
||||
}
|
||||
if (phy_iface == PHY_INTERFACE_MODE_RMII) {
|
||||
for (j = 0; j < ARRAY_SIZE(rk_rmii_clocks); j++)
|
||||
bsp_priv->clks[i++].id = rk_rmii_clocks[j];
|
||||
}
|
||||
|
||||
bsp_priv->clk_mac_speed = devm_clk_get(dev, "clk_mac_speed");
|
||||
if (IS_ERR(bsp_priv->clk_mac_speed))
|
||||
dev_err(dev, "cannot get clock %s\n", "clk_mac_speed");
|
||||
ret = devm_clk_bulk_get_optional(dev, bsp_priv->num_clks,
|
||||
bsp_priv->clks);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get clocks\n");
|
||||
|
||||
/* "stmmaceth" will be enabled by the core */
|
||||
bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
|
||||
ret = PTR_ERR_OR_ZERO(bsp_priv->clk_mac);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Cannot get stmmaceth clock\n");
|
||||
|
||||
if (bsp_priv->clock_input) {
|
||||
dev_info(dev, "clock input from PHY\n");
|
||||
} else {
|
||||
if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
|
||||
clk_set_rate(bsp_priv->clk_mac, 50000000);
|
||||
} else if (phy_iface == PHY_INTERFACE_MODE_RMII) {
|
||||
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;
|
||||
}
|
||||
ret = PTR_ERR_OR_ZERO(bsp_priv->clk_phy);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Cannot get PHY clock\n");
|
||||
clk_set_rate(bsp_priv->clk_phy, 50000000);
|
||||
}
|
||||
|
||||
@ -1545,77 +1543,36 @@ static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat)
|
||||
|
||||
static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
|
||||
{
|
||||
int phy_iface = bsp_priv->phy_iface;
|
||||
int ret;
|
||||
|
||||
if (enable) {
|
||||
if (!bsp_priv->clk_enabled) {
|
||||
if (phy_iface == PHY_INTERFACE_MODE_RMII) {
|
||||
if (!IS_ERR(bsp_priv->mac_clk_rx))
|
||||
clk_prepare_enable(
|
||||
bsp_priv->mac_clk_rx);
|
||||
ret = clk_bulk_prepare_enable(bsp_priv->num_clks,
|
||||
bsp_priv->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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->clk_phy))
|
||||
clk_prepare_enable(bsp_priv->clk_phy);
|
||||
|
||||
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_speed))
|
||||
clk_prepare_enable(bsp_priv->clk_mac_speed);
|
||||
ret = clk_prepare_enable(bsp_priv->clk_phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
|
||||
bsp_priv->ops->set_clock_selection(bsp_priv,
|
||||
bsp_priv->clock_input, true);
|
||||
|
||||
/**
|
||||
* if (!IS_ERR(bsp_priv->clk_mac))
|
||||
* clk_prepare_enable(bsp_priv->clk_mac);
|
||||
*/
|
||||
mdelay(5);
|
||||
bsp_priv->clk_enabled = true;
|
||||
}
|
||||
} else {
|
||||
if (bsp_priv->clk_enabled) {
|
||||
if (phy_iface == PHY_INTERFACE_MODE_RMII) {
|
||||
clk_disable_unprepare(bsp_priv->mac_clk_rx);
|
||||
|
||||
clk_disable_unprepare(bsp_priv->clk_mac_ref);
|
||||
|
||||
clk_disable_unprepare(bsp_priv->clk_mac_refout);
|
||||
}
|
||||
|
||||
clk_bulk_disable_unprepare(bsp_priv->num_clks,
|
||||
bsp_priv->clks);
|
||||
clk_disable_unprepare(bsp_priv->clk_phy);
|
||||
|
||||
clk_disable_unprepare(bsp_priv->aclk_mac);
|
||||
|
||||
clk_disable_unprepare(bsp_priv->pclk_mac);
|
||||
|
||||
clk_disable_unprepare(bsp_priv->mac_clk_tx);
|
||||
|
||||
clk_disable_unprepare(bsp_priv->clk_mac_speed);
|
||||
|
||||
if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
|
||||
bsp_priv->ops->set_clock_selection(bsp_priv,
|
||||
bsp_priv->clock_input, false);
|
||||
/**
|
||||
* if (!IS_ERR(bsp_priv->clk_mac))
|
||||
* clk_disable_unprepare(bsp_priv->clk_mac);
|
||||
*/
|
||||
|
||||
bsp_priv->clk_enabled = false;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user