Lines Matching +full:num +full:- +full:lanes
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/clk-provider.h>
23 #include <dt-bindings/phy/phy.h>
25 #include "phy-qcom-qmp.h"
46 * if yes, then offset gives index in the reg-layout
50 * mask of lanes for which this register is written
78 /* set of registers with offsets different per-PHY */
534 /* struct qmp_phy_cfg - per-PHY initialization config */
536 int lanes; member
538 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
568 * struct qmp_phy - per-lane phy descriptor
595 * struct qcom_qmp - structure holding QMP phy block attributes
603 * @phys: array of per-lane phy descriptors
657 "vdda-phy", "vdda-pll",
661 .lanes = 1,
686 .lanes = 2,
710 .lanes = 1,
733 .lanes = 2,
755 .lanes = 2,
777 .lanes = 2,
801 int num, in qmp_ufs_configure_lane() argument
810 for (i = 0; i < num; i++, t++) { in qmp_ufs_configure_lane()
811 if (!(t->lane_mask & lane_mask)) in qmp_ufs_configure_lane()
814 if (t->in_layout) in qmp_ufs_configure_lane()
815 writel(t->val, base + regs[t->offset]); in qmp_ufs_configure_lane()
817 writel(t->val, base + t->offset); in qmp_ufs_configure_lane()
824 int num) in qmp_ufs_configure() argument
826 qmp_ufs_configure_lane(base, regs, tbl, num, 0xff); in qmp_ufs_configure()
831 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_ufs_serdes_init()
832 void __iomem *serdes = qphy->serdes; in qmp_ufs_serdes_init()
833 const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; in qmp_ufs_serdes_init()
834 int serdes_tbl_num = cfg->serdes_tbl_num; in qmp_ufs_serdes_init()
836 qmp_ufs_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); in qmp_ufs_serdes_init()
843 struct qcom_qmp *qmp = qphy->qmp; in qmp_ufs_com_init()
844 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_ufs_com_init()
845 void __iomem *pcs = qphy->pcs; in qmp_ufs_com_init()
849 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qmp_ufs_com_init()
851 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qmp_ufs_com_init()
855 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qmp_ufs_com_init()
859 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) in qmp_ufs_com_init()
861 cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_ufs_com_init()
862 cfg->pwrdn_ctrl); in qmp_ufs_com_init()
865 cfg->pwrdn_ctrl); in qmp_ufs_com_init()
870 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_ufs_com_init()
877 struct qcom_qmp *qmp = qphy->qmp; in qmp_ufs_com_exit()
878 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_ufs_com_exit()
880 reset_control_assert(qmp->ufs_reset); in qmp_ufs_com_exit()
882 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_ufs_com_exit()
884 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_ufs_com_exit()
892 struct qcom_qmp *qmp = qphy->qmp; in qmp_ufs_init()
893 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_ufs_init()
895 dev_vdbg(qmp->dev, "Initializing QMP phy\n"); in qmp_ufs_init()
897 if (cfg->no_pcs_sw_reset) { in qmp_ufs_init()
903 if (!qmp->ufs_reset) { in qmp_ufs_init()
904 qmp->ufs_reset = in qmp_ufs_init()
905 devm_reset_control_get_exclusive(qmp->dev, in qmp_ufs_init()
908 if (IS_ERR(qmp->ufs_reset)) { in qmp_ufs_init()
909 ret = PTR_ERR(qmp->ufs_reset); in qmp_ufs_init()
910 dev_err(qmp->dev, in qmp_ufs_init()
914 qmp->ufs_reset = NULL; in qmp_ufs_init()
919 ret = reset_control_assert(qmp->ufs_reset); in qmp_ufs_init()
934 struct qcom_qmp *qmp = qphy->qmp; in qmp_ufs_power_on()
935 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_ufs_power_on()
936 void __iomem *tx = qphy->tx; in qmp_ufs_power_on()
937 void __iomem *rx = qphy->rx; in qmp_ufs_power_on()
938 void __iomem *pcs = qphy->pcs; in qmp_ufs_power_on()
946 qmp_ufs_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); in qmp_ufs_power_on()
948 if (cfg->lanes >= 2) { in qmp_ufs_power_on()
949 qmp_ufs_configure_lane(qphy->tx2, cfg->regs, in qmp_ufs_power_on()
950 cfg->tx_tbl, cfg->tx_tbl_num, 2); in qmp_ufs_power_on()
953 qmp_ufs_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); in qmp_ufs_power_on()
955 if (cfg->lanes >= 2) { in qmp_ufs_power_on()
956 qmp_ufs_configure_lane(qphy->rx2, cfg->regs, in qmp_ufs_power_on()
957 cfg->rx_tbl, cfg->rx_tbl_num, 2); in qmp_ufs_power_on()
960 qmp_ufs_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qmp_ufs_power_on()
962 ret = reset_control_deassert(qmp->ufs_reset); in qmp_ufs_power_on()
967 if (!cfg->no_pcs_sw_reset) in qmp_ufs_power_on()
968 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_ufs_power_on()
969 /* start SerDes and Phy-Coding-Sublayer */ in qmp_ufs_power_on()
970 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qmp_ufs_power_on()
972 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; in qmp_ufs_power_on()
979 dev_err(qmp->dev, "phy initialization timed-out\n"); in qmp_ufs_power_on()
989 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_ufs_power_off()
992 if (!cfg->no_pcs_sw_reset) in qmp_ufs_power_off()
993 qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_ufs_power_off()
995 /* stop SerDes and Phy-Coding-Sublayer */ in qmp_ufs_power_off()
996 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qmp_ufs_power_off()
999 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { in qmp_ufs_power_off()
1000 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_ufs_power_off()
1001 cfg->pwrdn_ctrl); in qmp_ufs_power_off()
1003 qphy_clrbits(qphy->pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, in qmp_ufs_power_off()
1004 cfg->pwrdn_ctrl); in qmp_ufs_power_off()
1047 int num = cfg->num_vregs; in qmp_ufs_vreg_init() local
1050 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qmp_ufs_vreg_init()
1051 if (!qmp->vregs) in qmp_ufs_vreg_init()
1052 return -ENOMEM; in qmp_ufs_vreg_init()
1054 for (i = 0; i < num; i++) in qmp_ufs_vreg_init()
1055 qmp->vregs[i].supply = cfg->vreg_list[i]; in qmp_ufs_vreg_init()
1057 return devm_regulator_bulk_get(dev, num, qmp->vregs); in qmp_ufs_vreg_init()
1063 int num = cfg->num_clks; in qmp_ufs_clk_init() local
1066 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qmp_ufs_clk_init()
1067 if (!qmp->clks) in qmp_ufs_clk_init()
1068 return -ENOMEM; in qmp_ufs_clk_init()
1070 for (i = 0; i < num; i++) in qmp_ufs_clk_init()
1071 qmp->clks[i].id = cfg->clk_list[i]; in qmp_ufs_clk_init()
1073 return devm_clk_bulk_get(dev, num, qmp->clks); in qmp_ufs_clk_init()
1092 return -ENOMEM; in qmp_ufs_create()
1094 qphy->cfg = cfg; in qmp_ufs_create()
1095 qphy->serdes = serdes; in qmp_ufs_create()
1098 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. in qmp_ufs_create()
1099 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 in qmp_ufs_create()
1100 * For single lane PHYs: pcs_misc (optional) -> 3. in qmp_ufs_create()
1102 qphy->tx = devm_of_iomap(dev, np, 0, NULL); in qmp_ufs_create()
1103 if (IS_ERR(qphy->tx)) in qmp_ufs_create()
1104 return PTR_ERR(qphy->tx); in qmp_ufs_create()
1106 qphy->rx = devm_of_iomap(dev, np, 1, NULL); in qmp_ufs_create()
1107 if (IS_ERR(qphy->rx)) in qmp_ufs_create()
1108 return PTR_ERR(qphy->rx); in qmp_ufs_create()
1110 qphy->pcs = devm_of_iomap(dev, np, 2, NULL); in qmp_ufs_create()
1111 if (IS_ERR(qphy->pcs)) in qmp_ufs_create()
1112 return PTR_ERR(qphy->pcs); in qmp_ufs_create()
1114 if (cfg->lanes >= 2) { in qmp_ufs_create()
1115 qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); in qmp_ufs_create()
1116 if (IS_ERR(qphy->tx2)) in qmp_ufs_create()
1117 return PTR_ERR(qphy->tx2); in qmp_ufs_create()
1119 qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); in qmp_ufs_create()
1120 if (IS_ERR(qphy->rx2)) in qmp_ufs_create()
1121 return PTR_ERR(qphy->rx2); in qmp_ufs_create()
1123 qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); in qmp_ufs_create()
1125 qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); in qmp_ufs_create()
1128 if (IS_ERR(qphy->pcs_misc)) in qmp_ufs_create()
1129 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qmp_ufs_create()
1138 qphy->phy = generic_phy; in qmp_ufs_create()
1139 qphy->qmp = qmp; in qmp_ufs_create()
1140 qmp->phys[id] = qphy; in qmp_ufs_create()
1148 .compatible = "qcom,msm8996-qmp-ufs-phy",
1151 .compatible = "qcom,msm8998-qmp-ufs-phy",
1154 .compatible = "qcom,sc8180x-qmp-ufs-phy",
1157 .compatible = "qcom,sc8280xp-qmp-ufs-phy",
1160 .compatible = "qcom,sdm845-qmp-ufs-phy",
1163 .compatible = "qcom,sm6115-qmp-ufs-phy",
1166 .compatible = "qcom,sm6350-qmp-ufs-phy",
1169 .compatible = "qcom,sm8150-qmp-ufs-phy",
1172 .compatible = "qcom,sm8250-qmp-ufs-phy",
1175 .compatible = "qcom,sm8350-qmp-ufs-phy",
1178 .compatible = "qcom,sm8450-qmp-ufs-phy",
1188 struct device *dev = &pdev->dev; in qmp_ufs_probe()
1193 int num, id; in qmp_ufs_probe() local
1198 return -ENOMEM; in qmp_ufs_probe()
1200 qmp->dev = dev; in qmp_ufs_probe()
1206 return -EINVAL; in qmp_ufs_probe()
1222 num = of_get_available_child_count(dev->of_node); in qmp_ufs_probe()
1224 if (num > 1) in qmp_ufs_probe()
1225 return -EINVAL; in qmp_ufs_probe()
1227 qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); in qmp_ufs_probe()
1228 if (!qmp->phys) in qmp_ufs_probe()
1229 return -ENOMEM; in qmp_ufs_probe()
1232 for_each_available_child_of_node(dev->of_node, child) { in qmp_ufs_probe()
1233 /* Create per-lane phy */ in qmp_ufs_probe()
1256 .name = "qcom-qmp-ufs-phy",