Lines Matching +full:ssc +full:- +full:mode

1 // SPDX-License-Identifier: GPL-2.0
3 * phy-zynqmp.c - PHY driver for Xilinx ZynqMP GT.
5 * Copyright (C) 2018-2020 Xilinx Inc.
26 #include <dt-bindings/phy/phy.h>
32 /* TX De-emphasis parameters */
57 /* PLL Test Mode register parameters */
61 /* PLL SSC step size offsets */
70 /* SSC step size parameters */
125 /* Test Mode common reset control parameters */
170 * struct xpsgtr_ssc - structure to hold SSC settings for a lane
173 * @steps: number of steps of SSC (Spread Spectrum Clock)
184 * struct xpsgtr_phy - representation of a lane
204 * struct xpsgtr_dev - representation of a ZynMP GT device
254 return readl(gtr_dev->serdes + reg); in xpsgtr_read()
259 writel(value, gtr_dev->serdes + reg); in xpsgtr_write()
274 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_read_phy()
275 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_read_phy()
283 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_write_phy()
284 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_write_phy()
292 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_clr_set_phy()
293 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_clr_set_phy()
306 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_wait_pll_lock()
310 dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n"); in xpsgtr_wait_pll_lock()
320 if (--timeout == 0) { in xpsgtr_wait_pll_lock()
321 ret = -ETIMEDOUT; in xpsgtr_wait_pll_lock()
328 if (ret == -ETIMEDOUT) in xpsgtr_wait_pll_lock()
329 dev_err(gtr_dev->dev, in xpsgtr_wait_pll_lock()
331 gtr_phy->lane, gtr_phy->type, gtr_phy->protocol); in xpsgtr_wait_pll_lock()
336 /* Configure PLL and spread-sprectrum clock. */
339 const struct xpsgtr_ssc *ssc; in xpsgtr_configure_pll() local
342 ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk]; in xpsgtr_configure_pll()
343 step_size = ssc->step_size; in xpsgtr_configure_pll()
345 xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
346 PLL_FREQ_MASK, ssc->pll_ref_clk); in xpsgtr_configure_pll()
349 if (gtr_phy->refclk != gtr_phy->lane) { in xpsgtr_configure_pll()
351 xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
352 L0_REF_CLK_SEL_MASK, 1 << gtr_phy->refclk); in xpsgtr_configure_pll()
355 /* SSC step size [7:0] */ in xpsgtr_configure_pll()
359 /* SSC step size [15:8] */ in xpsgtr_configure_pll()
364 /* SSC step size [23:16] */ in xpsgtr_configure_pll()
369 /* SSC steps [7:0] */ in xpsgtr_configure_pll()
371 STEPS_0_MASK, ssc->steps & STEPS_0_MASK); in xpsgtr_configure_pll()
373 /* SSC steps [10:8] */ in xpsgtr_configure_pll()
376 (ssc->steps >> STEP_SIZE_SHIFT) & STEPS_1_MASK); in xpsgtr_configure_pll()
378 /* SSC step size [24:25] */ in xpsgtr_configure_pll()
388 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_lane_set_protocol()
389 u8 protocol = gtr_phy->protocol; in xpsgtr_lane_set_protocol()
391 switch (gtr_phy->lane) { in xpsgtr_lane_set_protocol()
419 /* DP-specific initialization. */
432 /* SATA-specific initialization. */
435 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init_sata()
439 writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET); in xpsgtr_phy_init_sata()
442 /* SGMII-specific initialization. */
445 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init_sgmii()
449 PROT_BUS_WIDTH_10 << (gtr_phy->lane * PROT_BUS_WIDTH_SHIFT)); in xpsgtr_phy_init_sgmii()
451 PROT_BUS_WIDTH_10 << (gtr_phy->lane * PROT_BUS_WIDTH_SHIFT)); in xpsgtr_phy_init_sgmii()
456 /* Configure TX de-emphasis and margining for DP. */
487 * except when gtr_phy->skip_phy_init is false (this happens when FPD is in xpsgtr_phy_init_required()
490 if (gtr_phy->protocol == ICM_PROTOCOL_USB && gtr_phy->skip_phy_init) in xpsgtr_phy_init_required()
503 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_tx_term_fix()
507 /* Enabling Test Mode control for CMN Rest */ in xpsgtr_phy_tx_term_fix()
510 /* Set Test Mode reset */ in xpsgtr_phy_tx_term_fix()
523 /* Clear Test Mode reset */ in xpsgtr_phy_tx_term_fix()
526 dev_dbg(gtr_dev->dev, "calibrating...\n"); in xpsgtr_phy_tx_term_fix()
534 if (!--timeout) { in xpsgtr_phy_tx_term_fix()
535 dev_err(gtr_dev->dev, "calibration time out\n"); in xpsgtr_phy_tx_term_fix()
536 return -ETIMEDOUT; in xpsgtr_phy_tx_term_fix()
542 dev_dbg(gtr_dev->dev, "calibration done\n"); in xpsgtr_phy_tx_term_fix()
547 /* Set Test Mode reset */ in xpsgtr_phy_tx_term_fix()
558 /* Clear Test Mode reset */ in xpsgtr_phy_tx_term_fix()
567 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init()
570 mutex_lock(&gtr_dev->gtr_mutex); in xpsgtr_phy_init()
576 if (gtr_dev->tx_term_fix) { in xpsgtr_phy_init()
581 gtr_dev->tx_term_fix = false; in xpsgtr_phy_init()
588 * Configure the PLL, the lane protocol, and perform protocol-specific in xpsgtr_phy_init()
594 switch (gtr_phy->protocol) { in xpsgtr_phy_init()
609 mutex_unlock(&gtr_dev->gtr_mutex); in xpsgtr_phy_init()
617 gtr_phy->skip_phy_init = false; in xpsgtr_phy_exit()
632 if (gtr_phy->protocol != ICM_PROTOCOL_DP || in xpsgtr_phy_power_on()
633 gtr_phy->type == XPSGTR_TYPE_DP_0) in xpsgtr_phy_power_on()
643 if (gtr_phy->protocol != ICM_PROTOCOL_DP) in xpsgtr_phy_configure()
646 xpsgtr_phy_configure_dp(gtr_phy, opts->dp.pre[0], opts->dp.voltage[0]); in xpsgtr_phy_configure()
679 gtr_phy->protocol = ICM_PROTOCOL_SATA; in xpsgtr_set_lane_type()
690 gtr_phy->protocol = ICM_PROTOCOL_USB; in xpsgtr_set_lane_type()
701 gtr_phy->protocol = ICM_PROTOCOL_DP; in xpsgtr_set_lane_type()
714 gtr_phy->protocol = ICM_PROTOCOL_PCIE; in xpsgtr_set_lane_type()
727 gtr_phy->protocol = ICM_PROTOCOL_SGMII; in xpsgtr_set_lane_type()
731 return -EINVAL; in xpsgtr_set_lane_type()
735 return -EINVAL; in xpsgtr_set_lane_type()
737 gtr_phy->type = phy_types[phy_instance]; in xpsgtr_set_lane_type()
768 if (args->args_count != 4) { in xpsgtr_xlate()
770 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
777 phy_lane = args->args[0]; in xpsgtr_xlate()
778 if (phy_lane >= ARRAY_SIZE(gtr_dev->phys)) { in xpsgtr_xlate()
780 return ERR_PTR(-ENODEV); in xpsgtr_xlate()
783 gtr_phy = &gtr_dev->phys[phy_lane]; in xpsgtr_xlate()
784 phy_type = args->args[1]; in xpsgtr_xlate()
785 phy_instance = args->args[2]; in xpsgtr_xlate()
789 dev_err(gtr_dev->dev, "Invalid PHY type and/or instance\n"); in xpsgtr_xlate()
793 refclk = args->args[3]; in xpsgtr_xlate()
794 if (refclk >= ARRAY_SIZE(gtr_dev->refclk_sscs) || in xpsgtr_xlate()
795 !gtr_dev->refclk_sscs[refclk]) { in xpsgtr_xlate()
797 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
800 gtr_phy->refclk = refclk; in xpsgtr_xlate()
807 if (icm_matrix[phy_lane][i] == gtr_phy->type) in xpsgtr_xlate()
808 return gtr_phy->phy; in xpsgtr_xlate()
811 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
823 gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0); in xpsgtr_suspend()
824 gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1); in xpsgtr_suspend()
840 if (!gtr_dev->saved_icm_cfg0 && !gtr_dev->saved_icm_cfg1) in xpsgtr_resume()
844 if (icm_cfg0 == gtr_dev->saved_icm_cfg0 && in xpsgtr_resume()
845 icm_cfg1 == gtr_dev->saved_icm_cfg1) in xpsgtr_resume()
851 for (i = 0; i < ARRAY_SIZE(gtr_dev->phys); i++) in xpsgtr_resume()
852 gtr_dev->phys[i].skip_phy_init = skip_phy_init; in xpsgtr_resume()
869 for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->refclk_sscs); ++refclk) { in xpsgtr_get_ref_clocks()
876 clk = devm_clk_get_optional(gtr_dev->dev, name); in xpsgtr_get_ref_clocks()
878 if (PTR_ERR(clk) != -EPROBE_DEFER) in xpsgtr_get_ref_clocks()
879 dev_err(gtr_dev->dev, in xpsgtr_get_ref_clocks()
889 * Get the spread spectrum (SSC) settings for the reference in xpsgtr_get_ref_clocks()
896 gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i]; in xpsgtr_get_ref_clocks()
902 dev_err(gtr_dev->dev, in xpsgtr_get_ref_clocks()
905 return -EINVAL; in xpsgtr_get_ref_clocks()
914 struct device_node *np = pdev->dev.of_node; in xpsgtr_probe()
920 gtr_dev = devm_kzalloc(&pdev->dev, sizeof(*gtr_dev), GFP_KERNEL); in xpsgtr_probe()
922 return -ENOMEM; in xpsgtr_probe()
924 gtr_dev->dev = &pdev->dev; in xpsgtr_probe()
927 mutex_init(&gtr_dev->gtr_mutex); in xpsgtr_probe()
929 if (of_device_is_compatible(np, "xlnx,zynqmp-psgtr")) in xpsgtr_probe()
930 gtr_dev->tx_term_fix = in xpsgtr_probe()
931 of_property_read_bool(np, "xlnx,tx-termination-fix"); in xpsgtr_probe()
934 gtr_dev->serdes = devm_platform_ioremap_resource_byname(pdev, "serdes"); in xpsgtr_probe()
935 if (IS_ERR(gtr_dev->serdes)) in xpsgtr_probe()
936 return PTR_ERR(gtr_dev->serdes); in xpsgtr_probe()
938 gtr_dev->siou = devm_platform_ioremap_resource_byname(pdev, "siou"); in xpsgtr_probe()
939 if (IS_ERR(gtr_dev->siou)) in xpsgtr_probe()
940 return PTR_ERR(gtr_dev->siou); in xpsgtr_probe()
947 for (port = 0; port < ARRAY_SIZE(gtr_dev->phys); ++port) { in xpsgtr_probe()
948 struct xpsgtr_phy *gtr_phy = &gtr_dev->phys[port]; in xpsgtr_probe()
951 gtr_phy->lane = port; in xpsgtr_probe()
952 gtr_phy->dev = gtr_dev; in xpsgtr_probe()
954 phy = devm_phy_create(&pdev->dev, np, &xpsgtr_phyops); in xpsgtr_probe()
956 dev_err(&pdev->dev, "failed to create PHY\n"); in xpsgtr_probe()
960 gtr_phy->phy = phy; in xpsgtr_probe()
965 provider = devm_of_phy_provider_register(&pdev->dev, xpsgtr_xlate); in xpsgtr_probe()
967 dev_err(&pdev->dev, "registering provider failed\n"); in xpsgtr_probe()
974 { .compatible = "xlnx,zynqmp-psgtr", },
975 { .compatible = "xlnx,zynqmp-psgtr-v1.1", },
983 .name = "xilinx-psgtr",