From: Swathi K S Date: Thu, 13 Feb 2025 04:15:59 +0000 (+0530) Subject: net: stmmac: refactor clock management in EQoS driver X-Git-Tag: v6.15-rc1~160^2~323 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a045e40645dfa02a68c17ad8a3c92a8ef62375b0;p=thirdparty%2Flinux.git 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 Signed-off-by: Swathi K S Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250213041559.106111-1-swathi.ks@samsung.com Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index bd4eb187f8c64..1fadb8ba1d2ff 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -29,10 +29,8 @@ struct tegra_eqos { void __iomem *regs; struct reset_control *rst; - struct clk *clk_master; struct clk *clk_slave; struct clk *clk_tx; - struct clk *clk_rx; struct gpio_desc *reset; }; @@ -123,49 +121,14 @@ static int dwc_qos_probe(struct platform_device *pdev, struct plat_stmmacenet_data *plat_dat, struct stmmac_resources *stmmac_res) { - int err; - - plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk"); - if (IS_ERR(plat_dat->stmmac_clk)) { - dev_err(&pdev->dev, "apb_pclk clock not found.\n"); - 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; + for (int i = 0; i < plat_dat->num_clks; i++) { + if (strcmp(plat_dat->clks[i].id, "apb_pclk") == 0) + plat_dat->stmmac_clk = plat_dat->clks[i].clk; + else if (strcmp(plat_dat->clks[i].id, "phy_ref_clk") == 0) + plat_dat->pclk = plat_dat->clks[i].clk; } 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 @@ -278,52 +241,19 @@ static int tegra_eqos_probe(struct platform_device *pdev, if (!is_of_node(dev->fwnode)) goto bypass_clk_reset_gpio; - eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus"); - if (IS_ERR(eqos->clk_master)) { - err = PTR_ERR(eqos->clk_master); - goto error; - } - - 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; + for (int i = 0; i < data->num_clks; i++) { + if (strcmp(data->clks[i].id, "slave_bus") == 0) { + eqos->clk_slave = data->clks[i].clk; + 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_tx); - if (err < 0) - goto disable_rx; - eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH); if (IS_ERR(eqos->reset)) { err = PTR_ERR(eqos->reset); - goto disable_tx; + return err; } usleep_range(2000, 4000); @@ -365,15 +295,7 @@ reset: reset_control_assert(eqos->rst); reset_phy: 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; } @@ -383,10 +305,6 @@ static void tegra_eqos_remove(struct platform_device *pdev) reset_control_assert(eqos->rst); 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 { @@ -398,7 +316,6 @@ struct dwc_eth_dwmac_data { static const struct dwc_eth_dwmac_data dwc_qos_data = { .probe = dwc_qos_probe, - .remove = dwc_qos_remove, }; 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)) 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); if (ret < 0) { dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n"); + clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks); return ret; } @@ -451,7 +378,8 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) return ret; remove: - data->remove(pdev); + if (data->remove) + data->remove(pdev); return ret; } @@ -459,10 +387,15 @@ remove: static void dwc_eth_dwmac_remove(struct platform_device *pdev) { 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); - 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[] = { diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index c9878a612e532..24422ac4e4179 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -254,6 +254,8 @@ struct plat_stmmacenet_data { struct clk *clk_ptp_ref; unsigned long clk_ptp_rate; unsigned long clk_ref_rate; + struct clk_bulk_data *clks; + int num_clks; unsigned int mult_fact_100ns; s32 ptp_max_adj; u32 cdc_error_adj;