Lines Matching +full:serdes +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/clk.h>
7 #include <linux/clk-provider.h>
23 #include "phy-qcom-qmp.h"
24 #include "phy-qcom-qmp-pcs-misc-v3.h"
25 #include "phy-qcom-qmp-pcs-usb-v4.h"
26 #include "phy-qcom-qmp-pcs-usb-v5.h"
28 #include "phy-qcom-qmp-dp-com-v3.h"
70 /* set of registers with offsets different per-PHY */
482 u16 serdes; member
489 /* struct qmp_phy_cfg - per-PHY initialization config */
493 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
527 void __iomem *serdes; member
538 struct clk *pipe_clk;
599 "vdda-phy", "vdda-pll",
713 if (!(t->lane_mask & lane_mask)) in qmp_usb_legacy_configure_lane()
716 writel(t->val, base + t->offset); in qmp_usb_legacy_configure_lane()
729 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_serdes_init()
730 void __iomem *serdes = qmp->serdes; in qmp_usb_legacy_serdes_init() local
731 const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; in qmp_usb_legacy_serdes_init()
732 int serdes_tbl_num = cfg->serdes_tbl_num; in qmp_usb_legacy_serdes_init()
734 qmp_usb_legacy_configure(serdes, serdes_tbl, serdes_tbl_num); in qmp_usb_legacy_serdes_init()
742 void __iomem *dp_com = qmp->dp_com; in qmp_usb_legacy_init_dp_com()
751 /* Default type-c orientation, i.e CC1 */ in qmp_usb_legacy_init_dp_com()
769 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_init()
770 void __iomem *pcs = qmp->pcs; in qmp_usb_legacy_init()
773 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qmp_usb_legacy_init()
775 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qmp_usb_legacy_init()
779 ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_usb_legacy_init()
781 dev_err(qmp->dev, "reset assert failed\n"); in qmp_usb_legacy_init()
785 ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets); in qmp_usb_legacy_init()
787 dev_err(qmp->dev, "reset deassert failed\n"); in qmp_usb_legacy_init()
791 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qmp_usb_legacy_init()
797 qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN); in qmp_usb_legacy_init()
802 reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_usb_legacy_init()
804 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_usb_legacy_init()
812 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_exit()
814 reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_usb_legacy_exit()
816 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_usb_legacy_exit()
818 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_usb_legacy_exit()
826 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_power_on()
827 void __iomem *tx = qmp->tx; in qmp_usb_legacy_power_on()
828 void __iomem *rx = qmp->rx; in qmp_usb_legacy_power_on()
829 void __iomem *pcs = qmp->pcs; in qmp_usb_legacy_power_on()
836 ret = clk_prepare_enable(qmp->pipe_clk); in qmp_usb_legacy_power_on()
838 dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); in qmp_usb_legacy_power_on()
843 qmp_usb_legacy_configure_lane(tx, cfg->tx_tbl, cfg->tx_tbl_num, 1); in qmp_usb_legacy_power_on()
844 qmp_usb_legacy_configure_lane(rx, cfg->rx_tbl, cfg->rx_tbl_num, 1); in qmp_usb_legacy_power_on()
846 qmp_usb_legacy_configure_lane(qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2); in qmp_usb_legacy_power_on()
847 qmp_usb_legacy_configure_lane(qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2); in qmp_usb_legacy_power_on()
849 qmp_usb_legacy_configure(pcs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qmp_usb_legacy_power_on()
854 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_usb_legacy_power_on()
856 /* start SerDes and Phy-Coding-Sublayer */ in qmp_usb_legacy_power_on()
857 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); in qmp_usb_legacy_power_on()
859 status = pcs + cfg->regs[QPHY_PCS_STATUS]; in qmp_usb_legacy_power_on()
863 dev_err(qmp->dev, "phy initialization timed-out\n"); in qmp_usb_legacy_power_on()
870 clk_disable_unprepare(qmp->pipe_clk); in qmp_usb_legacy_power_on()
878 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_power_off()
880 clk_disable_unprepare(qmp->pipe_clk); in qmp_usb_legacy_power_off()
883 qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_usb_legacy_power_off()
885 /* stop SerDes and Phy-Coding-Sublayer */ in qmp_usb_legacy_power_off()
886 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], in qmp_usb_legacy_power_off()
890 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_usb_legacy_power_off()
925 qmp->mode = mode; in qmp_usb_legacy_set_mode()
939 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_enable_autonomous_mode()
940 void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs; in qmp_usb_legacy_enable_autonomous_mode()
941 void __iomem *pcs_misc = qmp->pcs_misc; in qmp_usb_legacy_enable_autonomous_mode()
944 if (qmp->mode == PHY_MODE_USB_HOST_SS || in qmp_usb_legacy_enable_autonomous_mode()
945 qmp->mode == PHY_MODE_USB_DEVICE_SS) in qmp_usb_legacy_enable_autonomous_mode()
951 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_legacy_enable_autonomous_mode()
953 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_legacy_enable_autonomous_mode()
955 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qmp_usb_legacy_enable_autonomous_mode()
959 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); in qmp_usb_legacy_enable_autonomous_mode()
968 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_disable_autonomous_mode()
969 void __iomem *pcs_usb = qmp->pcs_usb ?: qmp->pcs; in qmp_usb_legacy_disable_autonomous_mode()
970 void __iomem *pcs_misc = qmp->pcs_misc; in qmp_usb_legacy_disable_autonomous_mode()
976 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qmp_usb_legacy_disable_autonomous_mode()
979 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_legacy_disable_autonomous_mode()
981 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_legacy_disable_autonomous_mode()
987 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_runtime_suspend()
989 dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode); in qmp_usb_legacy_runtime_suspend()
991 if (!qmp->phy->init_count) { in qmp_usb_legacy_runtime_suspend()
998 clk_disable_unprepare(qmp->pipe_clk); in qmp_usb_legacy_runtime_suspend()
999 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_usb_legacy_runtime_suspend()
1007 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_runtime_resume()
1010 dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode); in qmp_usb_legacy_runtime_resume()
1012 if (!qmp->phy->init_count) { in qmp_usb_legacy_runtime_resume()
1017 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qmp_usb_legacy_runtime_resume()
1021 ret = clk_prepare_enable(qmp->pipe_clk); in qmp_usb_legacy_runtime_resume()
1024 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_usb_legacy_runtime_resume()
1040 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_vreg_init()
1041 struct device *dev = qmp->dev; in qmp_usb_legacy_vreg_init()
1042 int num = cfg->num_vregs; in qmp_usb_legacy_vreg_init()
1045 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qmp_usb_legacy_vreg_init()
1046 if (!qmp->vregs) in qmp_usb_legacy_vreg_init()
1047 return -ENOMEM; in qmp_usb_legacy_vreg_init()
1050 qmp->vregs[i].supply = cfg->vreg_list[i]; in qmp_usb_legacy_vreg_init()
1052 return devm_regulator_bulk_get(dev, num, qmp->vregs); in qmp_usb_legacy_vreg_init()
1057 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_reset_init()
1058 struct device *dev = qmp->dev; in qmp_usb_legacy_reset_init()
1062 qmp->resets = devm_kcalloc(dev, cfg->num_resets, in qmp_usb_legacy_reset_init()
1063 sizeof(*qmp->resets), GFP_KERNEL); in qmp_usb_legacy_reset_init()
1064 if (!qmp->resets) in qmp_usb_legacy_reset_init()
1065 return -ENOMEM; in qmp_usb_legacy_reset_init()
1067 for (i = 0; i < cfg->num_resets; i++) in qmp_usb_legacy_reset_init()
1068 qmp->resets[i].id = cfg->reset_list[i]; in qmp_usb_legacy_reset_init()
1070 ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets); in qmp_usb_legacy_reset_init()
1079 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_clk_init()
1080 struct device *dev = qmp->dev; in qmp_usb_legacy_clk_init()
1081 int num = cfg->num_clks; in qmp_usb_legacy_clk_init()
1084 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qmp_usb_legacy_clk_init()
1085 if (!qmp->clks) in qmp_usb_legacy_clk_init()
1086 return -ENOMEM; in qmp_usb_legacy_clk_init()
1089 qmp->clks[i].id = cfg->clk_list[i]; in qmp_usb_legacy_clk_init()
1091 return devm_clk_bulk_get(dev, num, qmp->clks); in qmp_usb_legacy_clk_init()
1109 * +---------------+
1110 * | PHY block |<<---------------------------------------+
1112 * | +-------+ | +-----+ |
1113 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
1114 * clk | +-------+ | +-----+
1115 * +---------------+
1119 struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed; in phy_pipe_clk_register()
1123 ret = of_property_read_string(np, "clock-output-names", &init.name); in phy_pipe_clk_register()
1125 dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); in phy_pipe_clk_register()
1132 fixed->fixed_rate = 125000000; in phy_pipe_clk_register()
1133 fixed->hw.init = &init; in phy_pipe_clk_register()
1135 ret = devm_clk_hw_register(qmp->dev, &fixed->hw); in phy_pipe_clk_register()
1139 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); in phy_pipe_clk_register()
1147 return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); in phy_pipe_clk_register()
1152 struct platform_device *pdev = to_platform_device(qmp->dev); in qmp_usb_legacy_parse_dt_legacy()
1153 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_parse_dt_legacy()
1154 struct device *dev = qmp->dev; in qmp_usb_legacy_parse_dt_legacy()
1156 qmp->serdes = devm_platform_ioremap_resource(pdev, 0); in qmp_usb_legacy_parse_dt_legacy()
1157 if (IS_ERR(qmp->serdes)) in qmp_usb_legacy_parse_dt_legacy()
1158 return PTR_ERR(qmp->serdes); in qmp_usb_legacy_parse_dt_legacy()
1160 qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); in qmp_usb_legacy_parse_dt_legacy()
1161 if (IS_ERR(qmp->dp_com)) in qmp_usb_legacy_parse_dt_legacy()
1162 return PTR_ERR(qmp->dp_com); in qmp_usb_legacy_parse_dt_legacy()
1166 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. in qmp_usb_legacy_parse_dt_legacy()
1167 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 in qmp_usb_legacy_parse_dt_legacy()
1168 * For single lane PHYs: pcs_misc (optional) -> 3. in qmp_usb_legacy_parse_dt_legacy()
1170 qmp->tx = devm_of_iomap(dev, np, 0, NULL); in qmp_usb_legacy_parse_dt_legacy()
1171 if (IS_ERR(qmp->tx)) in qmp_usb_legacy_parse_dt_legacy()
1172 return PTR_ERR(qmp->tx); in qmp_usb_legacy_parse_dt_legacy()
1174 qmp->rx = devm_of_iomap(dev, np, 1, NULL); in qmp_usb_legacy_parse_dt_legacy()
1175 if (IS_ERR(qmp->rx)) in qmp_usb_legacy_parse_dt_legacy()
1176 return PTR_ERR(qmp->rx); in qmp_usb_legacy_parse_dt_legacy()
1178 qmp->pcs = devm_of_iomap(dev, np, 2, NULL); in qmp_usb_legacy_parse_dt_legacy()
1179 if (IS_ERR(qmp->pcs)) in qmp_usb_legacy_parse_dt_legacy()
1180 return PTR_ERR(qmp->pcs); in qmp_usb_legacy_parse_dt_legacy()
1182 if (cfg->pcs_usb_offset) in qmp_usb_legacy_parse_dt_legacy()
1183 qmp->pcs_usb = qmp->pcs + cfg->pcs_usb_offset; in qmp_usb_legacy_parse_dt_legacy()
1185 qmp->tx2 = devm_of_iomap(dev, np, 3, NULL); in qmp_usb_legacy_parse_dt_legacy()
1186 if (IS_ERR(qmp->tx2)) in qmp_usb_legacy_parse_dt_legacy()
1187 return PTR_ERR(qmp->tx2); in qmp_usb_legacy_parse_dt_legacy()
1189 qmp->rx2 = devm_of_iomap(dev, np, 4, NULL); in qmp_usb_legacy_parse_dt_legacy()
1190 if (IS_ERR(qmp->rx2)) in qmp_usb_legacy_parse_dt_legacy()
1191 return PTR_ERR(qmp->rx2); in qmp_usb_legacy_parse_dt_legacy()
1193 qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL); in qmp_usb_legacy_parse_dt_legacy()
1194 if (IS_ERR(qmp->pcs_misc)) { in qmp_usb_legacy_parse_dt_legacy()
1195 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qmp_usb_legacy_parse_dt_legacy()
1196 qmp->pcs_misc = NULL; in qmp_usb_legacy_parse_dt_legacy()
1199 qmp->pipe_clk = devm_get_clk_from_child(dev, np, NULL); in qmp_usb_legacy_parse_dt_legacy()
1200 if (IS_ERR(qmp->pipe_clk)) { in qmp_usb_legacy_parse_dt_legacy()
1201 return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), in qmp_usb_legacy_parse_dt_legacy()
1210 struct platform_device *pdev = to_platform_device(qmp->dev); in qmp_usb_legacy_parse_dt()
1211 const struct qmp_phy_cfg *cfg = qmp->cfg; in qmp_usb_legacy_parse_dt()
1212 const struct qmp_usb_legacy_offsets *offs = cfg->offsets; in qmp_usb_legacy_parse_dt()
1213 struct device *dev = qmp->dev; in qmp_usb_legacy_parse_dt()
1217 return -EINVAL; in qmp_usb_legacy_parse_dt()
1223 qmp->serdes = base + offs->serdes; in qmp_usb_legacy_parse_dt()
1224 qmp->pcs = base + offs->pcs; in qmp_usb_legacy_parse_dt()
1225 qmp->pcs_usb = base + offs->pcs_usb; in qmp_usb_legacy_parse_dt()
1226 qmp->tx = base + offs->tx; in qmp_usb_legacy_parse_dt()
1227 qmp->rx = base + offs->rx; in qmp_usb_legacy_parse_dt()
1229 qmp->pipe_clk = devm_clk_get(dev, "pipe"); in qmp_usb_legacy_parse_dt()
1230 if (IS_ERR(qmp->pipe_clk)) { in qmp_usb_legacy_parse_dt()
1231 return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk), in qmp_usb_legacy_parse_dt()
1240 struct device *dev = &pdev->dev; in qmp_usb_legacy_probe()
1248 return -ENOMEM; in qmp_usb_legacy_probe()
1250 qmp->dev = dev; in qmp_usb_legacy_probe()
1253 qmp->cfg = of_device_get_match_data(dev); in qmp_usb_legacy_probe()
1254 if (!qmp->cfg) in qmp_usb_legacy_probe()
1255 return -EINVAL; in qmp_usb_legacy_probe()
1270 np = of_get_next_available_child(dev->of_node, NULL); in qmp_usb_legacy_probe()
1274 np = of_node_get(dev->of_node); in qmp_usb_legacy_probe()
1294 qmp->phy = devm_phy_create(dev, np, &qmp_usb_legacy_phy_ops); in qmp_usb_legacy_probe()
1295 if (IS_ERR(qmp->phy)) { in qmp_usb_legacy_probe()
1296 ret = PTR_ERR(qmp->phy); in qmp_usb_legacy_probe()
1301 phy_set_drvdata(qmp->phy, qmp); in qmp_usb_legacy_probe()
1316 .compatible = "qcom,sc7180-qmp-usb3-phy",
1319 .compatible = "qcom,sc8180x-qmp-usb3-phy",
1322 .compatible = "qcom,sdm845-qmp-usb3-phy",
1325 .compatible = "qcom,sm8150-qmp-usb3-phy",
1328 .compatible = "qcom,sm8250-qmp-usb3-phy",
1331 .compatible = "qcom,sm8350-qmp-usb3-phy",
1334 .compatible = "qcom,sm8450-qmp-usb3-phy",
1344 .name = "qcom-qmp-usb-legacy-phy",