Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Swathi K S and committed by
Jakub Kicinski
a045e406 c6287e1a

+34 -99
+32 -99
drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
··· 29 29 void __iomem *regs; 30 30 31 31 struct reset_control *rst; 32 - struct clk *clk_master; 33 32 struct clk *clk_slave; 34 33 struct clk *clk_tx; 35 - struct clk *clk_rx; 36 34 37 35 struct gpio_desc *reset; 38 36 }; ··· 121 123 struct plat_stmmacenet_data *plat_dat, 122 124 struct stmmac_resources *stmmac_res) 123 125 { 124 - int err; 125 - 126 - plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk"); 127 - if (IS_ERR(plat_dat->stmmac_clk)) { 128 - dev_err(&pdev->dev, "apb_pclk clock not found.\n"); 129 - return PTR_ERR(plat_dat->stmmac_clk); 130 - } 131 - 132 - err = clk_prepare_enable(plat_dat->stmmac_clk); 133 - if (err < 0) { 134 - dev_err(&pdev->dev, "failed to enable apb_pclk clock: %d\n", 135 - err); 136 - return err; 137 - } 138 - 139 - plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk"); 140 - if (IS_ERR(plat_dat->pclk)) { 141 - dev_err(&pdev->dev, "phy_ref_clk clock not found.\n"); 142 - err = PTR_ERR(plat_dat->pclk); 143 - goto disable; 144 - } 145 - 146 - err = clk_prepare_enable(plat_dat->pclk); 147 - if (err < 0) { 148 - dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n", 149 - err); 150 - goto disable; 126 + for (int i = 0; i < plat_dat->num_clks; i++) { 127 + if (strcmp(plat_dat->clks[i].id, "apb_pclk") == 0) 128 + plat_dat->stmmac_clk = plat_dat->clks[i].clk; 129 + else if (strcmp(plat_dat->clks[i].id, "phy_ref_clk") == 0) 130 + plat_dat->pclk = plat_dat->clks[i].clk; 151 131 } 152 132 153 133 return 0; 154 - 155 - disable: 156 - clk_disable_unprepare(plat_dat->stmmac_clk); 157 - return err; 158 - } 159 - 160 - static void dwc_qos_remove(struct platform_device *pdev) 161 - { 162 - struct net_device *ndev = platform_get_drvdata(pdev); 163 - struct stmmac_priv *priv = netdev_priv(ndev); 164 - 165 - clk_disable_unprepare(priv->plat->pclk); 166 - clk_disable_unprepare(priv->plat->stmmac_clk); 167 134 } 168 135 169 136 #define SDMEMCOMPPADCTRL 0x8800 ··· 241 278 if (!is_of_node(dev->fwnode)) 242 279 goto bypass_clk_reset_gpio; 243 280 244 - eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus"); 245 - if (IS_ERR(eqos->clk_master)) { 246 - err = PTR_ERR(eqos->clk_master); 247 - goto error; 281 + for (int i = 0; i < data->num_clks; i++) { 282 + if (strcmp(data->clks[i].id, "slave_bus") == 0) { 283 + eqos->clk_slave = data->clks[i].clk; 284 + data->stmmac_clk = eqos->clk_slave; 285 + } else if (strcmp(data->clks[i].id, "tx") == 0) { 286 + eqos->clk_tx = data->clks[i].clk; 287 + } 248 288 } 249 - 250 - err = clk_prepare_enable(eqos->clk_master); 251 - if (err < 0) 252 - goto error; 253 - 254 - eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus"); 255 - if (IS_ERR(eqos->clk_slave)) { 256 - err = PTR_ERR(eqos->clk_slave); 257 - goto disable_master; 258 - } 259 - 260 - data->stmmac_clk = eqos->clk_slave; 261 - 262 - err = clk_prepare_enable(eqos->clk_slave); 263 - if (err < 0) 264 - goto disable_master; 265 - 266 - eqos->clk_rx = devm_clk_get(&pdev->dev, "rx"); 267 - if (IS_ERR(eqos->clk_rx)) { 268 - err = PTR_ERR(eqos->clk_rx); 269 - goto disable_slave; 270 - } 271 - 272 - err = clk_prepare_enable(eqos->clk_rx); 273 - if (err < 0) 274 - goto disable_slave; 275 - 276 - eqos->clk_tx = devm_clk_get(&pdev->dev, "tx"); 277 - if (IS_ERR(eqos->clk_tx)) { 278 - err = PTR_ERR(eqos->clk_tx); 279 - goto disable_rx; 280 - } 281 - 282 - err = clk_prepare_enable(eqos->clk_tx); 283 - if (err < 0) 284 - goto disable_rx; 285 289 286 290 eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH); 287 291 if (IS_ERR(eqos->reset)) { 288 292 err = PTR_ERR(eqos->reset); 289 - goto disable_tx; 293 + return err; 290 294 } 291 295 292 296 usleep_range(2000, 4000); ··· 295 365 reset_control_assert(eqos->rst); 296 366 reset_phy: 297 367 gpiod_set_value(eqos->reset, 1); 298 - disable_tx: 299 - clk_disable_unprepare(eqos->clk_tx); 300 - disable_rx: 301 - clk_disable_unprepare(eqos->clk_rx); 302 - disable_slave: 303 - clk_disable_unprepare(eqos->clk_slave); 304 - disable_master: 305 - clk_disable_unprepare(eqos->clk_master); 306 - error: 368 + 307 369 return err; 308 370 } 309 371 ··· 305 383 306 384 reset_control_assert(eqos->rst); 307 385 gpiod_set_value(eqos->reset, 1); 308 - clk_disable_unprepare(eqos->clk_tx); 309 - clk_disable_unprepare(eqos->clk_rx); 310 - clk_disable_unprepare(eqos->clk_slave); 311 - clk_disable_unprepare(eqos->clk_master); 312 386 } 313 387 314 388 struct dwc_eth_dwmac_data { ··· 316 398 317 399 static const struct dwc_eth_dwmac_data dwc_qos_data = { 318 400 .probe = dwc_qos_probe, 319 - .remove = dwc_qos_remove, 320 401 }; 321 402 322 403 static const struct dwc_eth_dwmac_data tegra_eqos_data = { ··· 351 434 if (IS_ERR(plat_dat)) 352 435 return PTR_ERR(plat_dat); 353 436 437 + ret = devm_clk_bulk_get_all(&pdev->dev, &plat_dat->clks); 438 + if (ret < 0) 439 + return dev_err_probe(&pdev->dev, ret, "Failed to retrieve all required clocks\n"); 440 + plat_dat->num_clks = ret; 441 + 442 + ret = clk_bulk_prepare_enable(plat_dat->num_clks, plat_dat->clks); 443 + if (ret) 444 + return dev_err_probe(&pdev->dev, ret, "Failed to enable clocks\n"); 445 + 354 446 ret = data->probe(pdev, plat_dat, &stmmac_res); 355 447 if (ret < 0) { 356 448 dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n"); 449 + clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks); 357 450 return ret; 358 451 } 359 452 ··· 378 451 return ret; 379 452 380 453 remove: 381 - data->remove(pdev); 454 + if (data->remove) 455 + data->remove(pdev); 382 456 383 457 return ret; 384 458 } ··· 387 459 static void dwc_eth_dwmac_remove(struct platform_device *pdev) 388 460 { 389 461 const struct dwc_eth_dwmac_data *data = device_get_match_data(&pdev->dev); 462 + struct plat_stmmacenet_data *plat_data = dev_get_platdata(&pdev->dev); 390 463 391 464 stmmac_dvr_remove(&pdev->dev); 392 465 393 - data->remove(pdev); 466 + if (data->remove) 467 + data->remove(pdev); 468 + 469 + if (plat_data) 470 + clk_bulk_disable_unprepare(plat_data->num_clks, plat_data->clks); 394 471 } 395 472 396 473 static const struct of_device_id dwc_eth_dwmac_match[] = {
+2
include/linux/stmmac.h
··· 254 254 struct clk *clk_ptp_ref; 255 255 unsigned long clk_ptp_rate; 256 256 unsigned long clk_ref_rate; 257 + struct clk_bulk_data *clks; 258 + int num_clks; 257 259 unsigned int mult_fact_100ns; 258 260 s32 ptp_max_adj; 259 261 u32 cdc_error_adj;