Lines Matching +full:per +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2021-2022 NXP. */
6 #include <linux/phy.h>
7 #include <linux/phy/phy.h>
14 /* General registers per SerDes block */
24 #define LYNX_28G_LNa_PCC_OFFSET(lane) (4 * (LYNX_28G_NUM_LANE - (lane->id) - 1))
26 /* Per PLL registers */
45 /* Per SerDes lane registers */
120 struct phy *phy; member
143 void __iomem *reg = priv->base + off; in lynx_28g_rmw()
153 lynx_28g_rmw((lane)->priv, LYNX_28G_##reg(lane->id), \
156 ioread32((lane)->priv->base + LYNX_28G_##reg((lane)->id))
158 ioread32((pll)->priv->base + LYNX_28G_##reg((pll)->id))
165 if (LYNX_28G_PLLnRSTCTL_DIS(priv->pll[i].rstctl)) in lynx_28g_supports_interface()
168 if (test_bit(intf, priv->pll[i].supported)) in lynx_28g_supports_interface()
182 pll = &priv->pll[i]; in lynx_28g_pll_get()
184 if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl)) in lynx_28g_pll_get()
187 if (test_bit(intf, pll->supported)) in lynx_28g_pll_get()
194 dev_WARN_ONCE(priv->dev, 1, "no pll for interface %s\n", phy_modes(intf)); in lynx_28g_pll_get()
202 switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) { in lynx_28g_lane_set_nrate()
234 if (pll->id == 0) { in lynx_28g_lane_set_pll()
246 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_cleanup_lane()
249 switch (lane->interface) { in lynx_28g_cleanup_lane()
269 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_lane_set_sgmii()
298 iowrite32(0x00808006, priv->base + LYNX_28G_LNaTECR0(lane->id)); in lynx_28g_lane_set_sgmii()
299 iowrite32(0x04310000, priv->base + LYNX_28G_LNaRGCR1(lane->id)); in lynx_28g_lane_set_sgmii()
300 iowrite32(0x9f800000, priv->base + LYNX_28G_LNaRECR0(lane->id)); in lynx_28g_lane_set_sgmii()
301 iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id)); in lynx_28g_lane_set_sgmii()
302 iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR2(lane->id)); in lynx_28g_lane_set_sgmii()
303 iowrite32(0x00000000, priv->base + LYNX_28G_LNaRSCCR0(lane->id)); in lynx_28g_lane_set_sgmii()
309 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_lane_set_10gbaser()
338 iowrite32(0x10808307, priv->base + LYNX_28G_LNaTECR0(lane->id)); in lynx_28g_lane_set_10gbaser()
339 iowrite32(0x10000000, priv->base + LYNX_28G_LNaRGCR1(lane->id)); in lynx_28g_lane_set_10gbaser()
340 iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR0(lane->id)); in lynx_28g_lane_set_10gbaser()
341 iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id)); in lynx_28g_lane_set_10gbaser()
342 iowrite32(0x81000020, priv->base + LYNX_28G_LNaRECR2(lane->id)); in lynx_28g_lane_set_10gbaser()
343 iowrite32(0x00002000, priv->base + LYNX_28G_LNaRSCCR0(lane->id)); in lynx_28g_lane_set_10gbaser()
346 static int lynx_28g_power_off(struct phy *phy) in lynx_28g_power_off() argument
348 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_power_off()
351 if (!lane->powered_up) in lynx_28g_power_off()
365 lane->powered_up = false; in lynx_28g_power_off()
370 static int lynx_28g_power_on(struct phy *phy) in lynx_28g_power_on() argument
372 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_power_on()
375 if (lane->powered_up) in lynx_28g_power_on()
389 lane->powered_up = true; in lynx_28g_power_on()
394 static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) in lynx_28g_set_mode() argument
396 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_set_mode()
397 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_set_mode()
398 int powered_up = lane->powered_up; in lynx_28g_set_mode()
402 return -EOPNOTSUPP; in lynx_28g_set_mode()
404 if (lane->interface == PHY_INTERFACE_MODE_NA) in lynx_28g_set_mode()
405 return -EOPNOTSUPP; in lynx_28g_set_mode()
408 return -EOPNOTSUPP; in lynx_28g_set_mode()
414 lynx_28g_power_off(phy); in lynx_28g_set_mode()
416 spin_lock(&priv->pcc_lock); in lynx_28g_set_mode()
427 err = -EOPNOTSUPP; in lynx_28g_set_mode()
431 lane->interface = submode; in lynx_28g_set_mode()
434 spin_unlock(&priv->pcc_lock); in lynx_28g_set_mode()
438 lynx_28g_power_on(phy); in lynx_28g_set_mode()
443 static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode, in lynx_28g_validate() argument
446 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_validate()
447 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_validate()
450 return -EOPNOTSUPP; in lynx_28g_validate()
453 return -EOPNOTSUPP; in lynx_28g_validate()
458 static int lynx_28g_init(struct phy *phy) in lynx_28g_init() argument
460 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_init()
463 lane->init = true; in lynx_28g_init()
466 * by this driver will get powered down at init time aka at dpaa2-eth in lynx_28g_init()
469 lane->powered_up = true; in lynx_28g_init()
470 lynx_28g_power_off(phy); in lynx_28g_init()
490 pll = &priv->pll[i]; in lynx_28g_pll_read_configuration()
491 pll->priv = priv; in lynx_28g_pll_read_configuration()
492 pll->id = i; in lynx_28g_pll_read_configuration()
494 pll->rstctl = lynx_28g_pll_read(pll, PLLnRSTCTL); in lynx_28g_pll_read_configuration()
495 pll->cr0 = lynx_28g_pll_read(pll, PLLnCR0); in lynx_28g_pll_read_configuration()
496 pll->cr1 = lynx_28g_pll_read(pll, PLLnCR1); in lynx_28g_pll_read_configuration()
498 if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl)) in lynx_28g_pll_read_configuration()
501 switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) { in lynx_28g_pll_read_configuration()
505 __set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported); in lynx_28g_pll_read_configuration()
506 __set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported); in lynx_28g_pll_read_configuration()
510 __set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported); in lynx_28g_pll_read_configuration()
529 lane = &priv->lane[i]; in lynx_28g_cdr_lock_check()
531 mutex_lock(&lane->phy->mutex); in lynx_28g_cdr_lock_check()
533 if (!lane->init || !lane->powered_up) { in lynx_28g_cdr_lock_check()
534 mutex_unlock(&lane->phy->mutex); in lynx_28g_cdr_lock_check()
546 mutex_unlock(&lane->phy->mutex); in lynx_28g_cdr_lock_check()
548 queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, in lynx_28g_cdr_lock_check()
560 lane->interface = PHY_INTERFACE_MODE_SGMII; in lynx_28g_lane_read_configuration()
563 lane->interface = PHY_INTERFACE_MODE_10GBASER; in lynx_28g_lane_read_configuration()
566 lane->interface = PHY_INTERFACE_MODE_NA; in lynx_28g_lane_read_configuration()
570 static struct phy *lynx_28g_xlate(struct device *dev, in lynx_28g_xlate()
574 int idx = args->args[0]; in lynx_28g_xlate()
577 return ERR_PTR(-EINVAL); in lynx_28g_xlate()
579 return priv->lane[idx].phy; in lynx_28g_xlate()
584 struct device *dev = &pdev->dev; in lynx_28g_probe()
589 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in lynx_28g_probe()
591 return -ENOMEM; in lynx_28g_probe()
592 priv->dev = &pdev->dev; in lynx_28g_probe()
594 priv->base = devm_platform_ioremap_resource(pdev, 0); in lynx_28g_probe()
595 if (IS_ERR(priv->base)) in lynx_28g_probe()
596 return PTR_ERR(priv->base); in lynx_28g_probe()
601 struct lynx_28g_lane *lane = &priv->lane[i]; in lynx_28g_probe()
602 struct phy *phy; in lynx_28g_probe() local
606 phy = devm_phy_create(&pdev->dev, NULL, &lynx_28g_ops); in lynx_28g_probe()
607 if (IS_ERR(phy)) in lynx_28g_probe()
608 return PTR_ERR(phy); in lynx_28g_probe()
610 lane->priv = priv; in lynx_28g_probe()
611 lane->phy = phy; in lynx_28g_probe()
612 lane->id = i; in lynx_28g_probe()
613 phy_set_drvdata(phy, lane); in lynx_28g_probe()
619 spin_lock_init(&priv->pcc_lock); in lynx_28g_probe()
620 INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check); in lynx_28g_probe()
622 queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, in lynx_28g_probe()
625 dev_set_drvdata(&pdev->dev, priv); in lynx_28g_probe()
626 provider = devm_of_phy_provider_register(&pdev->dev, lynx_28g_xlate); in lynx_28g_probe()
633 struct device *dev = &pdev->dev; in lynx_28g_remove()
636 cancel_delayed_work_sync(&priv->cdr_check); in lynx_28g_remove()
640 { .compatible = "fsl,lynx-28g" },
649 .name = "lynx-28g",
656 MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs");