1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU 4 * 5 * Copyright (C) STMicroelectronics SA 2017 6 * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics. 7 */ 8 9#include <linux/clk.h> 10#include <linux/kernel.h> 11#include <linux/mfd/syscon.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <linux/of_device.h> 15#include <linux/of_net.h> 16#include <linux/phy.h> 17#include <linux/platform_device.h> 18#include <linux/pm_wakeirq.h> 19#include <linux/regmap.h> 20#include <linux/slab.h> 21#include <linux/stmmac.h> 22 23#include "stmmac_platform.h" 24 25#define SYSCFG_MCU_ETH_MASK BIT(23) 26#define SYSCFG_MP1_ETH_MASK GENMASK(23, 16) 27#define SYSCFG_PMCCLRR_OFFSET 0x40 28 29#define SYSCFG_PMCR_ETH_CLK_SEL BIT(16) 30#define SYSCFG_PMCR_ETH_REF_CLK_SEL BIT(17) 31 32/* CLOCK feed to PHY*/ 33#define ETH_CK_F_25M 25000000 34#define ETH_CK_F_50M 50000000 35#define ETH_CK_F_125M 125000000 36 37/* Ethernet PHY interface selection in register SYSCFG Configuration 38 *------------------------------------------ 39 * src |BIT(23)| BIT(22)| BIT(21)|BIT(20)| 40 *------------------------------------------ 41 * MII | 0 | 0 | 0 | 1 | 42 *------------------------------------------ 43 * GMII | 0 | 0 | 0 | 0 | 44 *------------------------------------------ 45 * RGMII | 0 | 0 | 1 | n/a | 46 *------------------------------------------ 47 * RMII | 1 | 0 | 0 | n/a | 48 *------------------------------------------ 49 */ 50#define SYSCFG_PMCR_ETH_SEL_MII BIT(20) 51#define SYSCFG_PMCR_ETH_SEL_RGMII BIT(21) 52#define SYSCFG_PMCR_ETH_SEL_RMII BIT(23) 53#define SYSCFG_PMCR_ETH_SEL_GMII 0 54#define SYSCFG_MCU_ETH_SEL_MII 0 55#define SYSCFG_MCU_ETH_SEL_RMII 1 56 57/* STM32MP1 register definitions 58 * 59 * Below table summarizes the clock requirement and clock sources for 60 * supported phy interface modes. 61 * __________________________________________________________________________ 62 *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY| 63 *| | | 25MHz | 50MHz | | 64 * --------------------------------------------------------------------------- 65 *| MII | - | eth-ck | n/a | n/a | 66 *| | | st,ext-phyclk | | | 67 * --------------------------------------------------------------------------- 68 *| GMII | - | eth-ck | n/a | n/a | 69 *| | | st,ext-phyclk | | | 70 * --------------------------------------------------------------------------- 71 *| RGMII | - | eth-ck | n/a | eth-ck | 72 *| | | st,ext-phyclk | | st,eth-clk-sel or| 73 *| | | | | st,ext-phyclk | 74 * --------------------------------------------------------------------------- 75 *| RMII | - | eth-ck | eth-ck | n/a | 76 *| | | st,ext-phyclk | st,eth-ref-clk-sel | | 77 *| | | | or st,ext-phyclk | | 78 * --------------------------------------------------------------------------- 79 * 80 */ 81 82struct stm32_dwmac { 83 struct clk *clk_tx; 84 struct clk *clk_rx; 85 struct clk *clk_eth_ck; 86 struct clk *clk_ethstp; 87 struct clk *syscfg_clk; 88 int ext_phyclk; 89 int enable_eth_ck; 90 int eth_clk_sel_reg; 91 int eth_ref_clk_sel_reg; 92 int irq_pwr_wakeup; 93 u32 mode_reg; /* MAC glue-logic mode register */ 94 struct regmap *regmap; 95 u32 speed; 96 const struct stm32_ops *ops; 97 struct device *dev; 98}; 99 100struct stm32_ops { 101 int (*set_mode)(struct plat_stmmacenet_data *plat_dat); 102 int (*clk_prepare)(struct stm32_dwmac *dwmac, bool prepare); 103 int (*suspend)(struct stm32_dwmac *dwmac); 104 void (*resume)(struct stm32_dwmac *dwmac); 105 int (*parse_data)(struct stm32_dwmac *dwmac, 106 struct device *dev); 107 u32 syscfg_eth_mask; 108 bool clk_rx_enable_in_suspend; 109}; 110 111static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) 112{ 113 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; 114 int ret; 115 116 if (dwmac->ops->set_mode) { 117 ret = dwmac->ops->set_mode(plat_dat); 118 if (ret) 119 return ret; 120 } 121 122 ret = clk_prepare_enable(dwmac->clk_tx); 123 if (ret) 124 return ret; 125 126 if (!dwmac->ops->clk_rx_enable_in_suspend || 127 !dwmac->dev->power.is_suspended) { 128 ret = clk_prepare_enable(dwmac->clk_rx); 129 if (ret) { 130 clk_disable_unprepare(dwmac->clk_tx); 131 return ret; 132 } 133 } 134 135 if (dwmac->ops->clk_prepare) { 136 ret = dwmac->ops->clk_prepare(dwmac, true); 137 if (ret) { 138 clk_disable_unprepare(dwmac->clk_rx); 139 clk_disable_unprepare(dwmac->clk_tx); 140 } 141 } 142 143 return ret; 144} 145 146static int stm32mp1_clk_prepare(struct stm32_dwmac *dwmac, bool prepare) 147{ 148 int ret = 0; 149 150 if (prepare) { 151 ret = clk_prepare_enable(dwmac->syscfg_clk); 152 if (ret) 153 return ret; 154 if (dwmac->enable_eth_ck) { 155 ret = clk_prepare_enable(dwmac->clk_eth_ck); 156 if (ret) { 157 clk_disable_unprepare(dwmac->syscfg_clk); 158 return ret; 159 } 160 } 161 } else { 162 clk_disable_unprepare(dwmac->syscfg_clk); 163 if (dwmac->enable_eth_ck) 164 clk_disable_unprepare(dwmac->clk_eth_ck); 165 } 166 return ret; 167} 168 169static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) 170{ 171 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; 172 u32 reg = dwmac->mode_reg, clk_rate; 173 int val; 174 175 clk_rate = clk_get_rate(dwmac->clk_eth_ck); 176 dwmac->enable_eth_ck = false; 177 switch (plat_dat->interface) { 178 case PHY_INTERFACE_MODE_MII: 179 if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk) 180 dwmac->enable_eth_ck = true; 181 val = SYSCFG_PMCR_ETH_SEL_MII; 182 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); 183 break; 184 case PHY_INTERFACE_MODE_GMII: 185 val = SYSCFG_PMCR_ETH_SEL_GMII; 186 if (clk_rate == ETH_CK_F_25M && 187 (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) { 188 dwmac->enable_eth_ck = true; 189 val |= SYSCFG_PMCR_ETH_CLK_SEL; 190 } 191 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n"); 192 break; 193 case PHY_INTERFACE_MODE_RMII: 194 val = SYSCFG_PMCR_ETH_SEL_RMII; 195 if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_50M) && 196 (dwmac->eth_ref_clk_sel_reg || dwmac->ext_phyclk)) { 197 dwmac->enable_eth_ck = true; 198 val |= SYSCFG_PMCR_ETH_REF_CLK_SEL; 199 } 200 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); 201 break; 202 case PHY_INTERFACE_MODE_RGMII: 203 case PHY_INTERFACE_MODE_RGMII_ID: 204 case PHY_INTERFACE_MODE_RGMII_RXID: 205 case PHY_INTERFACE_MODE_RGMII_TXID: 206 val = SYSCFG_PMCR_ETH_SEL_RGMII; 207 if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_125M) && 208 (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) { 209 dwmac->enable_eth_ck = true; 210 val |= SYSCFG_PMCR_ETH_CLK_SEL; 211 } 212 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n"); 213 break; 214 default: 215 pr_debug("SYSCFG init : Do not manage %d interface\n", 216 plat_dat->interface); 217 /* Do not manage others interfaces */ 218 return -EINVAL; 219 } 220 221 /* Need to update PMCCLRR (clear register) */ 222 regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET, 223 dwmac->ops->syscfg_eth_mask); 224 225 /* Update PMCSETR (set register) */ 226 return regmap_update_bits(dwmac->regmap, reg, 227 dwmac->ops->syscfg_eth_mask, val); 228} 229 230static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) 231{ 232 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; 233 u32 reg = dwmac->mode_reg; 234 int val; 235 236 switch (plat_dat->interface) { 237 case PHY_INTERFACE_MODE_MII: 238 val = SYSCFG_MCU_ETH_SEL_MII; 239 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); 240 break; 241 case PHY_INTERFACE_MODE_RMII: 242 val = SYSCFG_MCU_ETH_SEL_RMII; 243 pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); 244 break; 245 default: 246 pr_debug("SYSCFG init : Do not manage %d interface\n", 247 plat_dat->interface); 248 /* Do not manage others interfaces */ 249 return -EINVAL; 250 } 251 252 return regmap_update_bits(dwmac->regmap, reg, 253 dwmac->ops->syscfg_eth_mask, val << 23); 254} 255 256static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac) 257{ 258 clk_disable_unprepare(dwmac->clk_tx); 259 clk_disable_unprepare(dwmac->clk_rx); 260 261 if (dwmac->ops->clk_prepare) 262 dwmac->ops->clk_prepare(dwmac, false); 263} 264 265static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, 266 struct device *dev) 267{ 268 struct device_node *np = dev->of_node; 269 int err; 270 271 /* Get TX/RX clocks */ 272 dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx"); 273 if (IS_ERR(dwmac->clk_tx)) { 274 dev_err(dev, "No ETH Tx clock provided...\n"); 275 return PTR_ERR(dwmac->clk_tx); 276 } 277 278 dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx"); 279 if (IS_ERR(dwmac->clk_rx)) { 280 dev_err(dev, "No ETH Rx clock provided...\n"); 281 return PTR_ERR(dwmac->clk_rx); 282 } 283 284 if (dwmac->ops->parse_data) { 285 err = dwmac->ops->parse_data(dwmac, dev); 286 if (err) 287 return err; 288 } 289 290 /* Get mode register */ 291 dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); 292 if (IS_ERR(dwmac->regmap)) 293 return PTR_ERR(dwmac->regmap); 294 295 err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg); 296 if (err) 297 dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err); 298 299 return err; 300} 301 302static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, 303 struct device *dev) 304{ 305 struct platform_device *pdev = to_platform_device(dev); 306 struct device_node *np = dev->of_node; 307 int err = 0; 308 309 /* Ethernet PHY have no crystal */ 310 dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); 311 312 /* Gigabit Ethernet 125MHz clock selection. */ 313 dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel"); 314 315 /* Ethernet 50Mhz RMII clock selection */ 316 dwmac->eth_ref_clk_sel_reg = 317 of_property_read_bool(np, "st,eth-ref-clk-sel"); 318 319 /* Get ETH_CLK clocks */ 320 dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); 321 if (IS_ERR(dwmac->clk_eth_ck)) { 322 dev_info(dev, "No phy clock provided...\n"); 323 dwmac->clk_eth_ck = NULL; 324 } 325 326 /* Clock used for low power mode */ 327 dwmac->clk_ethstp = devm_clk_get(dev, "ethstp"); 328 if (IS_ERR(dwmac->clk_ethstp)) { 329 dev_err(dev, 330 "No ETH peripheral clock provided for CStop mode ...\n"); 331 return PTR_ERR(dwmac->clk_ethstp); 332 } 333 334 /* Optional Clock for sysconfig */ 335 dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk"); 336 if (IS_ERR(dwmac->syscfg_clk)) 337 dwmac->syscfg_clk = NULL; 338 339 /* Get IRQ information early to have an ability to ask for deferred 340 * probe if needed before we went too far with resource allocation. 341 */ 342 dwmac->irq_pwr_wakeup = platform_get_irq_byname_optional(pdev, 343 "stm32_pwr_wakeup"); 344 if (dwmac->irq_pwr_wakeup == -EPROBE_DEFER) 345 return -EPROBE_DEFER; 346 347 if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) { 348 err = device_init_wakeup(&pdev->dev, true); 349 if (err) { 350 dev_err(&pdev->dev, "Failed to init wake up irq\n"); 351 return err; 352 } 353 err = dev_pm_set_dedicated_wake_irq(&pdev->dev, 354 dwmac->irq_pwr_wakeup); 355 if (err) { 356 dev_err(&pdev->dev, "Failed to set wake up irq\n"); 357 device_init_wakeup(&pdev->dev, false); 358 } 359 device_set_wakeup_enable(&pdev->dev, false); 360 } 361 return err; 362} 363 364static int stm32_dwmac_probe(struct platform_device *pdev) 365{ 366 struct plat_stmmacenet_data *plat_dat; 367 struct stmmac_resources stmmac_res; 368 struct stm32_dwmac *dwmac; 369 const struct stm32_ops *data; 370 int ret; 371 372 ret = stmmac_get_platform_resources(pdev, &stmmac_res); 373 if (ret) 374 return ret; 375 376 plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 377 if (IS_ERR(plat_dat)) 378 return PTR_ERR(plat_dat); 379 380 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); 381 if (!dwmac) { 382 ret = -ENOMEM; 383 goto err_remove_config_dt; 384 } 385 386 data = of_device_get_match_data(&pdev->dev); 387 if (!data) { 388 dev_err(&pdev->dev, "no of match data provided\n"); 389 ret = -EINVAL; 390 goto err_remove_config_dt; 391 } 392 393 dwmac->ops = data; 394 dwmac->dev = &pdev->dev; 395 396 ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); 397 if (ret) { 398 dev_err(&pdev->dev, "Unable to parse OF data\n"); 399 goto err_remove_config_dt; 400 } 401 402 plat_dat->bsp_priv = dwmac; 403 404 ret = stm32_dwmac_init(plat_dat); 405 if (ret) 406 goto err_remove_config_dt; 407 408 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 409 if (ret) 410 goto err_clk_disable; 411 412 return 0; 413 414err_clk_disable: 415 stm32_dwmac_clk_disable(dwmac); 416err_remove_config_dt: 417 stmmac_remove_config_dt(pdev, plat_dat); 418 419 return ret; 420} 421 422static int stm32_dwmac_remove(struct platform_device *pdev) 423{ 424 struct net_device *ndev = platform_get_drvdata(pdev); 425 struct stmmac_priv *priv = netdev_priv(ndev); 426 int ret = stmmac_dvr_remove(&pdev->dev); 427 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; 428 429 stm32_dwmac_clk_disable(priv->plat->bsp_priv); 430 431 if (dwmac->irq_pwr_wakeup >= 0) { 432 dev_pm_clear_wake_irq(&pdev->dev); 433 device_init_wakeup(&pdev->dev, false); 434 } 435 436 return ret; 437} 438 439static int stm32mp1_suspend(struct stm32_dwmac *dwmac) 440{ 441 int ret = 0; 442 443 ret = clk_prepare_enable(dwmac->clk_ethstp); 444 if (ret) 445 return ret; 446 447 clk_disable_unprepare(dwmac->clk_tx); 448 clk_disable_unprepare(dwmac->syscfg_clk); 449 if (dwmac->enable_eth_ck) 450 clk_disable_unprepare(dwmac->clk_eth_ck); 451 452 return ret; 453} 454 455static void stm32mp1_resume(struct stm32_dwmac *dwmac) 456{ 457 clk_disable_unprepare(dwmac->clk_ethstp); 458} 459 460static int stm32mcu_suspend(struct stm32_dwmac *dwmac) 461{ 462 clk_disable_unprepare(dwmac->clk_tx); 463 clk_disable_unprepare(dwmac->clk_rx); 464 465 return 0; 466} 467 468#ifdef CONFIG_PM_SLEEP 469static int stm32_dwmac_suspend(struct device *dev) 470{ 471 struct net_device *ndev = dev_get_drvdata(dev); 472 struct stmmac_priv *priv = netdev_priv(ndev); 473 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; 474 475 int ret; 476 477 ret = stmmac_suspend(dev); 478 479 if (dwmac->ops->suspend) 480 ret = dwmac->ops->suspend(dwmac); 481 482 return ret; 483} 484 485static int stm32_dwmac_resume(struct device *dev) 486{ 487 struct net_device *ndev = dev_get_drvdata(dev); 488 struct stmmac_priv *priv = netdev_priv(ndev); 489 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; 490 int ret; 491 492 if (dwmac->ops->resume) 493 dwmac->ops->resume(dwmac); 494 495 ret = stm32_dwmac_init(priv->plat); 496 if (ret) 497 return ret; 498 499 ret = stmmac_resume(dev); 500 501 return ret; 502} 503#endif /* CONFIG_PM_SLEEP */ 504 505static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops, 506 stm32_dwmac_suspend, stm32_dwmac_resume); 507 508static struct stm32_ops stm32mcu_dwmac_data = { 509 .set_mode = stm32mcu_set_mode, 510 .suspend = stm32mcu_suspend, 511 .syscfg_eth_mask = SYSCFG_MCU_ETH_MASK 512}; 513 514static struct stm32_ops stm32mp1_dwmac_data = { 515 .set_mode = stm32mp1_set_mode, 516 .clk_prepare = stm32mp1_clk_prepare, 517 .suspend = stm32mp1_suspend, 518 .resume = stm32mp1_resume, 519 .parse_data = stm32mp1_parse_data, 520 .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK, 521 .clk_rx_enable_in_suspend = true 522}; 523 524static const struct of_device_id stm32_dwmac_match[] = { 525 { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data}, 526 { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data}, 527 { } 528}; 529MODULE_DEVICE_TABLE(of, stm32_dwmac_match); 530 531static struct platform_driver stm32_dwmac_driver = { 532 .probe = stm32_dwmac_probe, 533 .remove = stm32_dwmac_remove, 534 .driver = { 535 .name = "stm32-dwmac", 536 .pm = &stm32_dwmac_pm_ops, 537 .of_match_table = stm32_dwmac_match, 538 }, 539}; 540module_platform_driver(stm32_dwmac_driver); 541 542MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@gmail.com>"); 543MODULE_AUTHOR("Christophe Roullier <christophe.roullier@st.com>"); 544MODULE_DESCRIPTION("STMicroelectronics STM32 DWMAC Specific Glue layer"); 545MODULE_LICENSE("GPL v2"); 546