Lines Matching +full:2 +full:- +full:lane

1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2021-2022 NXP. */
12 #define LYNX_28G_NUM_PLL 2
24 #define LYNX_28G_LNa_PCC_OFFSET(lane) (4 * (LYNX_28G_NUM_LANE - (lane->id) - 1)) argument
45 /* Per SerDes lane registers */
46 /* Lane a General Control Register */
47 #define LYNX_28G_LNaGCR0(lane) (0x800 + (lane) * 0x100 + 0x0) argument
51 #define LYNX_28G_LNaGCR0_IF_WIDTH_MSK GENMASK(2, 0)
55 /* Lane a Tx Reset Control Register */
56 #define LYNX_28G_LNaTRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x20) argument
61 /* Lane a Tx General Control Register */
62 #define LYNX_28G_LNaTGCR0(lane) (0x800 + (lane) * 0x100 + 0x24) argument
71 #define LYNX_28G_LNaTECR0(lane) (0x800 + (lane) * 0x100 + 0x30) argument
73 /* Lane a Rx Reset Control Register */
74 #define LYNX_28G_LNaRRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x40) argument
80 /* Lane a Rx General Control Register */
81 #define LYNX_28G_LNaRGCR0(lane) (0x800 + (lane) * 0x100 + 0x44) argument
91 #define LYNX_28G_LNaRGCR1(lane) (0x800 + (lane) * 0x100 + 0x48) argument
93 #define LYNX_28G_LNaRECR0(lane) (0x800 + (lane) * 0x100 + 0x50) argument
94 #define LYNX_28G_LNaRECR1(lane) (0x800 + (lane) * 0x100 + 0x54) argument
95 #define LYNX_28G_LNaRECR2(lane) (0x800 + (lane) * 0x100 + 0x58) argument
97 #define LYNX_28G_LNaRSCCR0(lane) (0x800 + (lane) * 0x100 + 0x74) argument
99 #define LYNX_28G_LNaPSS(lane) (0x1000 + (lane) * 0x4) argument
104 #define LYNX_28G_SGMIIaCR1(lane) (0x1804 + (lane) * 0x10) argument
135 struct lynx_28g_lane lane[LYNX_28G_NUM_LANE]; member
143 void __iomem *reg = priv->base + off; in lynx_28g_rmw()
152 #define lynx_28g_lane_rmw(lane, reg, val, mask) \ argument
153 lynx_28g_rmw((lane)->priv, LYNX_28G_##reg(lane->id), \
155 #define lynx_28g_lane_read(lane, reg) \ argument
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 static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane, in lynx_28g_lane_set_nrate() argument
198 switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) { in lynx_28g_lane_set_nrate()
204 lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_QUARTER, N_RATE_MSK); in lynx_28g_lane_set_nrate()
205 lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_QUARTER, N_RATE_MSK); in lynx_28g_lane_set_nrate()
215 lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_FULL, N_RATE_MSK); in lynx_28g_lane_set_nrate()
216 lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_FULL, N_RATE_MSK); in lynx_28g_lane_set_nrate()
227 static void lynx_28g_lane_set_pll(struct lynx_28g_lane *lane, in lynx_28g_lane_set_pll() argument
230 if (pll->id == 0) { in lynx_28g_lane_set_pll()
231 lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLF, USE_PLL_MSK); in lynx_28g_lane_set_pll()
232 lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLF, USE_PLL_MSK); in lynx_28g_lane_set_pll()
234 lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLS, USE_PLL_MSK); in lynx_28g_lane_set_pll()
235 lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLS, USE_PLL_MSK); in lynx_28g_lane_set_pll()
239 static void lynx_28g_cleanup_lane(struct lynx_28g_lane *lane) in lynx_28g_cleanup_lane() argument
241 u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane); in lynx_28g_cleanup_lane()
242 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_cleanup_lane()
245 switch (lane->interface) { in lynx_28g_cleanup_lane()
262 static void lynx_28g_lane_set_sgmii(struct lynx_28g_lane *lane) in lynx_28g_lane_set_sgmii() argument
264 u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane); in lynx_28g_lane_set_sgmii()
265 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_lane_set_sgmii()
268 lynx_28g_cleanup_lane(lane); in lynx_28g_lane_set_sgmii()
270 /* Setup the lane to run in SGMII */ in lynx_28g_lane_set_sgmii()
276 lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_SGMII, PROTO_SEL_MSK); in lynx_28g_lane_set_sgmii()
277 lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_10_BIT, IF_WIDTH_MSK); in lynx_28g_lane_set_sgmii()
281 lynx_28g_lane_set_pll(lane, pll); in lynx_28g_lane_set_sgmii()
283 /* Choose the portion of clock net to be used on this lane */ in lynx_28g_lane_set_sgmii()
284 lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_SGMII); in lynx_28g_lane_set_sgmii()
287 lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_EN, SGPCS_MSK); in lynx_28g_lane_set_sgmii()
290 iowrite32(0x00808006, priv->base + LYNX_28G_LNaTECR0(lane->id)); in lynx_28g_lane_set_sgmii()
291 iowrite32(0x04310000, priv->base + LYNX_28G_LNaRGCR1(lane->id)); in lynx_28g_lane_set_sgmii()
292 iowrite32(0x9f800000, priv->base + LYNX_28G_LNaRECR0(lane->id)); in lynx_28g_lane_set_sgmii()
293 iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id)); in lynx_28g_lane_set_sgmii()
294 iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR2(lane->id)); in lynx_28g_lane_set_sgmii()
295 iowrite32(0x00000000, priv->base + LYNX_28G_LNaRSCCR0(lane->id)); in lynx_28g_lane_set_sgmii()
298 static void lynx_28g_lane_set_10gbaser(struct lynx_28g_lane *lane) in lynx_28g_lane_set_10gbaser() argument
300 u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane); in lynx_28g_lane_set_10gbaser()
301 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_lane_set_10gbaser()
304 lynx_28g_cleanup_lane(lane); in lynx_28g_lane_set_10gbaser()
306 /* Enable the SXGMII lane */ in lynx_28g_lane_set_10gbaser()
312 lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_XFI, PROTO_SEL_MSK); in lynx_28g_lane_set_10gbaser()
313 lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_20_BIT, IF_WIDTH_MSK); in lynx_28g_lane_set_10gbaser()
317 lynx_28g_lane_set_pll(lane, pll); in lynx_28g_lane_set_10gbaser()
319 /* Choose the portion of clock net to be used on this lane */ in lynx_28g_lane_set_10gbaser()
320 lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_10GBASER); in lynx_28g_lane_set_10gbaser()
323 lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_DIS, SGPCS_MSK); in lynx_28g_lane_set_10gbaser()
326 iowrite32(0x10808307, priv->base + LYNX_28G_LNaTECR0(lane->id)); in lynx_28g_lane_set_10gbaser()
327 iowrite32(0x10000000, priv->base + LYNX_28G_LNaRGCR1(lane->id)); in lynx_28g_lane_set_10gbaser()
328 iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR0(lane->id)); in lynx_28g_lane_set_10gbaser()
329 iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id)); in lynx_28g_lane_set_10gbaser()
330 iowrite32(0x81000020, priv->base + LYNX_28G_LNaRECR2(lane->id)); in lynx_28g_lane_set_10gbaser()
331 iowrite32(0x00002000, priv->base + LYNX_28G_LNaRSCCR0(lane->id)); in lynx_28g_lane_set_10gbaser()
336 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_power_off() local
339 if (!lane->powered_up) in lynx_28g_power_off()
343 lynx_28g_lane_rmw(lane, LNaTRSTCTL, HLT_REQ, HLT_REQ); in lynx_28g_power_off()
344 lynx_28g_lane_rmw(lane, LNaRRSTCTL, HLT_REQ, HLT_REQ); in lynx_28g_power_off()
348 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); in lynx_28g_power_off()
349 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); in lynx_28g_power_off()
353 lane->powered_up = false; in lynx_28g_power_off()
360 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_power_on() local
363 if (lane->powered_up) in lynx_28g_power_on()
366 /* Issue a reset request on the lane */ in lynx_28g_power_on()
367 lynx_28g_lane_rmw(lane, LNaTRSTCTL, RST_REQ, RST_REQ); in lynx_28g_power_on()
368 lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ); in lynx_28g_power_on()
372 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL); in lynx_28g_power_on()
373 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); in lynx_28g_power_on()
377 lane->powered_up = true; in lynx_28g_power_on()
384 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_set_mode() local
385 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_set_mode()
386 int powered_up = lane->powered_up; in lynx_28g_set_mode()
390 return -EOPNOTSUPP; in lynx_28g_set_mode()
392 if (lane->interface == PHY_INTERFACE_MODE_NA) in lynx_28g_set_mode()
393 return -EOPNOTSUPP; in lynx_28g_set_mode()
396 return -EOPNOTSUPP; in lynx_28g_set_mode()
398 /* If the lane is powered up, put the lane into the halt state while in lynx_28g_set_mode()
404 spin_lock(&priv->pcc_lock); in lynx_28g_set_mode()
409 lynx_28g_lane_set_sgmii(lane); in lynx_28g_set_mode()
412 lynx_28g_lane_set_10gbaser(lane); in lynx_28g_set_mode()
415 err = -EOPNOTSUPP; in lynx_28g_set_mode()
419 lane->interface = submode; in lynx_28g_set_mode()
422 spin_unlock(&priv->pcc_lock); in lynx_28g_set_mode()
424 /* Power up the lane if necessary */ in lynx_28g_set_mode()
434 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_validate() local
435 struct lynx_28g_priv *priv = lane->priv; in lynx_28g_validate()
438 return -EOPNOTSUPP; in lynx_28g_validate()
441 return -EOPNOTSUPP; in lynx_28g_validate()
448 struct lynx_28g_lane *lane = phy_get_drvdata(phy); in lynx_28g_init() local
450 /* Mark the fact that the lane was init */ in lynx_28g_init()
451 lane->init = true; in lynx_28g_init()
453 /* SerDes lanes are powered on at boot time. Any lane that is managed in lynx_28g_init()
454 * by this driver will get powered down at init time aka at dpaa2-eth in lynx_28g_init()
457 lane->powered_up = true; in lynx_28g_init()
478 pll = &priv->pll[i]; in lynx_28g_pll_read_configuration()
479 pll->priv = priv; in lynx_28g_pll_read_configuration()
480 pll->id = i; in lynx_28g_pll_read_configuration()
482 pll->rstctl = lynx_28g_pll_read(pll, PLLnRSTCTL); in lynx_28g_pll_read_configuration()
483 pll->cr0 = lynx_28g_pll_read(pll, PLLnCR0); in lynx_28g_pll_read_configuration()
484 pll->cr1 = lynx_28g_pll_read(pll, PLLnCR1); in lynx_28g_pll_read_configuration()
486 if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl)) in lynx_28g_pll_read_configuration()
489 switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) { in lynx_28g_pll_read_configuration()
493 __set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported); in lynx_28g_pll_read_configuration()
494 __set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported); in lynx_28g_pll_read_configuration()
498 __set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported); in lynx_28g_pll_read_configuration()
512 struct lynx_28g_lane *lane; in lynx_28g_cdr_lock_check() local
517 lane = &priv->lane[i]; in lynx_28g_cdr_lock_check()
519 mutex_lock(&lane->phy->mutex); in lynx_28g_cdr_lock_check()
521 if (!lane->init || !lane->powered_up) { in lynx_28g_cdr_lock_check()
522 mutex_unlock(&lane->phy->mutex); in lynx_28g_cdr_lock_check()
526 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); in lynx_28g_cdr_lock_check()
528 lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ); in lynx_28g_cdr_lock_check()
530 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); in lynx_28g_cdr_lock_check()
534 mutex_unlock(&lane->phy->mutex); in lynx_28g_cdr_lock_check()
536 queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, in lynx_28g_cdr_lock_check()
540 static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane) in lynx_28g_lane_read_configuration() argument
544 pss = lynx_28g_lane_read(lane, LNaPSS); in lynx_28g_lane_read_configuration()
548 lane->interface = PHY_INTERFACE_MODE_SGMII; in lynx_28g_lane_read_configuration()
551 lane->interface = PHY_INTERFACE_MODE_10GBASER; in lynx_28g_lane_read_configuration()
554 lane->interface = PHY_INTERFACE_MODE_NA; in lynx_28g_lane_read_configuration()
562 int idx = args->args[0]; in lynx_28g_xlate()
565 return ERR_PTR(-EINVAL); in lynx_28g_xlate()
567 return priv->lane[idx].phy; in lynx_28g_xlate()
572 struct device *dev = &pdev->dev; in lynx_28g_probe()
577 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in lynx_28g_probe()
579 return -ENOMEM; in lynx_28g_probe()
580 priv->dev = &pdev->dev; in lynx_28g_probe()
582 priv->base = devm_platform_ioremap_resource(pdev, 0); in lynx_28g_probe()
583 if (IS_ERR(priv->base)) in lynx_28g_probe()
584 return PTR_ERR(priv->base); in lynx_28g_probe()
589 struct lynx_28g_lane *lane = &priv->lane[i]; in lynx_28g_probe() local
592 memset(lane, 0, sizeof(*lane)); in lynx_28g_probe()
594 phy = devm_phy_create(&pdev->dev, NULL, &lynx_28g_ops); in lynx_28g_probe()
598 lane->priv = priv; in lynx_28g_probe()
599 lane->phy = phy; in lynx_28g_probe()
600 lane->id = i; in lynx_28g_probe()
601 phy_set_drvdata(phy, lane); in lynx_28g_probe()
602 lynx_28g_lane_read_configuration(lane); in lynx_28g_probe()
607 spin_lock_init(&priv->pcc_lock); in lynx_28g_probe()
608 INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check); in lynx_28g_probe()
610 queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, in lynx_28g_probe()
613 dev_set_drvdata(&pdev->dev, priv); in lynx_28g_probe()
614 provider = devm_of_phy_provider_register(&pdev->dev, lynx_28g_xlate); in lynx_28g_probe()
621 struct device *dev = &pdev->dev; in lynx_28g_remove()
624 cancel_delayed_work_sync(&priv->cdr_check); in lynx_28g_remove()
628 { .compatible = "fsl,lynx-28g" },
637 .name = "lynx-28g",