Lines Matching +full:irq +full:- +full:syscfg
1 // SPDX-License-Identifier: GPL-2.0-only
3 * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU
36 /* Ethernet PHY interface selection in register SYSCFG Configuration
37 *------------------------------------------
39 *------------------------------------------
41 *------------------------------------------
43 *------------------------------------------
45 *------------------------------------------
47 *------------------------------------------
74 * ---------------------------------------------------------------------------
75 *| MII | - | eth-ck | n/a | n/a |
76 *| | | st,ext-phyclk | | |
77 * ---------------------------------------------------------------------------
78 *| GMII | - | eth-ck | n/a | n/a |
79 *| | | st,ext-phyclk | | |
80 * ---------------------------------------------------------------------------
81 *| RGMII | - | eth-ck | n/a | eth-ck |
82 *| | | st,ext-phyclk | | st,eth-clk-sel or|
83 *| | | | | st,ext-phyclk |
84 * ---------------------------------------------------------------------------
85 *| RMII | - | eth-ck | eth-ck | n/a |
86 *| | | st,ext-phyclk | st,eth-ref-clk-sel | |
87 *| | | | or st,ext-phyclk | |
88 * ---------------------------------------------------------------------------
103 u32 mode_reg; /* MAC glue-logic mode register */
126 ret = clk_prepare_enable(dwmac->clk_tx); in stm32_dwmac_clk_enable()
130 if (!dwmac->ops->clk_rx_enable_in_suspend || !resume) { in stm32_dwmac_clk_enable()
131 ret = clk_prepare_enable(dwmac->clk_rx); in stm32_dwmac_clk_enable()
136 ret = clk_prepare_enable(dwmac->syscfg_clk); in stm32_dwmac_clk_enable()
140 if (dwmac->enable_eth_ck) { in stm32_dwmac_clk_enable()
141 ret = clk_prepare_enable(dwmac->clk_eth_ck); in stm32_dwmac_clk_enable()
149 clk_disable_unprepare(dwmac->syscfg_clk); in stm32_dwmac_clk_enable()
151 if (!dwmac->ops->clk_rx_enable_in_suspend || !resume) in stm32_dwmac_clk_enable()
152 clk_disable_unprepare(dwmac->clk_rx); in stm32_dwmac_clk_enable()
154 clk_disable_unprepare(dwmac->clk_tx); in stm32_dwmac_clk_enable()
161 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32_dwmac_init()
164 if (dwmac->ops->set_mode) { in stm32_dwmac_init()
165 ret = dwmac->ops->set_mode(plat_dat); in stm32_dwmac_init()
175 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mp1_select_ethck_external()
177 switch (plat_dat->mac_interface) { in stm32mp1_select_ethck_external()
179 dwmac->enable_eth_ck = dwmac->ext_phyclk; in stm32mp1_select_ethck_external()
182 dwmac->enable_eth_ck = dwmac->eth_clk_sel_reg || in stm32mp1_select_ethck_external()
183 dwmac->ext_phyclk; in stm32mp1_select_ethck_external()
186 dwmac->enable_eth_ck = dwmac->eth_ref_clk_sel_reg || in stm32mp1_select_ethck_external()
187 dwmac->ext_phyclk; in stm32mp1_select_ethck_external()
193 dwmac->enable_eth_ck = dwmac->eth_clk_sel_reg || in stm32mp1_select_ethck_external()
194 dwmac->ext_phyclk; in stm32mp1_select_ethck_external()
197 dwmac->enable_eth_ck = false; in stm32mp1_select_ethck_external()
198 dev_err(dwmac->dev, "Mode %s not supported", in stm32mp1_select_ethck_external()
199 phy_modes(plat_dat->mac_interface)); in stm32mp1_select_ethck_external()
200 return -EINVAL; in stm32mp1_select_ethck_external()
206 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mp1_validate_ethck_rate()
207 const u32 clk_rate = clk_get_rate(dwmac->clk_eth_ck); in stm32mp1_validate_ethck_rate()
209 if (!dwmac->enable_eth_ck) in stm32mp1_validate_ethck_rate()
212 switch (plat_dat->mac_interface) { in stm32mp1_validate_ethck_rate()
233 dev_err(dwmac->dev, "Mode %s does not match eth-ck frequency %d Hz", in stm32mp1_validate_ethck_rate()
234 phy_modes(plat_dat->mac_interface), clk_rate); in stm32mp1_validate_ethck_rate()
235 return -EINVAL; in stm32mp1_validate_ethck_rate()
240 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mp1_configure_pmcr()
241 u32 reg = dwmac->mode_reg; in stm32mp1_configure_pmcr()
244 switch (plat_dat->mac_interface) { in stm32mp1_configure_pmcr()
252 if (!dwmac->ops->is_mp13) /* Select MII mode on STM32MP15xx */ in stm32mp1_configure_pmcr()
257 if (dwmac->enable_eth_ck) in stm32mp1_configure_pmcr()
262 if (dwmac->enable_eth_ck) in stm32mp1_configure_pmcr()
270 if (dwmac->enable_eth_ck) in stm32mp1_configure_pmcr()
274 dev_err(dwmac->dev, "Mode %s not supported", in stm32mp1_configure_pmcr()
275 phy_modes(plat_dat->mac_interface)); in stm32mp1_configure_pmcr()
277 return -EINVAL; in stm32mp1_configure_pmcr()
280 dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface)); in stm32mp1_configure_pmcr()
283 val <<= ffs(dwmac->mode_mask) - ffs(SYSCFG_MP1_ETH_MASK); in stm32mp1_configure_pmcr()
286 regmap_write(dwmac->regmap, dwmac->ops->syscfg_clr_off, in stm32mp1_configure_pmcr()
287 dwmac->mode_mask); in stm32mp1_configure_pmcr()
290 return regmap_update_bits(dwmac->regmap, reg, in stm32mp1_configure_pmcr()
291 dwmac->mode_mask, val); in stm32mp1_configure_pmcr()
296 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mp2_configure_syscfg()
297 u32 reg = dwmac->mode_reg; in stm32mp2_configure_syscfg()
300 switch (plat_dat->mac_interface) { in stm32mp2_configure_syscfg()
302 /* ETH_REF_CLK_SEL bit in SYSCFG register is not applicable in MII mode */ in stm32mp2_configure_syscfg()
306 if (dwmac->enable_eth_ck) { in stm32mp2_configure_syscfg()
318 if (dwmac->enable_eth_ck) { in stm32mp2_configure_syscfg()
324 dev_err(dwmac->dev, "Mode %s not supported", in stm32mp2_configure_syscfg()
325 phy_modes(plat_dat->mac_interface)); in stm32mp2_configure_syscfg()
327 return -EINVAL; in stm32mp2_configure_syscfg()
330 dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface)); in stm32mp2_configure_syscfg()
336 return regmap_update_bits(dwmac->regmap, reg, in stm32mp2_configure_syscfg()
342 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mp1_set_mode()
353 if (!dwmac->ops->is_mp2) in stm32mp1_set_mode()
361 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mcu_set_mode()
362 u32 reg = dwmac->mode_reg; in stm32mcu_set_mode()
365 switch (plat_dat->mac_interface) { in stm32mcu_set_mode()
373 dev_err(dwmac->dev, "Mode %s not supported", in stm32mcu_set_mode()
374 phy_modes(plat_dat->mac_interface)); in stm32mcu_set_mode()
376 return -EINVAL; in stm32mcu_set_mode()
379 dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface)); in stm32mcu_set_mode()
381 return regmap_update_bits(dwmac->regmap, reg, in stm32mcu_set_mode()
387 clk_disable_unprepare(dwmac->clk_tx); in stm32_dwmac_clk_disable()
388 if (!dwmac->ops->clk_rx_enable_in_suspend || !suspend) in stm32_dwmac_clk_disable()
389 clk_disable_unprepare(dwmac->clk_rx); in stm32_dwmac_clk_disable()
391 clk_disable_unprepare(dwmac->syscfg_clk); in stm32_dwmac_clk_disable()
392 if (dwmac->enable_eth_ck) in stm32_dwmac_clk_disable()
393 clk_disable_unprepare(dwmac->clk_eth_ck); in stm32_dwmac_clk_disable()
399 struct device_node *np = dev->of_node; in stm32_dwmac_parse_data()
403 dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx"); in stm32_dwmac_parse_data()
404 if (IS_ERR(dwmac->clk_tx)) { in stm32_dwmac_parse_data()
406 return PTR_ERR(dwmac->clk_tx); in stm32_dwmac_parse_data()
409 dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx"); in stm32_dwmac_parse_data()
410 if (IS_ERR(dwmac->clk_rx)) { in stm32_dwmac_parse_data()
412 return PTR_ERR(dwmac->clk_rx); in stm32_dwmac_parse_data()
415 if (dwmac->ops->parse_data) { in stm32_dwmac_parse_data()
416 err = dwmac->ops->parse_data(dwmac, dev); in stm32_dwmac_parse_data()
422 dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); in stm32_dwmac_parse_data()
423 if (IS_ERR(dwmac->regmap)) in stm32_dwmac_parse_data()
424 return PTR_ERR(dwmac->regmap); in stm32_dwmac_parse_data()
426 err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg); in stm32_dwmac_parse_data()
432 if (dwmac->ops->is_mp2) in stm32_dwmac_parse_data()
435 dwmac->mode_mask = SYSCFG_MP1_ETH_MASK; in stm32_dwmac_parse_data()
436 err = of_property_read_u32_index(np, "st,syscon", 2, &dwmac->mode_mask); in stm32_dwmac_parse_data()
438 if (dwmac->ops->is_mp13) { in stm32_dwmac_parse_data()
453 struct device_node *np = dev->of_node; in stm32mp1_parse_data()
457 dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); in stm32mp1_parse_data()
460 dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel"); in stm32mp1_parse_data()
463 dwmac->eth_ref_clk_sel_reg = in stm32mp1_parse_data()
464 of_property_read_bool(np, "st,eth-ref-clk-sel"); in stm32mp1_parse_data()
467 dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); in stm32mp1_parse_data()
468 if (IS_ERR(dwmac->clk_eth_ck)) { in stm32mp1_parse_data()
470 dwmac->clk_eth_ck = NULL; in stm32mp1_parse_data()
474 dwmac->clk_ethstp = devm_clk_get(dev, "ethstp"); in stm32mp1_parse_data()
475 if (IS_ERR(dwmac->clk_ethstp)) { in stm32mp1_parse_data()
478 return PTR_ERR(dwmac->clk_ethstp); in stm32mp1_parse_data()
482 dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk"); in stm32mp1_parse_data()
483 if (IS_ERR(dwmac->syscfg_clk)) in stm32mp1_parse_data()
484 dwmac->syscfg_clk = NULL; in stm32mp1_parse_data()
486 /* Get IRQ information early to have an ability to ask for deferred in stm32mp1_parse_data()
489 dwmac->irq_pwr_wakeup = platform_get_irq_byname_optional(pdev, in stm32mp1_parse_data()
491 if (dwmac->irq_pwr_wakeup == -EPROBE_DEFER) in stm32mp1_parse_data()
492 return -EPROBE_DEFER; in stm32mp1_parse_data()
494 if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) { in stm32mp1_parse_data()
495 err = device_init_wakeup(&pdev->dev, true); in stm32mp1_parse_data()
497 dev_err(&pdev->dev, "Failed to init wake up irq\n"); in stm32mp1_parse_data()
500 err = dev_pm_set_dedicated_wake_irq(&pdev->dev, in stm32mp1_parse_data()
501 dwmac->irq_pwr_wakeup); in stm32mp1_parse_data()
503 dev_err(&pdev->dev, "Failed to set wake up irq\n"); in stm32mp1_parse_data()
504 device_init_wakeup(&pdev->dev, false); in stm32mp1_parse_data()
506 device_set_wakeup_enable(&pdev->dev, false); in stm32mp1_parse_data()
527 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); in stm32_dwmac_probe()
529 return -ENOMEM; in stm32_dwmac_probe()
531 data = of_device_get_match_data(&pdev->dev); in stm32_dwmac_probe()
533 dev_err(&pdev->dev, "no of match data provided\n"); in stm32_dwmac_probe()
534 return -EINVAL; in stm32_dwmac_probe()
537 dwmac->ops = data; in stm32_dwmac_probe()
538 dwmac->dev = &pdev->dev; in stm32_dwmac_probe()
540 ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); in stm32_dwmac_probe()
542 dev_err(&pdev->dev, "Unable to parse OF data\n"); in stm32_dwmac_probe()
546 plat_dat->bsp_priv = dwmac; in stm32_dwmac_probe()
552 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); in stm32_dwmac_probe()
568 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; in stm32_dwmac_remove()
570 stmmac_dvr_remove(&pdev->dev); in stm32_dwmac_remove()
574 if (dwmac->irq_pwr_wakeup >= 0) { in stm32_dwmac_remove()
575 dev_pm_clear_wake_irq(&pdev->dev); in stm32_dwmac_remove()
576 device_init_wakeup(&pdev->dev, false); in stm32_dwmac_remove()
582 return clk_prepare_enable(dwmac->clk_ethstp); in stm32mp1_suspend()
587 clk_disable_unprepare(dwmac->clk_ethstp); in stm32mp1_resume()
595 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; in stm32_dwmac_suspend()
605 if (dwmac->ops->suspend) in stm32_dwmac_suspend()
606 ret = dwmac->ops->suspend(dwmac); in stm32_dwmac_suspend()
615 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; in stm32_dwmac_resume()
618 if (dwmac->ops->resume) in stm32_dwmac_resume()
619 dwmac->ops->resume(dwmac); in stm32_dwmac_resume()
621 ret = stm32_dwmac_init(priv->plat, true); in stm32_dwmac_resume()
668 { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data},
669 { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data},
670 { .compatible = "st,stm32mp13-dwmac", .data = &stm32mp13_dwmac_data},
671 { .compatible = "st,stm32mp25-dwmac", .data = &stm32mp25_dwmac_data},
680 .name = "stm32-dwmac",