mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 10:20:17 -04:00
net: stmmac: refactor clock management in EQoS driver
Refactor clock management in EQoS driver for code reuse and to avoid redundancy. This way, only minimal changes are required when a new platform is added. Suggested-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Swathi K S <swathi.ks@samsung.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Link: https://patch.msgid.link/20250213041559.106111-1-swathi.ks@samsung.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
c6287e1a85
commit
a045e40645
@@ -29,10 +29,8 @@ struct tegra_eqos {
|
|||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
|
|
||||||
struct reset_control *rst;
|
struct reset_control *rst;
|
||||||
struct clk *clk_master;
|
|
||||||
struct clk *clk_slave;
|
struct clk *clk_slave;
|
||||||
struct clk *clk_tx;
|
struct clk *clk_tx;
|
||||||
struct clk *clk_rx;
|
|
||||||
|
|
||||||
struct gpio_desc *reset;
|
struct gpio_desc *reset;
|
||||||
};
|
};
|
||||||
@@ -123,49 +121,14 @@ static int dwc_qos_probe(struct platform_device *pdev,
|
|||||||
struct plat_stmmacenet_data *plat_dat,
|
struct plat_stmmacenet_data *plat_dat,
|
||||||
struct stmmac_resources *stmmac_res)
|
struct stmmac_resources *stmmac_res)
|
||||||
{
|
{
|
||||||
int err;
|
for (int i = 0; i < plat_dat->num_clks; i++) {
|
||||||
|
if (strcmp(plat_dat->clks[i].id, "apb_pclk") == 0)
|
||||||
plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk");
|
plat_dat->stmmac_clk = plat_dat->clks[i].clk;
|
||||||
if (IS_ERR(plat_dat->stmmac_clk)) {
|
else if (strcmp(plat_dat->clks[i].id, "phy_ref_clk") == 0)
|
||||||
dev_err(&pdev->dev, "apb_pclk clock not found.\n");
|
plat_dat->pclk = plat_dat->clks[i].clk;
|
||||||
return PTR_ERR(plat_dat->stmmac_clk);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_prepare_enable(plat_dat->stmmac_clk);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(&pdev->dev, "failed to enable apb_pclk clock: %d\n",
|
|
||||||
err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk");
|
|
||||||
if (IS_ERR(plat_dat->pclk)) {
|
|
||||||
dev_err(&pdev->dev, "phy_ref_clk clock not found.\n");
|
|
||||||
err = PTR_ERR(plat_dat->pclk);
|
|
||||||
goto disable;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_prepare_enable(plat_dat->pclk);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n",
|
|
||||||
err);
|
|
||||||
goto disable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
disable:
|
|
||||||
clk_disable_unprepare(plat_dat->stmmac_clk);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dwc_qos_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
|
||||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
|
||||||
|
|
||||||
clk_disable_unprepare(priv->plat->pclk);
|
|
||||||
clk_disable_unprepare(priv->plat->stmmac_clk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SDMEMCOMPPADCTRL 0x8800
|
#define SDMEMCOMPPADCTRL 0x8800
|
||||||
@@ -278,52 +241,19 @@ static int tegra_eqos_probe(struct platform_device *pdev,
|
|||||||
if (!is_of_node(dev->fwnode))
|
if (!is_of_node(dev->fwnode))
|
||||||
goto bypass_clk_reset_gpio;
|
goto bypass_clk_reset_gpio;
|
||||||
|
|
||||||
eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus");
|
for (int i = 0; i < data->num_clks; i++) {
|
||||||
if (IS_ERR(eqos->clk_master)) {
|
if (strcmp(data->clks[i].id, "slave_bus") == 0) {
|
||||||
err = PTR_ERR(eqos->clk_master);
|
eqos->clk_slave = data->clks[i].clk;
|
||||||
goto error;
|
data->stmmac_clk = eqos->clk_slave;
|
||||||
|
} else if (strcmp(data->clks[i].id, "tx") == 0) {
|
||||||
|
eqos->clk_tx = data->clks[i].clk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(eqos->clk_master);
|
|
||||||
if (err < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus");
|
|
||||||
if (IS_ERR(eqos->clk_slave)) {
|
|
||||||
err = PTR_ERR(eqos->clk_slave);
|
|
||||||
goto disable_master;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->stmmac_clk = eqos->clk_slave;
|
|
||||||
|
|
||||||
err = clk_prepare_enable(eqos->clk_slave);
|
|
||||||
if (err < 0)
|
|
||||||
goto disable_master;
|
|
||||||
|
|
||||||
eqos->clk_rx = devm_clk_get(&pdev->dev, "rx");
|
|
||||||
if (IS_ERR(eqos->clk_rx)) {
|
|
||||||
err = PTR_ERR(eqos->clk_rx);
|
|
||||||
goto disable_slave;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_prepare_enable(eqos->clk_rx);
|
|
||||||
if (err < 0)
|
|
||||||
goto disable_slave;
|
|
||||||
|
|
||||||
eqos->clk_tx = devm_clk_get(&pdev->dev, "tx");
|
|
||||||
if (IS_ERR(eqos->clk_tx)) {
|
|
||||||
err = PTR_ERR(eqos->clk_tx);
|
|
||||||
goto disable_rx;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = clk_prepare_enable(eqos->clk_tx);
|
|
||||||
if (err < 0)
|
|
||||||
goto disable_rx;
|
|
||||||
|
|
||||||
eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
|
eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH);
|
||||||
if (IS_ERR(eqos->reset)) {
|
if (IS_ERR(eqos->reset)) {
|
||||||
err = PTR_ERR(eqos->reset);
|
err = PTR_ERR(eqos->reset);
|
||||||
goto disable_tx;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep_range(2000, 4000);
|
usleep_range(2000, 4000);
|
||||||
@@ -365,15 +295,7 @@ static int tegra_eqos_probe(struct platform_device *pdev,
|
|||||||
reset_control_assert(eqos->rst);
|
reset_control_assert(eqos->rst);
|
||||||
reset_phy:
|
reset_phy:
|
||||||
gpiod_set_value(eqos->reset, 1);
|
gpiod_set_value(eqos->reset, 1);
|
||||||
disable_tx:
|
|
||||||
clk_disable_unprepare(eqos->clk_tx);
|
|
||||||
disable_rx:
|
|
||||||
clk_disable_unprepare(eqos->clk_rx);
|
|
||||||
disable_slave:
|
|
||||||
clk_disable_unprepare(eqos->clk_slave);
|
|
||||||
disable_master:
|
|
||||||
clk_disable_unprepare(eqos->clk_master);
|
|
||||||
error:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,10 +305,6 @@ static void tegra_eqos_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
reset_control_assert(eqos->rst);
|
reset_control_assert(eqos->rst);
|
||||||
gpiod_set_value(eqos->reset, 1);
|
gpiod_set_value(eqos->reset, 1);
|
||||||
clk_disable_unprepare(eqos->clk_tx);
|
|
||||||
clk_disable_unprepare(eqos->clk_rx);
|
|
||||||
clk_disable_unprepare(eqos->clk_slave);
|
|
||||||
clk_disable_unprepare(eqos->clk_master);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dwc_eth_dwmac_data {
|
struct dwc_eth_dwmac_data {
|
||||||
@@ -398,7 +316,6 @@ struct dwc_eth_dwmac_data {
|
|||||||
|
|
||||||
static const struct dwc_eth_dwmac_data dwc_qos_data = {
|
static const struct dwc_eth_dwmac_data dwc_qos_data = {
|
||||||
.probe = dwc_qos_probe,
|
.probe = dwc_qos_probe,
|
||||||
.remove = dwc_qos_remove,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct dwc_eth_dwmac_data tegra_eqos_data = {
|
static const struct dwc_eth_dwmac_data tegra_eqos_data = {
|
||||||
@@ -434,9 +351,19 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(plat_dat))
|
if (IS_ERR(plat_dat))
|
||||||
return PTR_ERR(plat_dat);
|
return PTR_ERR(plat_dat);
|
||||||
|
|
||||||
|
ret = devm_clk_bulk_get_all(&pdev->dev, &plat_dat->clks);
|
||||||
|
if (ret < 0)
|
||||||
|
return dev_err_probe(&pdev->dev, ret, "Failed to retrieve all required clocks\n");
|
||||||
|
plat_dat->num_clks = ret;
|
||||||
|
|
||||||
|
ret = clk_bulk_prepare_enable(plat_dat->num_clks, plat_dat->clks);
|
||||||
|
if (ret)
|
||||||
|
return dev_err_probe(&pdev->dev, ret, "Failed to enable clocks\n");
|
||||||
|
|
||||||
ret = data->probe(pdev, plat_dat, &stmmac_res);
|
ret = data->probe(pdev, plat_dat, &stmmac_res);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n");
|
dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n");
|
||||||
|
clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +378,8 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
remove:
|
remove:
|
||||||
data->remove(pdev);
|
if (data->remove)
|
||||||
|
data->remove(pdev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -459,10 +387,15 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev)
|
|||||||
static void dwc_eth_dwmac_remove(struct platform_device *pdev)
|
static void dwc_eth_dwmac_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct dwc_eth_dwmac_data *data = device_get_match_data(&pdev->dev);
|
const struct dwc_eth_dwmac_data *data = device_get_match_data(&pdev->dev);
|
||||||
|
struct plat_stmmacenet_data *plat_data = dev_get_platdata(&pdev->dev);
|
||||||
|
|
||||||
stmmac_dvr_remove(&pdev->dev);
|
stmmac_dvr_remove(&pdev->dev);
|
||||||
|
|
||||||
data->remove(pdev);
|
if (data->remove)
|
||||||
|
data->remove(pdev);
|
||||||
|
|
||||||
|
if (plat_data)
|
||||||
|
clk_bulk_disable_unprepare(plat_data->num_clks, plat_data->clks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id dwc_eth_dwmac_match[] = {
|
static const struct of_device_id dwc_eth_dwmac_match[] = {
|
||||||
|
|||||||
@@ -254,6 +254,8 @@ struct plat_stmmacenet_data {
|
|||||||
struct clk *clk_ptp_ref;
|
struct clk *clk_ptp_ref;
|
||||||
unsigned long clk_ptp_rate;
|
unsigned long clk_ptp_rate;
|
||||||
unsigned long clk_ref_rate;
|
unsigned long clk_ref_rate;
|
||||||
|
struct clk_bulk_data *clks;
|
||||||
|
int num_clks;
|
||||||
unsigned int mult_fact_100ns;
|
unsigned int mult_fact_100ns;
|
||||||
s32 ptp_max_adj;
|
s32 ptp_max_adj;
|
||||||
u32 cdc_error_adj;
|
u32 cdc_error_adj;
|
||||||
|
|||||||
Reference in New Issue
Block a user