Lines Matching +full:serdes +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0
3 * PCIe SERDES driver for AM654x SoC
5 * Copyright (C) 2018 - 2019 Texas Instruments Incorporated - http://www.ti.com/
9 #include <dt-bindings/phy/phy.h>
11 #include <linux/clk.h>
12 #include <linux/clk-provider.h>
142 /* Mid-speed initial calibration control */
145 /* High-speed initial calibration control */
148 /* Mid-speed recalibration control */
151 /* High-speed recalibration control */
172 /* Mid-speed rate change calibration control */
175 /* High-speed rate change calibration control */
178 /* Serdes reset */
243 struct clk *clks[SERDES_NUM_CLOCKS];
251 ret = regmap_field_write(phy->fields[PLL_ENABLE], PLL_ENABLE_STATE); in serdes_am654_enable_pll()
255 return regmap_field_read_poll_timeout(phy->fields[PLL_OK], val, val, in serdes_am654_enable_pll()
261 struct device *dev = phy->dev; in serdes_am654_disable_pll()
264 ret = regmap_field_write(phy->fields[PLL_ENABLE], PLL_DISABLE_STATE); in serdes_am654_disable_pll()
274 ret |= regmap_field_write(phy->fields[TX0_ENABLE], TX0_ENABLE_STATE); in serdes_am654_enable_txrx()
277 ret |= regmap_field_write(phy->fields[RX0_ENABLE], RX0_ENABLE_STATE); in serdes_am654_enable_txrx()
280 return -EIO; in serdes_am654_enable_txrx()
290 ret |= regmap_field_write(phy->fields[TX0_ENABLE], TX0_DISABLE_STATE); in serdes_am654_disable_txrx()
293 ret |= regmap_field_write(phy->fields[RX0_ENABLE], RX0_DISABLE_STATE); in serdes_am654_disable_txrx()
296 return -EIO; in serdes_am654_disable_txrx()
304 struct device *dev = phy->dev; in serdes_am654_power_on()
320 return regmap_field_read_poll_timeout(phy->fields[CMU_OK_I_0], val, in serdes_am654_power_on()
335 regmap_update_bits(phy->regmap, (offset),\
421 ret |= regmap_field_write(phy->fields[CMU_PLL_CTRL], 0x2); in serdes_am654_pcie_init()
422 ret |= regmap_field_write(phy->fields[AHB_PMA_CM_VCO_VBIAS_VREG], 0x98); in serdes_am654_pcie_init()
423 ret |= regmap_field_write(phy->fields[AHB_PMA_CM_VCO_BIAS_VREG], 0x98); in serdes_am654_pcie_init()
424 ret |= regmap_field_write(phy->fields[AHB_PMA_CM_SR], 0x45); in serdes_am654_pcie_init()
425 ret |= regmap_field_write(phy->fields[AHB_SSC_GEN_Z_O_20_13], 0xe); in serdes_am654_pcie_init()
426 ret |= regmap_field_write(phy->fields[LANE_PLL_CTRL_RXEQ_RXIDLE], 0x5); in serdes_am654_pcie_init()
427 ret |= regmap_field_write(phy->fields[AHB_PMA_LN_AGC_THSEL_VREGH], 0x83); in serdes_am654_pcie_init()
428 ret |= regmap_field_write(phy->fields[AHB_PMA_LN_GEN3_AGC_SD_THSEL], 0x83); in serdes_am654_pcie_init()
429 ret |= regmap_field_write(phy->fields[AHB_PMA_LN_RX_SELR_GEN3], 0x81); in serdes_am654_pcie_init()
430 ret |= regmap_field_write(phy->fields[AHB_PMA_LN_TX_DRV], 0x3b); in serdes_am654_pcie_init()
431 ret |= regmap_field_write(phy->fields[P2S_RBUF_PTR_DIFF], 0x3); in serdes_am654_pcie_init()
432 ret |= regmap_field_write(phy->fields[CONFIG_VERSION], VERSION_VAL); in serdes_am654_pcie_init()
433 ret |= regmap_field_write(phy->fields[COMRXEQ_MS_INIT_CTRL_7_0], 0xf); in serdes_am654_pcie_init()
434 ret |= regmap_field_write(phy->fields[COMRXEQ_HS_INIT_CAL_7_0], 0x4f); in serdes_am654_pcie_init()
435 ret |= regmap_field_write(phy->fields[COMRXEQ_MS_RECAL_CTRL_7_0], 0xf); in serdes_am654_pcie_init()
436 ret |= regmap_field_write(phy->fields[COMRXEQ_HS_RECAL_CTRL_7_0], 0x4f); in serdes_am654_pcie_init()
437 ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_ATT_CONFIG], 0x7); in serdes_am654_pcie_init()
438 ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_EBSTADAPT_WIN_LEN], 0x7f); in serdes_am654_pcie_init()
439 ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_3_4], 0xf); in serdes_am654_pcie_init()
440 ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_14_15_16], 0x9a); in serdes_am654_pcie_init()
441 ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_DLEV_ERR_THRESH], 0x32); in serdes_am654_pcie_init()
442 ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_25], 0x80); in serdes_am654_pcie_init()
443 ret |= regmap_field_write(phy->fields[CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O], 0xf); in serdes_am654_pcie_init()
444 ret |= regmap_field_write(phy->fields[COMRXEQ_HS_RCHANGE_CTRL_7_0], 0x4f); in serdes_am654_pcie_init()
445 ret |= regmap_field_write(phy->fields[CMU_MASTER_CDN], 0x1); in serdes_am654_pcie_init()
446 ret |= regmap_field_write(phy->fields[L1_MASTER_CDN], 0x2); in serdes_am654_pcie_init()
449 return -EIO; in serdes_am654_pcie_init()
458 switch (phy->type) { in serdes_am654_init()
464 return -EINVAL; in serdes_am654_init()
476 ret |= regmap_field_write(phy->fields[POR_EN], 0x1); in serdes_am654_reset()
480 ret |= regmap_field_write(phy->fields[POR_EN], 0x0); in serdes_am654_reset()
483 return -EIO; in serdes_am654_reset()
492 phy->type = PHY_NONE; in serdes_am654_release()
493 phy->busy = false; in serdes_am654_release()
494 mux_control_deselect(phy->control); in serdes_am654_release()
509 if (am654_phy->busy) in serdes_am654_xlate()
510 return ERR_PTR(-EBUSY); in serdes_am654_xlate()
512 ret = mux_control_select(am654_phy->control, args->args[1]); in serdes_am654_xlate()
514 dev_err(dev, "Failed to select SERDES Lane Function\n"); in serdes_am654_xlate()
518 am654_phy->busy = true; in serdes_am654_xlate()
519 am654_phy->type = args->args[0]; in serdes_am654_xlate()
543 * "Figure 12-1986. SerDes Reference Clock Distribution"
570 struct regmap *regmap = mux->regmap; in serdes_am654_clk_mux_get_parent()
571 unsigned int reg = mux->reg; in serdes_am654_clk_mux_get_parent()
578 return serdes_am654_mux_table[val][mux->clk_id]; in serdes_am654_clk_mux_get_parent()
584 struct regmap *regmap = mux->regmap; in serdes_am654_clk_mux_set_parent()
586 unsigned int reg = mux->reg; in serdes_am654_clk_mux_set_parent()
587 int clk_id = mux->clk_id; in serdes_am654_clk_mux_set_parent()
626 return -EINVAL; in serdes_am654_clk_mux_set_parent()
645 struct device_node *node = am654_phy->of_node; in serdes_am654_clk_register()
646 struct device *dev = am654_phy->dev; in serdes_am654_clk_register()
654 struct clk *clk; in serdes_am654_clk_register() local
658 return -ENOMEM; in serdes_am654_clk_register()
660 init = &mux->clk_data; in serdes_am654_clk_register()
663 of_parse_phandle(node, "ti,serdes-clk", 0); in serdes_am654_clk_register()
665 return dev_err_probe(dev, -ENODEV, "Fail to get serdes-clk node\n"); in serdes_am654_clk_register()
667 regmap = syscon_node_to_regmap(regmap_node->parent); in serdes_am654_clk_register()
674 return dev_err_probe(dev, -EINVAL, "SERDES clock must have parents\n"); in serdes_am654_clk_register()
679 return -ENOMEM; in serdes_am654_clk_register()
685 return -EINVAL; in serdes_am654_clk_register()
689 init->ops = &serdes_am654_clk_mux_ops; in serdes_am654_clk_register()
690 init->flags = CLK_SET_RATE_NO_REPARENT; in serdes_am654_clk_register()
691 init->parent_names = parent_names; in serdes_am654_clk_register()
692 init->num_parents = num_parents; in serdes_am654_clk_register()
693 init->name = clock_name; in serdes_am654_clk_register()
695 mux->regmap = regmap; in serdes_am654_clk_register()
696 mux->reg = reg; in serdes_am654_clk_register()
697 mux->clk_id = clock_num; in serdes_am654_clk_register()
698 mux->hw.init = init; in serdes_am654_clk_register()
700 clk = devm_clk_register(dev, &mux->hw); in serdes_am654_clk_register()
701 if (IS_ERR(clk)) in serdes_am654_clk_register()
702 return PTR_ERR(clk); in serdes_am654_clk_register()
704 am654_phy->clks[clock_num] = clk; in serdes_am654_clk_register()
711 .compatible = "ti,phy-am654-serdes",
719 struct regmap *regmap = am654_phy->regmap; in serdes_am654_regfield_init()
720 struct device *dev = am654_phy->dev; in serdes_am654_regfield_init()
724 am654_phy->fields[i] = devm_regmap_field_alloc(dev, in serdes_am654_regfield_init()
727 if (IS_ERR(am654_phy->fields[i])) { in serdes_am654_regfield_init()
729 return PTR_ERR(am654_phy->fields[i]); in serdes_am654_regfield_init()
739 struct device *dev = &pdev->dev; in serdes_am654_probe()
740 struct device_node *node = dev->of_node; in serdes_am654_probe()
753 return -ENOMEM; in serdes_am654_probe()
769 am654_phy->dev = dev; in serdes_am654_probe()
770 am654_phy->of_node = node; in serdes_am654_probe()
771 am654_phy->regmap = regmap; in serdes_am654_probe()
772 am654_phy->control = control; in serdes_am654_probe()
773 am654_phy->type = PHY_NONE; in serdes_am654_probe()
784 ret = of_property_read_string_index(node, "clock-output-names", in serdes_am654_probe()
799 clk_data = &am654_phy->clk_data; in serdes_am654_probe()
800 clk_data->clks = am654_phy->clks; in serdes_am654_probe()
801 clk_data->clk_num = SERDES_NUM_CLOCKS; in serdes_am654_probe()
832 struct device_node *node = am654_phy->of_node; in serdes_am654_remove()
834 pm_runtime_disable(&pdev->dev); in serdes_am654_remove()
842 .name = "phy-am654",
849 MODULE_DESCRIPTION("TI AM654x SERDES driver");