Lines Matching +full:force +full:- +full:external +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AppliedMicro X-Gene Multi-purpose PHY driver
10 * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes.
12 * PLL clock macro is used to generate the clock for the PHY. This driver
13 * configures the first PLL CMU, the second PLL CMU, and programs the PHY to
19 * -----------------
20 * | Internal | |------|
21 * | Ref PLL CMU |----| | ------------- ---------
22 * ------------ ---- | MUX |-----|PHY PLL CMU|----| Serdes|
23 * | | | | ---------
24 * External Clock ------| | -------------
25 * |------|
30 * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000.
33 * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP
34 * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP,
35 * it is located outside the PHY IP. This is the case for the PHY located
36 * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required
39 * Currently, this driver only supports Gen3 SATA mode with external clock.
45 #include <linux/phy/phy.h>
48 /* Max 2 lanes per a PHY unit */
51 /* Register offset inside the PHY */
92 /* SDS CSR used for PHY Indirect access */
267 /* PHY lane CSR accessing from SDS indirectly */
504 CLK_EXT_DIFF = 0, /* External differential */
525 u32 txprecursor_cn1[MAX_LANE*3]; /* Tx emphasis taps 1st pre-cursor */
526 u32 txprecursor_cn2[MAX_LANE*3]; /* Tx emphasis taps 2nd pre-cursor */
527 u32 txpostcursor_cp1[MAX_LANE*3]; /* Tx emphasis taps post-cursor */
532 struct phy *phy; member
535 void __iomem *sds_base; /* PHY CSR base addr */
547 MODULE_PARM_DESC(preA3Chip, "Enable pre-A3 chip support (1=enable 0=disable)");
560 readl(csr_base + indirect_data_reg); /* Force a barrier */ in sds_wr()
562 readl(csr_base + indirect_cmd_reg); /* Force a barrier */ in sds_wr()
582 readl(csr_base + indirect_cmd_reg); /* Force a barrier */ in sds_rd()
596 void __iomem *sds_base = ctx->sds_base; in cmu_wr()
607 pr_debug("CMU WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, val); in cmu_wr()
613 void __iomem *sds_base = ctx->sds_base; in cmu_rd()
659 void __iomem *sds_base = ctx->sds_base; in serdes_wr()
668 pr_debug("SERDES WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, in serdes_wr()
674 void __iomem *sds_base = ctx->sds_base; in serdes_rd()
719 /* Select external clock mux */ in xgene_phy_cfg_cmu_clk_type()
727 dev_dbg(ctx->dev, "Set external reference clock\n"); in xgene_phy_cfg_cmu_clk_type()
737 dev_dbg(ctx->dev, "Set internal reference clock\n"); in xgene_phy_cfg_cmu_clk_type()
752 dev_dbg(ctx->dev, in xgene_phy_cfg_cmu_clk_type()
834 /* Disable force PLL lock */ in xgene_phy_sata_cfg_cmu_core()
855 /* Configure lane for 20-bits */ in xgene_phy_sata_cfg_cmu_core()
933 /* Force VCO calibration to restart */ in xgene_phy_ssc_enable()
959 ctx->sata_param.txboostgain[lane * 3 + in xgene_phy_sata_cfg_lanes()
960 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
972 /* Configure Tx for 20-bits */ in xgene_phy_sata_cfg_lanes()
984 /* Set pre-emphasis first 1 and 2, and post-emphasis values */ in xgene_phy_sata_cfg_lanes()
987 ctx->sata_param.txprecursor_cn1[lane * 3 + in xgene_phy_sata_cfg_lanes()
988 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
990 ctx->sata_param.txpostcursor_cp1[lane * 3 + in xgene_phy_sata_cfg_lanes()
991 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
993 ctx->sata_param.txprecursor_cn2[lane * 3 + in xgene_phy_sata_cfg_lanes()
994 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
1000 ctx->sata_param.txamplitude[lane * 3 + in xgene_phy_sata_cfg_lanes()
1001 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
1008 /* Configure Rx for 20-bits */ in xgene_phy_sata_cfg_lanes()
1046 /* Set Eye Monitor counter width to 12-bit */ in xgene_phy_sata_cfg_lanes()
1095 ctx->sata_param.txeyedirection[lane * 3 + in xgene_phy_sata_cfg_lanes()
1096 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
1098 ctx->sata_param.txeyetuning[lane * 3 + in xgene_phy_sata_cfg_lanes()
1099 ctx->sata_param.speed[lane]]); in xgene_phy_sata_cfg_lanes()
1138 void __iomem *csr_serdes = ctx->sds_base; in xgene_phy_cal_rdy_chk()
1142 /* Release PHY main reset */ in xgene_phy_cal_rdy_chk()
1144 readl(csr_serdes + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ in xgene_phy_cal_rdy_chk()
1149 * As per PHY design spec, the PLL reset requires a minimum in xgene_phy_cal_rdy_chk()
1158 * As per PHY design spec, the PLL auto calibration requires in xgene_phy_cal_rdy_chk()
1166 * As per PHY design spec, the PLL requires a minimum of in xgene_phy_cal_rdy_chk()
1187 * The serial transmit pins, TXP/TXN, have Pull-UP and Pull-DOWN in xgene_phy_cal_rdy_chk()
1213 * As per PHY design spec, PLL calibration status requires in xgene_phy_cal_rdy_chk()
1217 } while (--loop > 0); in xgene_phy_cal_rdy_chk()
1220 dev_dbg(ctx->dev, "PLL calibration %s\n", in xgene_phy_cal_rdy_chk()
1223 dev_err(ctx->dev, in xgene_phy_cal_rdy_chk()
1225 return -1; in xgene_phy_cal_rdy_chk()
1227 dev_dbg(ctx->dev, "PLL calibration successful\n"); in xgene_phy_cal_rdy_chk()
1230 dev_dbg(ctx->dev, "PHY Tx is %sready\n", val & 0x300 ? "" : "not "); in xgene_phy_cal_rdy_chk()
1240 dev_dbg(ctx->dev, "Reset VCO and re-start again\n"); in xgene_phy_pdwn_force_vco()
1255 void __iomem *sds_base = ctx->sds_base; in xgene_phy_hw_init_sata()
1259 /* Configure the PHY for operation */ in xgene_phy_hw_init_sata()
1260 dev_dbg(ctx->dev, "Reset PHY\n"); in xgene_phy_hw_init_sata()
1261 /* Place PHY into reset */ in xgene_phy_hw_init_sata()
1263 val = readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ in xgene_phy_hw_init_sata()
1264 /* Release PHY lane from reset (active high) */ in xgene_phy_hw_init_sata()
1266 readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ in xgene_phy_hw_init_sata()
1267 /* Release all PHY module out of reset except PHY main reset */ in xgene_phy_hw_init_sata()
1269 readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */ in xgene_phy_hw_init_sata()
1274 ctx->sata_param.txspeed[ctx->sata_param.speed[0]]); in xgene_phy_hw_init_sata()
1277 dev_dbg(ctx->dev, "Set the customer pin mode to SATA\n"); in xgene_phy_hw_init_sata()
1292 /* Configure PHY lanes */ in xgene_phy_hw_init_sata()
1295 /* Set Rx/Tx 20-bit */ in xgene_phy_hw_init_sata()
1308 } while (--i > 0); in xgene_phy_hw_init_sata()
1311 dev_err(ctx->dev, "PLL calibration failed\n"); in xgene_phy_hw_init_sata()
1322 dev_dbg(ctx->dev, "PHY init clk type %d\n", clk_type); in xgene_phy_hw_initialize()
1324 if (ctx->mode == MODE_SATA) { in xgene_phy_hw_initialize()
1329 dev_err(ctx->dev, "Un-supported customer pin mode %d\n", in xgene_phy_hw_initialize()
1330 ctx->mode); in xgene_phy_hw_initialize()
1331 return -ENODEV; in xgene_phy_hw_initialize()
1340 * Calibrate the receiver signal path offset in two steps - summar and
1374 * As per PHY design spec, the Summer calibration requires a minimum in xgene_phy_force_lat_summer_cal()
1381 * As per PHY design spec, the auto calibration requires a minimum in xgene_phy_force_lat_summer_cal()
1390 * As per PHY design spec, the latch calibration requires a minimum in xgene_phy_force_lat_summer_cal()
1397 /* Configure the PHY lane for calibration */ in xgene_phy_force_lat_summer_cal()
1413 /* As per PHY design spec, the reset requires a minimum of 100us. */ in xgene_phy_reset_rxd()
1437 dev_dbg(ctx->dev, "Generating avg calibration value for lane %d\n", in xgene_phy_gen_avg_val()
1440 /* Enable RX Hi-Z termination */ in xgene_phy_gen_avg_val()
1450 * Calibrate the receiver signal path offset in two steps - summar in xgene_phy_gen_avg_val()
1493 dev_dbg(ctx->dev, "Iteration %d:\n", avg_loop); in xgene_phy_gen_avg_val()
1494 dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n", in xgene_phy_gen_avg_val()
1497 dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n", in xgene_phy_gen_avg_val()
1500 dev_dbg(ctx->dev, "SUM 0x%x\n", sum_cal_itr); in xgene_phy_gen_avg_val()
1503 dev_err(ctx->dev, in xgene_phy_gen_avg_val()
1545 dev_dbg(ctx->dev, "Average Value:\n"); in xgene_phy_gen_avg_val()
1546 dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n", in xgene_phy_gen_avg_val()
1551 dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n", in xgene_phy_gen_avg_val()
1556 dev_dbg(ctx->dev, "SUM 0x%x\n", in xgene_phy_gen_avg_val()
1562 dev_dbg(ctx->dev, "Enable Manual Summer calibration\n"); in xgene_phy_gen_avg_val()
1566 dev_dbg(ctx->dev, "Enable Manual Latch calibration\n"); in xgene_phy_gen_avg_val()
1569 /* Disable RX Hi-Z termination */ in xgene_phy_gen_avg_val()
1579 static int xgene_phy_hw_init(struct phy *phy) in xgene_phy_hw_init() argument
1581 struct xgene_phy_ctx *ctx = phy_get_drvdata(phy); in xgene_phy_hw_init()
1587 dev_err(ctx->dev, "PHY initialize failed %d\n", rc); in xgene_phy_hw_init()
1591 /* Setup clock properly after PHY configuration */ in xgene_phy_hw_init()
1592 if (!IS_ERR(ctx->clk)) { in xgene_phy_hw_init()
1594 clk_prepare_enable(ctx->clk); in xgene_phy_hw_init()
1595 clk_disable_unprepare(ctx->clk); in xgene_phy_hw_init()
1596 clk_prepare_enable(ctx->clk); in xgene_phy_hw_init()
1603 dev_dbg(ctx->dev, "PHY initialized\n"); in xgene_phy_hw_init()
1612 static struct phy *xgene_phy_xlate(struct device *dev, in xgene_phy_xlate()
1617 if (args->args_count <= 0) in xgene_phy_xlate()
1618 return ERR_PTR(-EINVAL); in xgene_phy_xlate()
1619 if (args->args[0] >= MODE_MAX) in xgene_phy_xlate()
1620 return ERR_PTR(-EINVAL); in xgene_phy_xlate()
1622 ctx->mode = args->args[0]; in xgene_phy_xlate()
1623 return ctx->phy; in xgene_phy_xlate()
1633 if (!of_property_read_u32_array(pdev->dev.of_node, name, buffer, in xgene_phy_get_param()
1658 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); in xgene_phy_probe()
1660 return -ENOMEM; in xgene_phy_probe()
1662 ctx->dev = &pdev->dev; in xgene_phy_probe()
1664 ctx->sds_base = devm_platform_ioremap_resource(pdev, 0); in xgene_phy_probe()
1665 if (IS_ERR(ctx->sds_base)) in xgene_phy_probe()
1666 return PTR_ERR(ctx->sds_base); in xgene_phy_probe()
1669 ctx->clk = clk_get(&pdev->dev, NULL); in xgene_phy_probe()
1672 xgene_phy_get_param(pdev, "apm,tx-eye-tuning", in xgene_phy_probe()
1673 ctx->sata_param.txeyetuning, 6, default_txeye_tuning, 1); in xgene_phy_probe()
1674 xgene_phy_get_param(pdev, "apm,tx-eye-direction", in xgene_phy_probe()
1675 ctx->sata_param.txeyedirection, 6, default_txeye_direction, 1); in xgene_phy_probe()
1676 xgene_phy_get_param(pdev, "apm,tx-boost-gain", in xgene_phy_probe()
1677 ctx->sata_param.txboostgain, 6, default_txboost_gain, 1); in xgene_phy_probe()
1678 xgene_phy_get_param(pdev, "apm,tx-amplitude", in xgene_phy_probe()
1679 ctx->sata_param.txamplitude, 6, default_txamp, 13300); in xgene_phy_probe()
1680 xgene_phy_get_param(pdev, "apm,tx-pre-cursor1", in xgene_phy_probe()
1681 ctx->sata_param.txprecursor_cn1, 6, default_txcn1, 18200); in xgene_phy_probe()
1682 xgene_phy_get_param(pdev, "apm,tx-pre-cursor2", in xgene_phy_probe()
1683 ctx->sata_param.txprecursor_cn2, 6, default_txcn2, 18200); in xgene_phy_probe()
1684 xgene_phy_get_param(pdev, "apm,tx-post-cursor", in xgene_phy_probe()
1685 ctx->sata_param.txpostcursor_cp1, 6, default_txcp1, 18200); in xgene_phy_probe()
1686 xgene_phy_get_param(pdev, "apm,tx-speed", in xgene_phy_probe()
1687 ctx->sata_param.txspeed, 3, default_spd, 1); in xgene_phy_probe()
1689 ctx->sata_param.speed[i] = 2; /* Default to Gen3 */ in xgene_phy_probe()
1693 ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops); in xgene_phy_probe()
1694 if (IS_ERR(ctx->phy)) { in xgene_phy_probe()
1695 dev_dbg(&pdev->dev, "Failed to create PHY\n"); in xgene_phy_probe()
1696 return PTR_ERR(ctx->phy); in xgene_phy_probe()
1698 phy_set_drvdata(ctx->phy, ctx); in xgene_phy_probe()
1700 phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate); in xgene_phy_probe()
1705 {.compatible = "apm,xgene-phy",},
1713 .name = "xgene-phy",
1719 MODULE_DESCRIPTION("APM X-Gene Multi-Purpose PHY driver");