Lines Matching +full:pre +full:- +full:calibration +full:- +full:data
1 // SPDX-License-Identifier: GPL-2.0
3 * phy-zynqmp.c - PHY driver for Xilinx ZynqMP GT.
5 * Copyright (C) 2018-2020 Xilinx Inc.
27 #include <dt-bindings/phy/phy.h>
33 /* TX De-emphasis parameters */
38 /* DN Resistor calibration code parameters */
87 /* Calibration digital logic parameters */
184 * struct xpsgtr_ssc - structure to hold SSC settings for a lane
198 * struct xpsgtr_phy - representation of a lane
219 * struct xpsgtr_dev - representation of a ZynMP GT device
245 * Configuration Data
271 return readl(gtr_dev->serdes + reg); in xpsgtr_read()
276 writel(value, gtr_dev->serdes + reg); in xpsgtr_write()
291 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_read_phy()
292 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_read_phy()
300 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_write_phy()
301 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_write_phy()
309 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_clr_set_phy()
310 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_clr_set_phy()
316 * xpsgtr_save_lane_regs - Saves registers on suspend
324 gtr_dev->saved_regs[i] = xpsgtr_read(gtr_dev, in xpsgtr_save_lane_regs()
329 * xpsgtr_restore_lane_regs - Restores registers on resume
338 gtr_dev->saved_regs[i]); in xpsgtr_restore_lane_regs()
349 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_wait_pll_lock()
351 u8 protocol = gtr_phy->protocol; in xpsgtr_wait_pll_lock()
354 dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n"); in xpsgtr_wait_pll_lock()
361 gtr_phy->instance) { in xpsgtr_wait_pll_lock()
365 gtr_phy = >r_dev->phys[i]; in xpsgtr_wait_pll_lock()
367 if (gtr_phy->protocol == protocol && !gtr_phy->instance) in xpsgtr_wait_pll_lock()
371 return -EBUSY; in xpsgtr_wait_pll_lock()
383 if (--timeout == 0) { in xpsgtr_wait_pll_lock()
384 ret = -ETIMEDOUT; in xpsgtr_wait_pll_lock()
391 if (ret == -ETIMEDOUT) in xpsgtr_wait_pll_lock()
392 dev_err(gtr_dev->dev, in xpsgtr_wait_pll_lock()
394 gtr_phy->lane, gtr_phy->protocol, gtr_phy->instance); in xpsgtr_wait_pll_lock()
406 clk = gtr_phy->dev->clk[gtr_phy->refclk]; in xpsgtr_find_sscs()
413 if (abs(rate - ssc_lookup[i].refclk_rate) < error) in xpsgtr_find_sscs()
417 dev_err(gtr_phy->dev->dev, "Invalid rate %lu for reference clock %u\n", in xpsgtr_find_sscs()
418 rate, gtr_phy->refclk); in xpsgtr_find_sscs()
423 /* Configure PLL and spread-sprectrum clock. */
431 return -EINVAL; in xpsgtr_configure_pll()
433 step_size = ssc->step_size; in xpsgtr_configure_pll()
435 xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
436 PLL_FREQ_MASK, ssc->pll_ref_clk); in xpsgtr_configure_pll()
439 if (gtr_phy->refclk == gtr_phy->lane) in xpsgtr_configure_pll()
440 xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
443 xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
444 L0_REF_CLK_SEL_MASK, 1 << gtr_phy->refclk); in xpsgtr_configure_pll()
462 STEPS_0_MASK, ssc->steps & STEPS_0_MASK); in xpsgtr_configure_pll()
467 (ssc->steps >> STEP_SIZE_SHIFT) & STEPS_1_MASK); in xpsgtr_configure_pll()
481 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_lane_set_protocol()
482 u8 protocol = gtr_phy->protocol; in xpsgtr_lane_set_protocol()
484 switch (gtr_phy->lane) { in xpsgtr_lane_set_protocol()
512 /* DP-specific initialization. */
525 /* SATA-specific initialization. */
528 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init_sata()
532 writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET); in xpsgtr_phy_init_sata()
535 /* SGMII-specific initialization. */
538 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init_sgmii()
539 u32 mask = PROT_BUS_WIDTH_MASK(gtr_phy->lane); in xpsgtr_phy_init_sgmii()
540 u32 val = PROT_BUS_WIDTH_10 << PROT_BUS_WIDTH_SHIFT(gtr_phy->lane); in xpsgtr_phy_init_sgmii()
549 /* Configure TX de-emphasis and margining for DP. */
550 static void xpsgtr_phy_configure_dp(struct xpsgtr_phy *gtr_phy, unsigned int pre, in xpsgtr_phy_configure_dp() argument
566 xpsgtr_write_phy(gtr_phy, L0_TXPMD_TM_48, voltage_swing[pre][voltage]); in xpsgtr_phy_configure_dp()
567 xpsgtr_write_phy(gtr_phy, L0_TX_ANA_TM_18, pre_emphasis[pre][voltage]); in xpsgtr_phy_configure_dp()
580 * except when gtr_phy->skip_phy_init is false (this happens when FPD is in xpsgtr_phy_init_required()
583 if (gtr_phy->protocol == ICM_PROTOCOL_USB && gtr_phy->skip_phy_init) in xpsgtr_phy_init_required()
591 * out of spec due to a issue in the calibration logic. This is the workaround
596 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_tx_term_fix()
610 * As a part of work around sequence for PMOS calibration fix, in xpsgtr_phy_tx_term_fix()
619 dev_dbg(gtr_dev->dev, "calibrating...\n"); in xpsgtr_phy_tx_term_fix()
627 if (!--timeout) { in xpsgtr_phy_tx_term_fix()
628 dev_err(gtr_dev->dev, "calibration time out\n"); in xpsgtr_phy_tx_term_fix()
629 return -ETIMEDOUT; in xpsgtr_phy_tx_term_fix()
635 dev_dbg(gtr_dev->dev, "calibration done\n"); in xpsgtr_phy_tx_term_fix()
660 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init()
663 mutex_lock(>r_dev->gtr_mutex); in xpsgtr_phy_init()
666 if (clk_prepare_enable(gtr_dev->clk[gtr_phy->refclk])) in xpsgtr_phy_init()
673 if (gtr_dev->tx_term_fix) { in xpsgtr_phy_init()
678 gtr_dev->tx_term_fix = false; in xpsgtr_phy_init()
685 * Configure the PLL, the lane protocol, and perform protocol-specific in xpsgtr_phy_init()
694 switch (gtr_phy->protocol) { in xpsgtr_phy_init()
709 mutex_unlock(>r_dev->gtr_mutex); in xpsgtr_phy_init()
716 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_exit()
718 gtr_phy->skip_phy_init = false; in xpsgtr_phy_exit()
721 clk_disable_unprepare(gtr_dev->clk[gtr_phy->refclk]); in xpsgtr_phy_exit()
741 if (gtr_phy->protocol != ICM_PROTOCOL_DP) in xpsgtr_phy_configure()
744 xpsgtr_phy_configure_dp(gtr_phy, opts->dp.pre[0], opts->dp.voltage[0]); in xpsgtr_phy_configure()
770 gtr_phy->protocol = ICM_PROTOCOL_SATA; in xpsgtr_set_lane_type()
774 gtr_phy->protocol = ICM_PROTOCOL_USB; in xpsgtr_set_lane_type()
778 gtr_phy->protocol = ICM_PROTOCOL_DP; in xpsgtr_set_lane_type()
782 gtr_phy->protocol = ICM_PROTOCOL_PCIE; in xpsgtr_set_lane_type()
786 gtr_phy->protocol = ICM_PROTOCOL_SGMII; in xpsgtr_set_lane_type()
789 return -EINVAL; in xpsgtr_set_lane_type()
793 return -EINVAL; in xpsgtr_set_lane_type()
795 gtr_phy->instance = phy_instance; in xpsgtr_set_lane_type()
829 if (args->args_count != 4) { in xpsgtr_xlate()
831 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
838 phy_lane = args->args[0]; in xpsgtr_xlate()
839 if (phy_lane >= ARRAY_SIZE(gtr_dev->phys)) { in xpsgtr_xlate()
841 return ERR_PTR(-ENODEV); in xpsgtr_xlate()
844 gtr_phy = >r_dev->phys[phy_lane]; in xpsgtr_xlate()
845 phy_type = args->args[1]; in xpsgtr_xlate()
846 phy_instance = args->args[2]; in xpsgtr_xlate()
848 guard(mutex)(>r_phy->phy->mutex); in xpsgtr_xlate()
851 dev_err(gtr_dev->dev, "Invalid PHY type and/or instance\n"); in xpsgtr_xlate()
855 refclk = args->args[3]; in xpsgtr_xlate()
856 if (refclk >= ARRAY_SIZE(gtr_dev->clk)) { in xpsgtr_xlate()
858 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
861 gtr_phy->refclk = refclk; in xpsgtr_xlate()
868 if (icm_matrix[phy_lane][i] == gtr_phy->instance) in xpsgtr_xlate()
869 return gtr_phy->phy; in xpsgtr_xlate()
872 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
879 static int xpsgtr_status_read(struct seq_file *seq, void *data) in xpsgtr_status_read() argument
881 struct device *dev = seq->private; in xpsgtr_status_read()
886 mutex_lock(>r_phy->phy->mutex); in xpsgtr_status_read()
888 clk = gtr_phy->dev->clk[gtr_phy->refclk]; in xpsgtr_status_read()
890 seq_printf(seq, "Lane: %u\n", gtr_phy->lane); in xpsgtr_status_read()
892 xpsgtr_icm_str[gtr_phy->protocol]); in xpsgtr_status_read()
893 seq_printf(seq, "Instance: %u\n", gtr_phy->instance); in xpsgtr_status_read()
894 seq_printf(seq, "Reference clock: %u (%pC)\n", gtr_phy->refclk, clk); in xpsgtr_status_read()
899 mutex_unlock(>r_phy->phy->mutex); in xpsgtr_status_read()
912 gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0); in xpsgtr_runtime_suspend()
913 gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1); in xpsgtr_runtime_suspend()
933 if (!gtr_dev->saved_icm_cfg0 && !gtr_dev->saved_icm_cfg1) in xpsgtr_runtime_resume()
937 if (icm_cfg0 == gtr_dev->saved_icm_cfg0 && in xpsgtr_runtime_resume()
938 icm_cfg1 == gtr_dev->saved_icm_cfg1) in xpsgtr_runtime_resume()
944 for (i = 0; i < ARRAY_SIZE(gtr_dev->phys); i++) in xpsgtr_runtime_resume()
945 gtr_dev->phys[i].skip_phy_init = skip_phy_init; in xpsgtr_runtime_resume()
960 for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->clk); ++refclk) { in xpsgtr_get_ref_clocks()
965 clk = devm_clk_get_optional(gtr_dev->dev, name); in xpsgtr_get_ref_clocks()
967 return dev_err_probe(gtr_dev->dev, PTR_ERR(clk), in xpsgtr_get_ref_clocks()
975 gtr_dev->clk[refclk] = clk; in xpsgtr_get_ref_clocks()
983 struct device_node *np = pdev->dev.of_node; in xpsgtr_probe()
989 gtr_dev = devm_kzalloc(&pdev->dev, sizeof(*gtr_dev), GFP_KERNEL); in xpsgtr_probe()
991 return -ENOMEM; in xpsgtr_probe()
993 gtr_dev->dev = &pdev->dev; in xpsgtr_probe()
996 mutex_init(>r_dev->gtr_mutex); in xpsgtr_probe()
998 if (of_device_is_compatible(np, "xlnx,zynqmp-psgtr")) in xpsgtr_probe()
999 gtr_dev->tx_term_fix = in xpsgtr_probe()
1000 of_property_read_bool(np, "xlnx,tx-termination-fix"); in xpsgtr_probe()
1003 gtr_dev->serdes = devm_platform_ioremap_resource_byname(pdev, "serdes"); in xpsgtr_probe()
1004 if (IS_ERR(gtr_dev->serdes)) in xpsgtr_probe()
1005 return PTR_ERR(gtr_dev->serdes); in xpsgtr_probe()
1007 gtr_dev->siou = devm_platform_ioremap_resource_byname(pdev, "siou"); in xpsgtr_probe()
1008 if (IS_ERR(gtr_dev->siou)) in xpsgtr_probe()
1009 return PTR_ERR(gtr_dev->siou); in xpsgtr_probe()
1016 for (port = 0; port < ARRAY_SIZE(gtr_dev->phys); ++port) { in xpsgtr_probe()
1017 struct xpsgtr_phy *gtr_phy = >r_dev->phys[port]; in xpsgtr_probe()
1020 gtr_phy->lane = port; in xpsgtr_probe()
1021 gtr_phy->dev = gtr_dev; in xpsgtr_probe()
1023 phy = devm_phy_create(&pdev->dev, np, &xpsgtr_phyops); in xpsgtr_probe()
1025 dev_err(&pdev->dev, "failed to create PHY\n"); in xpsgtr_probe()
1029 gtr_phy->phy = phy; in xpsgtr_probe()
1031 debugfs_create_devm_seqfile(&phy->dev, "status", phy->debugfs, in xpsgtr_probe()
1036 provider = devm_of_phy_provider_register(&pdev->dev, xpsgtr_xlate); in xpsgtr_probe()
1038 dev_err(&pdev->dev, "registering provider failed\n"); in xpsgtr_probe()
1042 pm_runtime_set_active(gtr_dev->dev); in xpsgtr_probe()
1043 pm_runtime_enable(gtr_dev->dev); in xpsgtr_probe()
1045 ret = pm_runtime_resume_and_get(gtr_dev->dev); in xpsgtr_probe()
1047 pm_runtime_disable(gtr_dev->dev); in xpsgtr_probe()
1051 gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev, in xpsgtr_probe()
1054 if (!gtr_dev->saved_regs) in xpsgtr_probe()
1055 return -ENOMEM; in xpsgtr_probe()
1064 pm_runtime_disable(gtr_dev->dev); in xpsgtr_remove()
1065 pm_runtime_put_noidle(gtr_dev->dev); in xpsgtr_remove()
1066 pm_runtime_set_suspended(gtr_dev->dev); in xpsgtr_remove()
1070 { .compatible = "xlnx,zynqmp-psgtr", },
1071 { .compatible = "xlnx,zynqmp-psgtr-v1.1", },
1080 .name = "xilinx-psgtr",