Lines Matching +full:stm32 +full:- +full:dwmac

1 // SPDX-License-Identifier: GPL-2.0-only
3 * dwmac-stm32.c - DWMAC Specific Glue layer for STM32 MCU
37 *------------------------------------------
39 *------------------------------------------
41 *------------------------------------------
43 *------------------------------------------
45 *------------------------------------------
47 *------------------------------------------
63 * ---------------------------------------------------------------------------
64 *| MII | - | eth-ck | n/a | n/a |
65 *| | | st,ext-phyclk | | |
66 * ---------------------------------------------------------------------------
67 *| GMII | - | eth-ck | n/a | n/a |
68 *| | | st,ext-phyclk | | |
69 * ---------------------------------------------------------------------------
70 *| RGMII | - | eth-ck | n/a | eth-ck |
71 *| | | st,ext-phyclk | | st,eth-clk-sel or|
72 *| | | | | st,ext-phyclk |
73 * ---------------------------------------------------------------------------
74 *| RMII | - | eth-ck | eth-ck | n/a |
75 *| | | st,ext-phyclk | st,eth-ref-clk-sel | |
76 *| | | | or st,ext-phyclk | |
77 * ---------------------------------------------------------------------------
92 u32 mode_reg; /* MAC glue-logic mode register */
101 int (*suspend)(struct stm32_dwmac *dwmac);
102 void (*resume)(struct stm32_dwmac *dwmac);
103 int (*parse_data)(struct stm32_dwmac *dwmac,
109 static int stm32_dwmac_clk_enable(struct stm32_dwmac *dwmac, bool resume) in stm32_dwmac_clk_enable() argument
113 ret = clk_prepare_enable(dwmac->clk_tx); in stm32_dwmac_clk_enable()
117 if (!dwmac->ops->clk_rx_enable_in_suspend || !resume) { in stm32_dwmac_clk_enable()
118 ret = clk_prepare_enable(dwmac->clk_rx); in stm32_dwmac_clk_enable()
123 ret = clk_prepare_enable(dwmac->syscfg_clk); in stm32_dwmac_clk_enable()
127 if (dwmac->enable_eth_ck) { in stm32_dwmac_clk_enable()
128 ret = clk_prepare_enable(dwmac->clk_eth_ck); in stm32_dwmac_clk_enable()
136 clk_disable_unprepare(dwmac->syscfg_clk); in stm32_dwmac_clk_enable()
138 if (!dwmac->ops->clk_rx_enable_in_suspend || !resume) in stm32_dwmac_clk_enable()
139 clk_disable_unprepare(dwmac->clk_rx); in stm32_dwmac_clk_enable()
141 clk_disable_unprepare(dwmac->clk_tx); in stm32_dwmac_clk_enable()
148 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32_dwmac_init() local
151 if (dwmac->ops->set_mode) { in stm32_dwmac_init()
152 ret = dwmac->ops->set_mode(plat_dat); in stm32_dwmac_init()
157 return stm32_dwmac_clk_enable(dwmac, resume); in stm32_dwmac_init()
162 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mp1_set_mode() local
163 u32 reg = dwmac->mode_reg, clk_rate; in stm32mp1_set_mode()
166 clk_rate = clk_get_rate(dwmac->clk_eth_ck); in stm32mp1_set_mode()
167 dwmac->enable_eth_ck = false; in stm32mp1_set_mode()
168 switch (plat_dat->mac_interface) { in stm32mp1_set_mode()
170 if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk) in stm32mp1_set_mode()
171 dwmac->enable_eth_ck = true; in stm32mp1_set_mode()
178 (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) { in stm32mp1_set_mode()
179 dwmac->enable_eth_ck = true; in stm32mp1_set_mode()
187 (dwmac->eth_ref_clk_sel_reg || dwmac->ext_phyclk)) { in stm32mp1_set_mode()
188 dwmac->enable_eth_ck = true; in stm32mp1_set_mode()
199 (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) { in stm32mp1_set_mode()
200 dwmac->enable_eth_ck = true; in stm32mp1_set_mode()
207 plat_dat->mac_interface); in stm32mp1_set_mode()
209 return -EINVAL; in stm32mp1_set_mode()
213 regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET, in stm32mp1_set_mode()
214 dwmac->ops->syscfg_eth_mask); in stm32mp1_set_mode()
217 return regmap_update_bits(dwmac->regmap, reg, in stm32mp1_set_mode()
218 dwmac->ops->syscfg_eth_mask, val); in stm32mp1_set_mode()
223 struct stm32_dwmac *dwmac = plat_dat->bsp_priv; in stm32mcu_set_mode() local
224 u32 reg = dwmac->mode_reg; in stm32mcu_set_mode()
227 switch (plat_dat->mac_interface) { in stm32mcu_set_mode()
238 plat_dat->mac_interface); in stm32mcu_set_mode()
240 return -EINVAL; in stm32mcu_set_mode()
243 return regmap_update_bits(dwmac->regmap, reg, in stm32mcu_set_mode()
244 dwmac->ops->syscfg_eth_mask, val << 23); in stm32mcu_set_mode()
247 static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac, bool suspend) in stm32_dwmac_clk_disable() argument
249 clk_disable_unprepare(dwmac->clk_tx); in stm32_dwmac_clk_disable()
250 if (!dwmac->ops->clk_rx_enable_in_suspend || !suspend) in stm32_dwmac_clk_disable()
251 clk_disable_unprepare(dwmac->clk_rx); in stm32_dwmac_clk_disable()
253 clk_disable_unprepare(dwmac->syscfg_clk); in stm32_dwmac_clk_disable()
254 if (dwmac->enable_eth_ck) in stm32_dwmac_clk_disable()
255 clk_disable_unprepare(dwmac->clk_eth_ck); in stm32_dwmac_clk_disable()
258 static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, in stm32_dwmac_parse_data() argument
261 struct device_node *np = dev->of_node; in stm32_dwmac_parse_data()
265 dwmac->clk_tx = devm_clk_get(dev, "mac-clk-tx"); in stm32_dwmac_parse_data()
266 if (IS_ERR(dwmac->clk_tx)) { in stm32_dwmac_parse_data()
268 return PTR_ERR(dwmac->clk_tx); in stm32_dwmac_parse_data()
271 dwmac->clk_rx = devm_clk_get(dev, "mac-clk-rx"); in stm32_dwmac_parse_data()
272 if (IS_ERR(dwmac->clk_rx)) { in stm32_dwmac_parse_data()
274 return PTR_ERR(dwmac->clk_rx); in stm32_dwmac_parse_data()
277 if (dwmac->ops->parse_data) { in stm32_dwmac_parse_data()
278 err = dwmac->ops->parse_data(dwmac, dev); in stm32_dwmac_parse_data()
284 dwmac->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscon"); in stm32_dwmac_parse_data()
285 if (IS_ERR(dwmac->regmap)) in stm32_dwmac_parse_data()
286 return PTR_ERR(dwmac->regmap); in stm32_dwmac_parse_data()
288 err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg); in stm32_dwmac_parse_data()
295 static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, in stm32mp1_parse_data() argument
299 struct device_node *np = dev->of_node; in stm32mp1_parse_data()
303 dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); in stm32mp1_parse_data()
306 dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel"); in stm32mp1_parse_data()
309 dwmac->eth_ref_clk_sel_reg = in stm32mp1_parse_data()
310 of_property_read_bool(np, "st,eth-ref-clk-sel"); in stm32mp1_parse_data()
313 dwmac->clk_eth_ck = devm_clk_get(dev, "eth-ck"); in stm32mp1_parse_data()
314 if (IS_ERR(dwmac->clk_eth_ck)) { in stm32mp1_parse_data()
316 dwmac->clk_eth_ck = NULL; in stm32mp1_parse_data()
320 dwmac->clk_ethstp = devm_clk_get(dev, "ethstp"); in stm32mp1_parse_data()
321 if (IS_ERR(dwmac->clk_ethstp)) { in stm32mp1_parse_data()
324 return PTR_ERR(dwmac->clk_ethstp); in stm32mp1_parse_data()
328 dwmac->syscfg_clk = devm_clk_get(dev, "syscfg-clk"); in stm32mp1_parse_data()
329 if (IS_ERR(dwmac->syscfg_clk)) in stm32mp1_parse_data()
330 dwmac->syscfg_clk = NULL; in stm32mp1_parse_data()
335 dwmac->irq_pwr_wakeup = platform_get_irq_byname_optional(pdev, in stm32mp1_parse_data()
337 if (dwmac->irq_pwr_wakeup == -EPROBE_DEFER) in stm32mp1_parse_data()
338 return -EPROBE_DEFER; in stm32mp1_parse_data()
340 if (!dwmac->clk_eth_ck && dwmac->irq_pwr_wakeup >= 0) { in stm32mp1_parse_data()
341 err = device_init_wakeup(&pdev->dev, true); in stm32mp1_parse_data()
343 dev_err(&pdev->dev, "Failed to init wake up irq\n"); in stm32mp1_parse_data()
346 err = dev_pm_set_dedicated_wake_irq(&pdev->dev, in stm32mp1_parse_data()
347 dwmac->irq_pwr_wakeup); in stm32mp1_parse_data()
349 dev_err(&pdev->dev, "Failed to set wake up irq\n"); in stm32mp1_parse_data()
350 device_init_wakeup(&pdev->dev, false); in stm32mp1_parse_data()
352 device_set_wakeup_enable(&pdev->dev, false); in stm32mp1_parse_data()
361 struct stm32_dwmac *dwmac; in stm32_dwmac_probe() local
373 dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); in stm32_dwmac_probe()
374 if (!dwmac) in stm32_dwmac_probe()
375 return -ENOMEM; in stm32_dwmac_probe()
377 data = of_device_get_match_data(&pdev->dev); in stm32_dwmac_probe()
379 dev_err(&pdev->dev, "no of match data provided\n"); in stm32_dwmac_probe()
380 return -EINVAL; in stm32_dwmac_probe()
383 dwmac->ops = data; in stm32_dwmac_probe()
384 dwmac->dev = &pdev->dev; in stm32_dwmac_probe()
386 ret = stm32_dwmac_parse_data(dwmac, &pdev->dev); in stm32_dwmac_probe()
388 dev_err(&pdev->dev, "Unable to parse OF data\n"); in stm32_dwmac_probe()
392 plat_dat->bsp_priv = dwmac; in stm32_dwmac_probe()
398 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); in stm32_dwmac_probe()
405 stm32_dwmac_clk_disable(dwmac, false); in stm32_dwmac_probe()
414 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; in stm32_dwmac_remove() local
416 stmmac_dvr_remove(&pdev->dev); in stm32_dwmac_remove()
418 stm32_dwmac_clk_disable(dwmac, false); in stm32_dwmac_remove()
420 if (dwmac->irq_pwr_wakeup >= 0) { in stm32_dwmac_remove()
421 dev_pm_clear_wake_irq(&pdev->dev); in stm32_dwmac_remove()
422 device_init_wakeup(&pdev->dev, false); in stm32_dwmac_remove()
426 static int stm32mp1_suspend(struct stm32_dwmac *dwmac) in stm32mp1_suspend() argument
428 return clk_prepare_enable(dwmac->clk_ethstp); in stm32mp1_suspend()
431 static void stm32mp1_resume(struct stm32_dwmac *dwmac) in stm32mp1_resume() argument
433 clk_disable_unprepare(dwmac->clk_ethstp); in stm32mp1_resume()
441 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; in stm32_dwmac_suspend() local
449 stm32_dwmac_clk_disable(dwmac, true); in stm32_dwmac_suspend()
451 if (dwmac->ops->suspend) in stm32_dwmac_suspend()
452 ret = dwmac->ops->suspend(dwmac); in stm32_dwmac_suspend()
461 struct stm32_dwmac *dwmac = priv->plat->bsp_priv; in stm32_dwmac_resume() local
464 if (dwmac->ops->resume) in stm32_dwmac_resume()
465 dwmac->ops->resume(dwmac); in stm32_dwmac_resume()
467 ret = stm32_dwmac_init(priv->plat, true); in stm32_dwmac_resume()
495 { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data},
496 { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data},
505 .name = "stm32-dwmac",
514 MODULE_DESCRIPTION("STMicroelectronics STM32 DWMAC Specific Glue layer");