Lines Matching +full:4 +full:- +full:lane

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>
29 * Lane Registers
32 /* TX De-emphasis parameters */
48 #define L0_TXPMD_TM_45_OVER_DP_POST2 BIT(4)
82 #define L0_Ln_REF_CLK_SEL(n) (0x2860 + (n) * 4)
94 #define L3_NSW_PIPE_SHIFT 4
104 #define PLL_REF_SEL(n) (0x10000 + (n) * 4)
115 #define ICM_CFG_SHIFT 4
141 #define NUM_LANES 4
152 #define XPSGTR_TYPE_SATA_0 2 /* SATA controller lane 0 */
153 #define XPSGTR_TYPE_SATA_1 3 /* SATA controller lane 1 */
154 #define XPSGTR_TYPE_PCIE_0 4 /* PCIe controller lane 0 */
155 #define XPSGTR_TYPE_PCIE_1 5 /* PCIe controller lane 1 */
156 #define XPSGTR_TYPE_PCIE_2 6 /* PCIe controller lane 2 */
157 #define XPSGTR_TYPE_PCIE_3 7 /* PCIe controller lane 3 */
158 #define XPSGTR_TYPE_DP_0 8 /* Display Port controller lane 0 */
159 #define XPSGTR_TYPE_DP_1 9 /* Display Port controller lane 1 */
171 * struct xpsgtr_ssc - structure to hold SSC settings for a lane
185 * struct xpsgtr_phy - representation of a lane
187 * @type: controller which uses this lane
188 * @lane: lane number
189 * @protocol: protocol in which the lane operates
197 u8 lane; member
205 * struct xpsgtr_dev - representation of a ZynMP GT device
257 return readl(gtr_dev->serdes + reg); in xpsgtr_read()
262 writel(value, gtr_dev->serdes + reg); in xpsgtr_write()
277 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_read_phy()
278 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_read_phy()
286 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_write_phy()
287 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_write_phy()
295 void __iomem *addr = gtr_phy->dev->serdes in xpsgtr_clr_set_phy()
296 + gtr_phy->lane * PHY_REG_OFFSET + reg; in xpsgtr_clr_set_phy()
309 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_wait_pll_lock()
313 dev_dbg(gtr_dev->dev, "Waiting for PLL lock\n"); in xpsgtr_wait_pll_lock()
323 if (--timeout == 0) { in xpsgtr_wait_pll_lock()
324 ret = -ETIMEDOUT; in xpsgtr_wait_pll_lock()
331 if (ret == -ETIMEDOUT) in xpsgtr_wait_pll_lock()
332 dev_err(gtr_dev->dev, in xpsgtr_wait_pll_lock()
333 "lane %u (type %u, protocol %u): PLL lock timeout\n", in xpsgtr_wait_pll_lock()
334 gtr_phy->lane, gtr_phy->type, gtr_phy->protocol); in xpsgtr_wait_pll_lock()
339 /* Configure PLL and spread-sprectrum clock. */
345 ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk]; in xpsgtr_configure_pll()
346 step_size = ssc->step_size; in xpsgtr_configure_pll()
348 xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
349 PLL_FREQ_MASK, ssc->pll_ref_clk); in xpsgtr_configure_pll()
351 /* Enable lane clock sharing, if required */ in xpsgtr_configure_pll()
352 if (gtr_phy->refclk != gtr_phy->lane) { in xpsgtr_configure_pll()
354 xpsgtr_clr_set(gtr_phy->dev, L0_Ln_REF_CLK_SEL(gtr_phy->lane), in xpsgtr_configure_pll()
355 L0_REF_CLK_SEL_MASK, 1 << gtr_phy->refclk); in xpsgtr_configure_pll()
374 STEPS_0_MASK, ssc->steps & STEPS_0_MASK); in xpsgtr_configure_pll()
379 (ssc->steps >> STEP_SIZE_SHIFT) & STEPS_1_MASK); in xpsgtr_configure_pll()
388 /* Configure the lane protocol. */
391 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_lane_set_protocol()
392 u8 protocol = gtr_phy->protocol; in xpsgtr_lane_set_protocol()
394 switch (gtr_phy->lane) { in xpsgtr_lane_set_protocol()
410 /* We already checked 0 <= lane <= 3 */ in xpsgtr_lane_set_protocol()
422 /* DP-specific initialization. */
435 /* SATA-specific initialization. */
438 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init_sata()
442 writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET); in xpsgtr_phy_init_sata()
445 /* SGMII-specific initialization. */
448 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init_sgmii()
449 u32 mask = PROT_BUS_WIDTH_MASK(gtr_phy->lane); in xpsgtr_phy_init_sgmii()
450 u32 val = PROT_BUS_WIDTH_10 << PROT_BUS_WIDTH_SHIFT(gtr_phy->lane); in xpsgtr_phy_init_sgmii()
459 /* Configure TX de-emphasis and margining for DP. */
463 static const u8 voltage_swing[4][4] = { in xpsgtr_phy_configure_dp()
469 static const u8 pre_emphasis[4][4] = { in xpsgtr_phy_configure_dp()
490 * except when gtr_phy->skip_phy_init is false (this happens when FPD is in xpsgtr_phy_init_required()
491 * shutdown during suspend or when gt lane is changed from current one) in xpsgtr_phy_init_required()
493 if (gtr_phy->protocol == ICM_PROTOCOL_USB && gtr_phy->skip_phy_init) in xpsgtr_phy_init_required()
506 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_tx_term_fix()
521 * we need to configure any lane ICM_CFG to valid protocol. This in xpsgtr_phy_tx_term_fix()
529 dev_dbg(gtr_dev->dev, "calibrating...\n"); in xpsgtr_phy_tx_term_fix()
537 if (!--timeout) { in xpsgtr_phy_tx_term_fix()
538 dev_err(gtr_dev->dev, "calibration time out\n"); in xpsgtr_phy_tx_term_fix()
539 return -ETIMEDOUT; in xpsgtr_phy_tx_term_fix()
545 dev_dbg(gtr_dev->dev, "calibration done\n"); in xpsgtr_phy_tx_term_fix()
570 struct xpsgtr_dev *gtr_dev = gtr_phy->dev; in xpsgtr_phy_init()
573 mutex_lock(&gtr_dev->gtr_mutex); in xpsgtr_phy_init()
579 if (gtr_dev->tx_term_fix) { in xpsgtr_phy_init()
584 gtr_dev->tx_term_fix = false; in xpsgtr_phy_init()
591 * Configure the PLL, the lane protocol, and perform protocol-specific in xpsgtr_phy_init()
597 switch (gtr_phy->protocol) { in xpsgtr_phy_init()
612 mutex_unlock(&gtr_dev->gtr_mutex); in xpsgtr_phy_init()
620 gtr_phy->skip_phy_init = false; in xpsgtr_phy_exit()
636 * lane 0 last. in xpsgtr_phy_power_on()
638 if (gtr_phy->protocol != ICM_PROTOCOL_DP || in xpsgtr_phy_power_on()
639 gtr_phy->type == XPSGTR_TYPE_DP_0) in xpsgtr_phy_power_on()
649 if (gtr_phy->protocol != ICM_PROTOCOL_DP) in xpsgtr_phy_configure()
652 xpsgtr_phy_configure_dp(gtr_phy, opts->dp.pre[0], opts->dp.voltage[0]); in xpsgtr_phy_configure()
669 /* Set the lane type and protocol based on the PHY type and instance number. */
685 gtr_phy->protocol = ICM_PROTOCOL_SATA; in xpsgtr_set_lane_type()
696 gtr_phy->protocol = ICM_PROTOCOL_USB; in xpsgtr_set_lane_type()
707 gtr_phy->protocol = ICM_PROTOCOL_DP; in xpsgtr_set_lane_type()
720 gtr_phy->protocol = ICM_PROTOCOL_PCIE; in xpsgtr_set_lane_type()
733 gtr_phy->protocol = ICM_PROTOCOL_SGMII; in xpsgtr_set_lane_type()
737 return -EINVAL; in xpsgtr_set_lane_type()
741 return -EINVAL; in xpsgtr_set_lane_type()
743 gtr_phy->type = phy_types[phy_instance]; in xpsgtr_set_lane_type()
774 if (args->args_count != 4) { in xpsgtr_xlate()
776 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
780 * Get the PHY parameters from the OF arguments and derive the lane in xpsgtr_xlate()
783 phy_lane = args->args[0]; in xpsgtr_xlate()
784 if (phy_lane >= ARRAY_SIZE(gtr_dev->phys)) { in xpsgtr_xlate()
785 dev_err(dev, "Invalid lane number %u\n", phy_lane); in xpsgtr_xlate()
786 return ERR_PTR(-ENODEV); in xpsgtr_xlate()
789 gtr_phy = &gtr_dev->phys[phy_lane]; in xpsgtr_xlate()
790 phy_type = args->args[1]; in xpsgtr_xlate()
791 phy_instance = args->args[2]; in xpsgtr_xlate()
795 dev_err(gtr_dev->dev, "Invalid PHY type and/or instance\n"); in xpsgtr_xlate()
799 refclk = args->args[3]; in xpsgtr_xlate()
800 if (refclk >= ARRAY_SIZE(gtr_dev->refclk_sscs) || in xpsgtr_xlate()
801 !gtr_dev->refclk_sscs[refclk]) { in xpsgtr_xlate()
803 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
806 gtr_phy->refclk = refclk; in xpsgtr_xlate()
809 * Ensure that the Interconnect Matrix is obeyed, i.e a given lane type in xpsgtr_xlate()
810 * is allowed to operate on the lane. in xpsgtr_xlate()
813 if (icm_matrix[phy_lane][i] == gtr_phy->type) in xpsgtr_xlate()
814 return gtr_phy->phy; in xpsgtr_xlate()
817 return ERR_PTR(-EINVAL); in xpsgtr_xlate()
830 gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0); in xpsgtr_suspend()
831 gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1); in xpsgtr_suspend()
833 for (i = 0; i < ARRAY_SIZE(gtr_dev->clk); i++) in xpsgtr_suspend()
834 clk_disable_unprepare(gtr_dev->clk[i]); in xpsgtr_suspend()
847 for (i = 0; i < ARRAY_SIZE(gtr_dev->clk); i++) { in xpsgtr_resume()
848 err = clk_prepare_enable(gtr_dev->clk[i]); in xpsgtr_resume()
857 if (!gtr_dev->saved_icm_cfg0 && !gtr_dev->saved_icm_cfg1) in xpsgtr_resume()
861 if (icm_cfg0 == gtr_dev->saved_icm_cfg0 && in xpsgtr_resume()
862 icm_cfg1 == gtr_dev->saved_icm_cfg1) in xpsgtr_resume()
868 for (i = 0; i < ARRAY_SIZE(gtr_dev->phys); i++) in xpsgtr_resume()
869 gtr_dev->phys[i].skip_phy_init = skip_phy_init; in xpsgtr_resume()
874 while (i--) in xpsgtr_resume()
875 clk_disable_unprepare(gtr_dev->clk[i]); in xpsgtr_resume()
893 for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->refclk_sscs); ++refclk) { in xpsgtr_get_ref_clocks()
900 clk = devm_clk_get_optional(gtr_dev->dev, name); in xpsgtr_get_ref_clocks()
902 ret = dev_err_probe(gtr_dev->dev, PTR_ERR(clk), in xpsgtr_get_ref_clocks()
915 gtr_dev->clk[refclk] = clk; in xpsgtr_get_ref_clocks()
925 gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i]; in xpsgtr_get_ref_clocks()
931 dev_err(gtr_dev->dev, in xpsgtr_get_ref_clocks()
934 ret = -EINVAL; in xpsgtr_get_ref_clocks()
942 while (refclk--) in xpsgtr_get_ref_clocks()
943 clk_disable_unprepare(gtr_dev->clk[refclk]); in xpsgtr_get_ref_clocks()
950 struct device_node *np = pdev->dev.of_node; in xpsgtr_probe()
957 gtr_dev = devm_kzalloc(&pdev->dev, sizeof(*gtr_dev), GFP_KERNEL); in xpsgtr_probe()
959 return -ENOMEM; in xpsgtr_probe()
961 gtr_dev->dev = &pdev->dev; in xpsgtr_probe()
964 mutex_init(&gtr_dev->gtr_mutex); in xpsgtr_probe()
966 if (of_device_is_compatible(np, "xlnx,zynqmp-psgtr")) in xpsgtr_probe()
967 gtr_dev->tx_term_fix = in xpsgtr_probe()
968 of_property_read_bool(np, "xlnx,tx-termination-fix"); in xpsgtr_probe()
971 gtr_dev->serdes = devm_platform_ioremap_resource_byname(pdev, "serdes"); in xpsgtr_probe()
972 if (IS_ERR(gtr_dev->serdes)) in xpsgtr_probe()
973 return PTR_ERR(gtr_dev->serdes); in xpsgtr_probe()
975 gtr_dev->siou = devm_platform_ioremap_resource_byname(pdev, "siou"); in xpsgtr_probe()
976 if (IS_ERR(gtr_dev->siou)) in xpsgtr_probe()
977 return PTR_ERR(gtr_dev->siou); in xpsgtr_probe()
984 for (port = 0; port < ARRAY_SIZE(gtr_dev->phys); ++port) { in xpsgtr_probe()
985 struct xpsgtr_phy *gtr_phy = &gtr_dev->phys[port]; in xpsgtr_probe()
988 gtr_phy->lane = port; in xpsgtr_probe()
989 gtr_phy->dev = gtr_dev; in xpsgtr_probe()
991 phy = devm_phy_create(&pdev->dev, np, &xpsgtr_phyops); in xpsgtr_probe()
993 dev_err(&pdev->dev, "failed to create PHY\n"); in xpsgtr_probe()
998 gtr_phy->phy = phy; in xpsgtr_probe()
1003 provider = devm_of_phy_provider_register(&pdev->dev, xpsgtr_xlate); in xpsgtr_probe()
1005 dev_err(&pdev->dev, "registering provider failed\n"); in xpsgtr_probe()
1012 for (i = 0; i < ARRAY_SIZE(gtr_dev->clk); i++) in xpsgtr_probe()
1013 clk_disable_unprepare(gtr_dev->clk[i]); in xpsgtr_probe()
1019 { .compatible = "xlnx,zynqmp-psgtr", },
1020 { .compatible = "xlnx,zynqmp-psgtr-v1.1", },
1028 .name = "xilinx-psgtr",