Commit a045e406 authored by Swathi K S's avatar Swathi K S Committed by Jakub Kicinski
Browse files

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: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarSwathi K S <swathi.ks@samsung.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250213041559.106111-1-swathi.ks@samsung.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c6287e1a
Loading
Loading
Loading
Loading
+32 −99
Original line number Diff line number Diff line
@@ -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;
	}

	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;

	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;
		} else if (strcmp(data->clks[i].id, "tx") == 0) {
			eqos->clk_tx = data->clks[i].clk;
		}

	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);
	if (IS_ERR(eqos->reset)) {
		err = PTR_ERR(eqos->reset);
		goto disable_tx;
		return err;
	}

	usleep_range(2000, 4000);
@@ -365,15 +295,7 @@ static int tegra_eqos_probe(struct platform_device *pdev,
	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,6 +378,7 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev)
	return ret;

remove:
	if (data->remove)
		data->remove(pdev);

	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)
{
	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);

	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[] = {
+2 −0
Original line number Diff line number Diff line
@@ -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;