Lines Matching +full:hs +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0
3 * STMicroelectronics STM32 USB PHY Controller driver
10 #include <linux/clk-provider.h>
16 #include <linux/phy/phy.h>
137 struct phy *phy; member
173 ret = regulator_enable(usbphyc->vdda1v1); in stm32_usbphyc_regulators_enable()
177 ret = regulator_enable(usbphyc->vdda1v8); in stm32_usbphyc_regulators_enable()
184 regulator_disable(usbphyc->vdda1v1); in stm32_usbphyc_regulators_enable()
193 ret = regulator_disable(usbphyc->vdda1v8); in stm32_usbphyc_regulators_disable()
197 ret = regulator_disable(usbphyc->vdda1v1); in stm32_usbphyc_regulators_disable()
217 * <=> PLLFRACIN = ((FVCO / (INFF*2)) - PLLNDIV) * 2^16 in stm32_usbphyc_get_pll_params()
223 pll_params->ndiv = (u8)ndiv; in stm32_usbphyc_get_pll_params()
227 frac = frac - (ndiv * (1 << 16)); in stm32_usbphyc_get_pll_params()
228 pll_params->frac = (u16)frac; in stm32_usbphyc_get_pll_params()
234 u32 clk_rate = clk_get_rate(usbphyc->clk); in stm32_usbphyc_pll_init()
240 dev_err(usbphyc->dev, "input clk freq (%dHz) out of range\n", in stm32_usbphyc_pll_init()
242 return -EINVAL; in stm32_usbphyc_pll_init()
254 writel_relaxed(usbphyc_pll, usbphyc->base + STM32_USBPHYC_PLL); in stm32_usbphyc_pll_init()
256 dev_dbg(usbphyc->dev, "input clk freq=%dHz, ndiv=%lu, frac=%lu\n", in stm32_usbphyc_pll_init()
265 void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; in __stm32_usbphyc_pll_disable()
272 dev_err(usbphyc->dev, "PLL not reset\n"); in __stm32_usbphyc_pll_disable()
279 /* Check if a phy port is still active or clk48 in use */ in stm32_usbphyc_pll_disable()
280 if (atomic_dec_return(&usbphyc->n_pll_cons) > 0) in stm32_usbphyc_pll_disable()
288 void __iomem *pll_reg = usbphyc->base + STM32_USBPHYC_PLL; in stm32_usbphyc_pll_enable()
293 * Check if a phy port or clk48 prepare has configured the pll in stm32_usbphyc_pll_enable()
296 if (atomic_inc_return(&usbphyc->n_pll_cons) > 1 && pllen) in stm32_usbphyc_pll_enable()
304 dev_warn(usbphyc->dev, "PLL enabled without known consumers\n"); in stm32_usbphyc_pll_enable()
330 atomic_dec(&usbphyc->n_pll_cons); in stm32_usbphyc_pll_enable()
335 static int stm32_usbphyc_phy_init(struct phy *phy) in stm32_usbphyc_phy_init() argument
337 struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); in stm32_usbphyc_phy_init()
338 struct stm32_usbphyc *usbphyc = usbphyc_phy->usbphyc; in stm32_usbphyc_phy_init()
339 u32 reg_mon = STM32_USBPHYC_MONITOR(usbphyc_phy->index); in stm32_usbphyc_phy_init()
349 /* Check that PLL Lock input to PHY is High */ in stm32_usbphyc_phy_init()
350 writel_relaxed(monsel, usbphyc->base + reg_mon); in stm32_usbphyc_phy_init()
351 ret = readl_relaxed_poll_timeout(usbphyc->base + reg_mon, monout, in stm32_usbphyc_phy_init()
355 dev_err(usbphyc->dev, "PLL Lock input to PHY is Low (val=%x)\n", in stm32_usbphyc_phy_init()
360 usbphyc_phy->active = true; in stm32_usbphyc_phy_init()
370 static int stm32_usbphyc_phy_exit(struct phy *phy) in stm32_usbphyc_phy_exit() argument
372 struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); in stm32_usbphyc_phy_exit()
373 struct stm32_usbphyc *usbphyc = usbphyc_phy->usbphyc; in stm32_usbphyc_phy_exit()
375 usbphyc_phy->active = false; in stm32_usbphyc_phy_exit()
380 static int stm32_usbphyc_phy_power_on(struct phy *phy) in stm32_usbphyc_phy_power_on() argument
382 struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); in stm32_usbphyc_phy_power_on()
384 if (usbphyc_phy->vbus) in stm32_usbphyc_phy_power_on()
385 return regulator_enable(usbphyc_phy->vbus); in stm32_usbphyc_phy_power_on()
390 static int stm32_usbphyc_phy_power_off(struct phy *phy) in stm32_usbphyc_phy_power_off() argument
392 struct stm32_usbphyc_phy *usbphyc_phy = phy_get_drvdata(phy); in stm32_usbphyc_phy_power_off()
394 if (usbphyc_phy->vbus) in stm32_usbphyc_phy_power_off()
395 return regulator_disable(usbphyc_phy->vbus); in stm32_usbphyc_phy_power_off()
437 of_clk_del_provider(usbphyc->dev->of_node); in stm32_usbphyc_clk48_unregister()
438 clk_hw_unregister(&usbphyc->clk48_hw); in stm32_usbphyc_clk48_unregister()
443 struct device_node *node = usbphyc->dev->of_node; in stm32_usbphyc_clk48_register()
450 usbphyc->clk48_hw.init = &init; in stm32_usbphyc_clk48_register()
452 ret = clk_hw_register(usbphyc->dev, &usbphyc->clk48_hw); in stm32_usbphyc_clk48_register()
456 ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &usbphyc->clk48_hw); in stm32_usbphyc_clk48_register()
458 clk_hw_unregister(&usbphyc->clk48_hw); in stm32_usbphyc_clk48_register()
466 struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys[index]; in stm32_usbphyc_phy_tuning()
472 otpcomp = FIELD_GET(OTPCOMP, readl_relaxed(usbphyc->base + reg)); in stm32_usbphyc_phy_tuning()
474 ret = of_property_read_u32(np, "st,current-boost-microamp", &val); in stm32_usbphyc_phy_tuning()
475 if (ret != -EINVAL) { in stm32_usbphyc_phy_tuning()
478 usbphyc_phy->tune |= INCURREN | FIELD_PREP(INCURRINT, val); in stm32_usbphyc_phy_tuning()
480 dev_warn(usbphyc->dev, "phy%d: invalid st,current-boost-microamp\n", index); in stm32_usbphyc_phy_tuning()
484 if (!of_property_read_bool(np, "st,no-lsfs-fb-cap")) in stm32_usbphyc_phy_tuning()
485 usbphyc_phy->tune |= LFSCAPEN; in stm32_usbphyc_phy_tuning()
487 if (of_property_read_bool(np, "st,decrease-hs-slew-rate")) in stm32_usbphyc_phy_tuning()
488 usbphyc_phy->tune |= HSDRVSLEW; in stm32_usbphyc_phy_tuning()
490 ret = of_property_read_u32(np, "st,tune-hs-dc-level", &val); in stm32_usbphyc_phy_tuning()
491 if (ret != -EINVAL) { in stm32_usbphyc_phy_tuning()
493 if (val == DC_MINUS_5_TO_7_MV) {/* Decreases HS driver DC level */ in stm32_usbphyc_phy_tuning()
494 usbphyc_phy->tune |= HSDRVDCCUR; in stm32_usbphyc_phy_tuning()
495 } else if (val > 0) { /* Increases HS driver DC level */ in stm32_usbphyc_phy_tuning()
497 usbphyc_phy->tune |= HSDRVCURINCR | FIELD_PREP(HSDRVDCLEV, val); in stm32_usbphyc_phy_tuning()
500 dev_warn(usbphyc->dev, "phy%d: invalid st,tune-hs-dc-level\n", index); in stm32_usbphyc_phy_tuning()
504 if (of_property_read_bool(np, "st,enable-fs-rftime-tuning")) in stm32_usbphyc_phy_tuning()
505 usbphyc_phy->tune |= FSDRVRFADJ; in stm32_usbphyc_phy_tuning()
507 if (of_property_read_bool(np, "st,enable-hs-rftime-reduction")) in stm32_usbphyc_phy_tuning()
508 usbphyc_phy->tune |= HSDRVRFRED; in stm32_usbphyc_phy_tuning()
510 ret = of_property_read_u32(np, "st,trim-hs-current", &val); in stm32_usbphyc_phy_tuning()
511 if (ret != -EINVAL) { in stm32_usbphyc_phy_tuning()
513 usbphyc_phy->tune |= FIELD_PREP(HSDRVCHKITRM, val); in stm32_usbphyc_phy_tuning()
515 dev_warn(usbphyc->dev, "phy%d: invalid st,trim-hs-current\n", index); in stm32_usbphyc_phy_tuning()
518 ret = of_property_read_u32(np, "st,trim-hs-impedance", &val); in stm32_usbphyc_phy_tuning()
519 if (ret != -EINVAL) { in stm32_usbphyc_phy_tuning()
521 usbphyc_phy->tune |= FIELD_PREP(HSDRVCHKZTRM, val); in stm32_usbphyc_phy_tuning()
523 dev_warn(usbphyc->dev, "phy%d: invalid st,trim-hs-impedance\n", index); in stm32_usbphyc_phy_tuning()
526 ret = of_property_read_u32(np, "st,tune-squelch-level", &val); in stm32_usbphyc_phy_tuning()
527 if (ret != -EINVAL) { in stm32_usbphyc_phy_tuning()
529 usbphyc_phy->tune |= FIELD_PREP(SQLCHCTL, val); in stm32_usbphyc_phy_tuning()
531 dev_warn(usbphyc->dev, "phy%d: invalid st,tune-squelch\n", index); in stm32_usbphyc_phy_tuning()
534 if (of_property_read_bool(np, "st,enable-hs-rx-gain-eq")) in stm32_usbphyc_phy_tuning()
535 usbphyc_phy->tune |= HDRXGNEQEN; in stm32_usbphyc_phy_tuning()
537 ret = of_property_read_u32(np, "st,tune-hs-rx-offset", &val); in stm32_usbphyc_phy_tuning()
538 if (ret != -EINVAL) { in stm32_usbphyc_phy_tuning()
540 usbphyc_phy->tune |= FIELD_PREP(HSRXOFF, val); in stm32_usbphyc_phy_tuning()
542 dev_warn(usbphyc->dev, "phy%d: invalid st,tune-hs-rx-offset\n", index); in stm32_usbphyc_phy_tuning()
545 if (of_property_read_bool(np, "st,no-hs-ftime-ctrl")) in stm32_usbphyc_phy_tuning()
546 usbphyc_phy->tune |= HSFALLPREEM; in stm32_usbphyc_phy_tuning()
548 if (!of_property_read_bool(np, "st,no-lsfs-sc")) in stm32_usbphyc_phy_tuning()
549 usbphyc_phy->tune |= SHTCCTCTLPROT; in stm32_usbphyc_phy_tuning()
551 if (of_property_read_bool(np, "st,enable-hs-tx-staggering")) in stm32_usbphyc_phy_tuning()
552 usbphyc_phy->tune |= STAGSEL; in stm32_usbphyc_phy_tuning()
555 usbphyc_phy->tune |= FIELD_PREP(OTPCOMP, otpcomp); in stm32_usbphyc_phy_tuning()
558 * By default, if no st,xxx tuning property is used, usbphyc_phy->tune is equal to in stm32_usbphyc_phy_tuning()
561 writel_relaxed(usbphyc_phy->tune, usbphyc->base + reg); in stm32_usbphyc_phy_tuning()
568 stm32_usbphyc_clr_bits(usbphyc->base + STM32_USBPHYC_MISC, in stm32_usbphyc_switch_setup()
571 stm32_usbphyc_set_bits(usbphyc->base + STM32_USBPHYC_MISC, in stm32_usbphyc_switch_setup()
573 usbphyc->switch_setup = utmi_switch; in stm32_usbphyc_switch_setup()
576 static struct phy *stm32_usbphyc_of_xlate(struct device *dev, in stm32_usbphyc_of_xlate()
581 struct device_node *phynode = args->np; in stm32_usbphyc_of_xlate()
584 for (port = 0; port < usbphyc->nphys; port++) { in stm32_usbphyc_of_xlate()
585 if (phynode == usbphyc->phys[port]->phy->dev.of_node) { in stm32_usbphyc_of_xlate()
586 usbphyc_phy = usbphyc->phys[port]; in stm32_usbphyc_of_xlate()
591 dev_err(dev, "failed to find phy\n"); in stm32_usbphyc_of_xlate()
592 return ERR_PTR(-EINVAL); in stm32_usbphyc_of_xlate()
595 if (((usbphyc_phy->index == 0) && (args->args_count != 0)) || in stm32_usbphyc_of_xlate()
596 ((usbphyc_phy->index == 1) && (args->args_count != 1))) { in stm32_usbphyc_of_xlate()
597 dev_err(dev, "invalid number of cells for phy port%d\n", in stm32_usbphyc_of_xlate()
598 usbphyc_phy->index); in stm32_usbphyc_of_xlate()
599 return ERR_PTR(-EINVAL); in stm32_usbphyc_of_xlate()
602 /* Configure the UTMI switch for PHY port#2 */ in stm32_usbphyc_of_xlate()
603 if (usbphyc_phy->index == 1) { in stm32_usbphyc_of_xlate()
604 if (usbphyc->switch_setup < 0) { in stm32_usbphyc_of_xlate()
605 stm32_usbphyc_switch_setup(usbphyc, args->args[0]); in stm32_usbphyc_of_xlate()
607 if (args->args[0] != usbphyc->switch_setup) { in stm32_usbphyc_of_xlate()
608 dev_err(dev, "phy port1 already used\n"); in stm32_usbphyc_of_xlate()
609 return ERR_PTR(-EBUSY); in stm32_usbphyc_of_xlate()
614 return usbphyc_phy->phy; in stm32_usbphyc_of_xlate()
620 struct device *dev = &pdev->dev; in stm32_usbphyc_probe()
621 struct device_node *child, *np = dev->of_node; in stm32_usbphyc_probe()
628 return -ENOMEM; in stm32_usbphyc_probe()
629 usbphyc->dev = dev; in stm32_usbphyc_probe()
632 usbphyc->base = devm_platform_ioremap_resource(pdev, 0); in stm32_usbphyc_probe()
633 if (IS_ERR(usbphyc->base)) in stm32_usbphyc_probe()
634 return PTR_ERR(usbphyc->base); in stm32_usbphyc_probe()
636 usbphyc->clk = devm_clk_get(dev, NULL); in stm32_usbphyc_probe()
637 if (IS_ERR(usbphyc->clk)) in stm32_usbphyc_probe()
638 return dev_err_probe(dev, PTR_ERR(usbphyc->clk), "clk get_failed\n"); in stm32_usbphyc_probe()
640 ret = clk_prepare_enable(usbphyc->clk); in stm32_usbphyc_probe()
646 usbphyc->rst = devm_reset_control_get(dev, NULL); in stm32_usbphyc_probe()
647 if (!IS_ERR(usbphyc->rst)) { in stm32_usbphyc_probe()
648 reset_control_assert(usbphyc->rst); in stm32_usbphyc_probe()
650 reset_control_deassert(usbphyc->rst); in stm32_usbphyc_probe()
652 ret = PTR_ERR(usbphyc->rst); in stm32_usbphyc_probe()
653 if (ret == -EPROBE_DEFER) in stm32_usbphyc_probe()
656 stm32_usbphyc_clr_bits(usbphyc->base + STM32_USBPHYC_PLL, PLLEN); in stm32_usbphyc_probe()
663 if (readl_relaxed_poll_timeout(usbphyc->base + STM32_USBPHYC_PLL, in stm32_usbphyc_probe()
665 dev_warn(usbphyc->dev, "PLL not reset\n"); in stm32_usbphyc_probe()
666 ret = -EPROBE_DEFER; in stm32_usbphyc_probe()
670 usbphyc->switch_setup = -EINVAL; in stm32_usbphyc_probe()
671 usbphyc->nphys = of_get_child_count(np); in stm32_usbphyc_probe()
672 usbphyc->phys = devm_kcalloc(dev, usbphyc->nphys, in stm32_usbphyc_probe()
673 sizeof(*usbphyc->phys), GFP_KERNEL); in stm32_usbphyc_probe()
674 if (!usbphyc->phys) { in stm32_usbphyc_probe()
675 ret = -ENOMEM; in stm32_usbphyc_probe()
679 usbphyc->vdda1v1 = devm_regulator_get(dev, "vdda1v1"); in stm32_usbphyc_probe()
680 if (IS_ERR(usbphyc->vdda1v1)) { in stm32_usbphyc_probe()
681 ret = dev_err_probe(dev, PTR_ERR(usbphyc->vdda1v1), in stm32_usbphyc_probe()
686 usbphyc->vdda1v8 = devm_regulator_get(dev, "vdda1v8"); in stm32_usbphyc_probe()
687 if (IS_ERR(usbphyc->vdda1v8)) { in stm32_usbphyc_probe()
688 ret = dev_err_probe(dev, PTR_ERR(usbphyc->vdda1v8), in stm32_usbphyc_probe()
695 struct phy *phy; in stm32_usbphyc_probe() local
698 phy = devm_phy_create(dev, child, &stm32_usbphyc_phy_ops); in stm32_usbphyc_probe()
699 if (IS_ERR(phy)) { in stm32_usbphyc_probe()
700 ret = PTR_ERR(phy); in stm32_usbphyc_probe()
701 if (ret != -EPROBE_DEFER) in stm32_usbphyc_probe()
702 dev_err(dev, "failed to create phy%d: %d\n", in stm32_usbphyc_probe()
710 ret = -ENOMEM; in stm32_usbphyc_probe()
715 if (ret || index > usbphyc->nphys) { in stm32_usbphyc_probe()
716 dev_err(&phy->dev, "invalid reg property: %d\n", ret); in stm32_usbphyc_probe()
718 ret = -EINVAL; in stm32_usbphyc_probe()
722 usbphyc->phys[port] = usbphyc_phy; in stm32_usbphyc_probe()
723 phy_set_bus_width(phy, 8); in stm32_usbphyc_probe()
724 phy_set_drvdata(phy, usbphyc_phy); in stm32_usbphyc_probe()
726 usbphyc->phys[port]->phy = phy; in stm32_usbphyc_probe()
727 usbphyc->phys[port]->usbphyc = usbphyc; in stm32_usbphyc_probe()
728 usbphyc->phys[port]->index = index; in stm32_usbphyc_probe()
729 usbphyc->phys[port]->active = false; in stm32_usbphyc_probe()
731 usbphyc->phys[port]->vbus = devm_regulator_get_optional(&phy->dev, "vbus"); in stm32_usbphyc_probe()
732 if (IS_ERR(usbphyc->phys[port]->vbus)) { in stm32_usbphyc_probe()
733 ret = PTR_ERR(usbphyc->phys[port]->vbus); in stm32_usbphyc_probe()
734 if (ret == -EPROBE_DEFER) in stm32_usbphyc_probe()
736 usbphyc->phys[port]->vbus = NULL; in stm32_usbphyc_probe()
739 /* Configure phy tuning */ in stm32_usbphyc_probe()
749 dev_err(dev, "failed to register phy provider: %d\n", ret); in stm32_usbphyc_probe()
759 version = readl_relaxed(usbphyc->base + STM32_USBPHYC_VERSION); in stm32_usbphyc_probe()
768 clk_disable_unprepare(usbphyc->clk); in stm32_usbphyc_probe()
775 struct stm32_usbphyc *usbphyc = dev_get_drvdata(&pdev->dev); in stm32_usbphyc_remove()
779 for (port = 0; port < usbphyc->nphys; port++) in stm32_usbphyc_remove()
780 if (usbphyc->phys[port]->active) in stm32_usbphyc_remove()
781 stm32_usbphyc_phy_exit(usbphyc->phys[port]->phy); in stm32_usbphyc_remove()
785 clk_disable_unprepare(usbphyc->clk); in stm32_usbphyc_remove()
794 if (usbphyc->switch_setup >= 0) in stm32_usbphyc_resume()
795 stm32_usbphyc_switch_setup(usbphyc, usbphyc->switch_setup); in stm32_usbphyc_resume()
797 for (port = 0; port < usbphyc->nphys; port++) { in stm32_usbphyc_resume()
798 usbphyc_phy = usbphyc->phys[port]; in stm32_usbphyc_resume()
799 writel_relaxed(usbphyc_phy->tune, usbphyc->base + STM32_USBPHYC_TUNE(port)); in stm32_usbphyc_resume()
808 { .compatible = "st,stm32mp1-usbphyc", },
818 .name = "stm32-usbphyc",