Lines Matching +full:gcc +full:- +full:ipq8074
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"
80 * if yes, then offset gives index in the reg-layout
98 /* set of registers with offsets different per-PHY */
604 /* struct qmp_phy_cfg - per-PHY initialization config */
606 /* phy-type - PCIE/UFS/USB */
611 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
657 * struct qmp_phy - per-lane phy descriptor
682 * struct qcom_qmp - structure holding QMP phy block attributes
693 * @phys: array of per-lane phy descriptors
761 "vdda-phy", "vdda-pll",
933 if (t->in_layout) in qcom_qmp_phy_configure()
934 writel(t->val, base + regs[t->offset]); in qcom_qmp_phy_configure()
936 writel(t->val, base + t->offset); in qcom_qmp_phy_configure()
942 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_com_init()
943 void __iomem *serdes = qmp->serdes; in qcom_qmp_phy_com_init()
944 void __iomem *dp_com = qmp->dp_com; in qcom_qmp_phy_com_init()
947 mutex_lock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
948 if (qmp->init_count++) { in qcom_qmp_phy_com_init()
949 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
954 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_init()
956 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qcom_qmp_phy_com_init()
960 for (i = 0; i < cfg->num_resets; i++) { in qcom_qmp_phy_com_init()
961 ret = reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_init()
963 dev_err(qmp->dev, "%s reset assert failed\n", in qcom_qmp_phy_com_init()
964 cfg->reset_list[i]); in qcom_qmp_phy_com_init()
969 for (i = cfg->num_resets - 1; i >= 0; i--) { in qcom_qmp_phy_com_init()
970 ret = reset_control_deassert(qmp->resets[i]); in qcom_qmp_phy_com_init()
972 dev_err(qmp->dev, "%s reset deassert failed\n", in qcom_qmp_phy_com_init()
973 qmp->cfg->reset_list[i]); in qcom_qmp_phy_com_init()
978 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_init()
980 dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); in qcom_qmp_phy_com_init()
984 if (cfg->has_phy_com_ctrl) in qcom_qmp_phy_com_init()
985 qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_init()
988 if (cfg->has_phy_dp_com_ctrl) { in qcom_qmp_phy_com_init()
1006 qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl, in qcom_qmp_phy_com_init()
1007 cfg->serdes_tbl_num); in qcom_qmp_phy_com_init()
1009 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_com_init()
1013 qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); in qcom_qmp_phy_com_init()
1014 qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], in qcom_qmp_phy_com_init()
1017 status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; in qcom_qmp_phy_com_init()
1018 mask = cfg->mask_com_pcs_ready; in qcom_qmp_phy_com_init()
1023 dev_err(qmp->dev, in qcom_qmp_phy_com_init()
1024 "phy common block init timed-out\n"); in qcom_qmp_phy_com_init()
1029 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
1034 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_init()
1036 while (++i < cfg->num_resets) in qcom_qmp_phy_com_init()
1037 reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_init()
1039 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_init()
1041 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_init()
1048 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_com_exit()
1049 void __iomem *serdes = qmp->serdes; in qcom_qmp_phy_com_exit()
1050 int i = cfg->num_resets; in qcom_qmp_phy_com_exit()
1052 mutex_lock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
1053 if (--qmp->init_count) { in qcom_qmp_phy_com_exit()
1054 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
1058 if (cfg->has_phy_com_ctrl) { in qcom_qmp_phy_com_exit()
1059 qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], in qcom_qmp_phy_com_exit()
1061 qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], in qcom_qmp_phy_com_exit()
1063 qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], in qcom_qmp_phy_com_exit()
1067 while (--i >= 0) in qcom_qmp_phy_com_exit()
1068 reset_control_assert(qmp->resets[i]); in qcom_qmp_phy_com_exit()
1070 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_com_exit()
1072 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qcom_qmp_phy_com_exit()
1074 mutex_unlock(&qmp->phy_mutex); in qcom_qmp_phy_com_exit()
1083 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_init()
1084 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_init()
1085 void __iomem *tx = qphy->tx; in qcom_qmp_phy_init()
1086 void __iomem *rx = qphy->rx; in qcom_qmp_phy_init()
1087 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_init()
1088 void __iomem *dp_com = qmp->dp_com; in qcom_qmp_phy_init()
1093 dev_vdbg(qmp->dev, "Initializing QMP phy\n"); in qcom_qmp_phy_init()
1099 if (cfg->has_lane_rst) { in qcom_qmp_phy_init()
1100 ret = reset_control_deassert(qphy->lane_rst); in qcom_qmp_phy_init()
1102 dev_err(qmp->dev, "lane%d reset deassert failed\n", in qcom_qmp_phy_init()
1103 qphy->index); in qcom_qmp_phy_init()
1108 ret = clk_prepare_enable(qphy->pipe_clk); in qcom_qmp_phy_init()
1110 dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); in qcom_qmp_phy_init()
1115 qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); in qcom_qmp_phy_init()
1116 /* Configuration for other LANE for USB-DP combo PHY */ in qcom_qmp_phy_init()
1117 if (cfg->has_phy_dp_com_ctrl) in qcom_qmp_phy_init()
1118 qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs, in qcom_qmp_phy_init()
1119 cfg->tx_tbl, cfg->tx_tbl_num); in qcom_qmp_phy_init()
1121 qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num); in qcom_qmp_phy_init()
1122 if (cfg->has_phy_dp_com_ctrl) in qcom_qmp_phy_init()
1123 qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs, in qcom_qmp_phy_init()
1124 cfg->rx_tbl, cfg->rx_tbl_num); in qcom_qmp_phy_init()
1126 qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qcom_qmp_phy_init()
1130 * This is active low enable signal to power-down PHY. in qcom_qmp_phy_init()
1132 qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); in qcom_qmp_phy_init()
1134 if (cfg->has_pwrdn_delay) in qcom_qmp_phy_init()
1135 usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); in qcom_qmp_phy_init()
1138 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qcom_qmp_phy_init()
1139 if (cfg->has_phy_dp_com_ctrl) in qcom_qmp_phy_init()
1142 /* start SerDes and Phy-Coding-Sublayer */ in qcom_qmp_phy_init()
1143 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qcom_qmp_phy_init()
1145 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; in qcom_qmp_phy_init()
1146 mask = cfg->mask_pcs_ready; in qcom_qmp_phy_init()
1151 dev_err(qmp->dev, "phy initialization timed-out\n"); in qcom_qmp_phy_init()
1154 qmp->phy_initialized = true; in qcom_qmp_phy_init()
1159 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_init()
1161 if (cfg->has_lane_rst) in qcom_qmp_phy_init()
1162 reset_control_assert(qphy->lane_rst); in qcom_qmp_phy_init()
1172 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_exit()
1173 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_exit()
1175 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_exit()
1178 qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qcom_qmp_phy_exit()
1180 /* stop SerDes and Phy-Coding-Sublayer */ in qcom_qmp_phy_exit()
1181 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qcom_qmp_phy_exit()
1184 qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); in qcom_qmp_phy_exit()
1186 if (cfg->has_lane_rst) in qcom_qmp_phy_exit()
1187 reset_control_assert(qphy->lane_rst); in qcom_qmp_phy_exit()
1191 qmp->phy_initialized = false; in qcom_qmp_phy_exit()
1199 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_set_mode()
1201 qmp->mode = mode; in qcom_qmp_phy_set_mode()
1208 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_enable_autonomous_mode()
1209 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_enable_autonomous_mode()
1210 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_enable_autonomous_mode()
1211 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_enable_autonomous_mode()
1214 if (qmp->mode == PHY_MODE_USB_HOST_SS || in qcom_qmp_phy_enable_autonomous_mode()
1215 qmp->mode == PHY_MODE_USB_DEVICE_SS) in qcom_qmp_phy_enable_autonomous_mode()
1221 qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_enable_autonomous_mode()
1223 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_enable_autonomous_mode()
1225 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qcom_qmp_phy_enable_autonomous_mode()
1229 qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); in qcom_qmp_phy_enable_autonomous_mode()
1238 struct qcom_qmp *qmp = qphy->qmp; in qcom_qmp_phy_disable_autonomous_mode()
1239 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_disable_autonomous_mode()
1240 void __iomem *pcs = qphy->pcs; in qcom_qmp_phy_disable_autonomous_mode()
1241 void __iomem *pcs_misc = qphy->pcs_misc; in qcom_qmp_phy_disable_autonomous_mode()
1247 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qcom_qmp_phy_disable_autonomous_mode()
1250 qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_disable_autonomous_mode()
1252 qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qcom_qmp_phy_disable_autonomous_mode()
1258 struct qmp_phy *qphy = qmp->phys[0]; in qcom_qmp_phy_runtime_suspend()
1259 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_runtime_suspend()
1261 dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode); in qcom_qmp_phy_runtime_suspend()
1264 if (cfg->type != PHY_TYPE_USB3) in qcom_qmp_phy_runtime_suspend()
1267 if (!qmp->phy_initialized) { in qcom_qmp_phy_runtime_suspend()
1274 clk_disable_unprepare(qphy->pipe_clk); in qcom_qmp_phy_runtime_suspend()
1275 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_suspend()
1283 struct qmp_phy *qphy = qmp->phys[0]; in qcom_qmp_phy_runtime_resume()
1284 const struct qmp_phy_cfg *cfg = qmp->cfg; in qcom_qmp_phy_runtime_resume()
1287 dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode); in qcom_qmp_phy_runtime_resume()
1290 if (cfg->type != PHY_TYPE_USB3) in qcom_qmp_phy_runtime_resume()
1293 if (!qmp->phy_initialized) { in qcom_qmp_phy_runtime_resume()
1298 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_resume()
1300 dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret); in qcom_qmp_phy_runtime_resume()
1304 ret = clk_prepare_enable(qphy->pipe_clk); in qcom_qmp_phy_runtime_resume()
1307 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qcom_qmp_phy_runtime_resume()
1319 int num = qmp->cfg->num_vregs; in qcom_qmp_phy_vreg_init()
1322 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qcom_qmp_phy_vreg_init()
1323 if (!qmp->vregs) in qcom_qmp_phy_vreg_init()
1324 return -ENOMEM; in qcom_qmp_phy_vreg_init()
1327 qmp->vregs[i].supply = qmp->cfg->vreg_list[i]; in qcom_qmp_phy_vreg_init()
1329 return devm_regulator_bulk_get(dev, num, qmp->vregs); in qcom_qmp_phy_vreg_init()
1337 qmp->resets = devm_kcalloc(dev, qmp->cfg->num_resets, in qcom_qmp_phy_reset_init()
1338 sizeof(*qmp->resets), GFP_KERNEL); in qcom_qmp_phy_reset_init()
1339 if (!qmp->resets) in qcom_qmp_phy_reset_init()
1340 return -ENOMEM; in qcom_qmp_phy_reset_init()
1342 for (i = 0; i < qmp->cfg->num_resets; i++) { in qcom_qmp_phy_reset_init()
1344 const char *name = qmp->cfg->reset_list[i]; in qcom_qmp_phy_reset_init()
1351 qmp->resets[i] = rst; in qcom_qmp_phy_reset_init()
1360 int num = qmp->cfg->num_clks; in qcom_qmp_phy_clk_init()
1363 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qcom_qmp_phy_clk_init()
1364 if (!qmp->clks) in qcom_qmp_phy_clk_init()
1365 return -ENOMEM; in qcom_qmp_phy_clk_init()
1368 qmp->clks[i].id = qmp->cfg->clk_list[i]; in qcom_qmp_phy_clk_init()
1370 return devm_clk_bulk_get(dev, num, qmp->clks); in qcom_qmp_phy_clk_init()
1376 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
1377 * controls it. The <s>_pipe_clk coming out of the GCC is requested
1379 * We register the <s>_pipe_clksrc here. The gcc driver takes care
1383 * +---------------+
1384 * | PHY block |<<---------------------------------------+
1386 * | +-------+ | +-----+ |
1387 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
1388 * clk | +-------+ | +-----+
1389 * +---------------+
1397 if ((qmp->cfg->type != PHY_TYPE_USB3) && in phy_pipe_clk_register()
1398 (qmp->cfg->type != PHY_TYPE_PCIE)) { in phy_pipe_clk_register()
1403 ret = of_property_read_string(np, "clock-output-names", &init.name); in phy_pipe_clk_register()
1405 dev_err(qmp->dev, "%s: No clock-output-names\n", np->name); in phy_pipe_clk_register()
1409 fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); in phy_pipe_clk_register()
1411 return -ENOMEM; in phy_pipe_clk_register()
1416 fixed->fixed_rate = 125000000; in phy_pipe_clk_register()
1417 fixed->hw.init = &init; in phy_pipe_clk_register()
1419 return devm_clk_hw_register(qmp->dev, &fixed->hw); in phy_pipe_clk_register()
1440 return -ENOMEM; in qcom_qmp_phy_create()
1444 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; and in qcom_qmp_phy_create()
1445 * pcs_misc (optional) -> 3. in qcom_qmp_phy_create()
1447 qphy->tx = of_iomap(np, 0); in qcom_qmp_phy_create()
1448 if (!qphy->tx) in qcom_qmp_phy_create()
1449 return -ENOMEM; in qcom_qmp_phy_create()
1451 qphy->rx = of_iomap(np, 1); in qcom_qmp_phy_create()
1452 if (!qphy->rx) in qcom_qmp_phy_create()
1453 return -ENOMEM; in qcom_qmp_phy_create()
1455 qphy->pcs = of_iomap(np, 2); in qcom_qmp_phy_create()
1456 if (!qphy->pcs) in qcom_qmp_phy_create()
1457 return -ENOMEM; in qcom_qmp_phy_create()
1459 qphy->pcs_misc = of_iomap(np, 3); in qcom_qmp_phy_create()
1460 if (!qphy->pcs_misc) in qcom_qmp_phy_create()
1461 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qcom_qmp_phy_create()
1471 qphy->pipe_clk = of_clk_get_by_name(np, prop_name); in qcom_qmp_phy_create()
1472 if (IS_ERR(qphy->pipe_clk)) { in qcom_qmp_phy_create()
1473 if (qmp->cfg->type == PHY_TYPE_PCIE || in qcom_qmp_phy_create()
1474 qmp->cfg->type == PHY_TYPE_USB3) { in qcom_qmp_phy_create()
1475 ret = PTR_ERR(qphy->pipe_clk); in qcom_qmp_phy_create()
1476 if (ret != -EPROBE_DEFER) in qcom_qmp_phy_create()
1482 qphy->pipe_clk = NULL; in qcom_qmp_phy_create()
1486 if (qmp->cfg->has_lane_rst) { in qcom_qmp_phy_create()
1488 qphy->lane_rst = of_reset_control_get(np, prop_name); in qcom_qmp_phy_create()
1489 if (IS_ERR(qphy->lane_rst)) { in qcom_qmp_phy_create()
1491 return PTR_ERR(qphy->lane_rst); in qcom_qmp_phy_create()
1502 qphy->phy = generic_phy; in qcom_qmp_phy_create()
1503 qphy->index = id; in qcom_qmp_phy_create()
1504 qphy->qmp = qmp; in qcom_qmp_phy_create()
1505 qmp->phys[id] = qphy; in qcom_qmp_phy_create()
1513 .compatible = "qcom,msm8996-qmp-pcie-phy",
1516 .compatible = "qcom,msm8996-qmp-usb3-phy",
1519 .compatible = "qcom,ipq8074-qmp-pcie-phy",
1522 .compatible = "qcom,sdm845-qmp-usb3-phy",
1525 .compatible = "qcom,sdm845-qmp-usb3-uni-phy",
1540 struct device *dev = &pdev->dev; in qcom_qmp_phy_probe()
1550 return -ENOMEM; in qcom_qmp_phy_probe()
1552 qmp->dev = dev; in qcom_qmp_phy_probe()
1556 qmp->cfg = of_device_get_match_data(dev); in qcom_qmp_phy_probe()
1557 if (!qmp->cfg) in qcom_qmp_phy_probe()
1558 return -EINVAL; in qcom_qmp_phy_probe()
1566 qmp->serdes = base; in qcom_qmp_phy_probe()
1569 if (qmp->cfg->has_phy_dp_com_ctrl) { in qcom_qmp_phy_probe()
1576 qmp->dp_com = base; in qcom_qmp_phy_probe()
1579 mutex_init(&qmp->phy_mutex); in qcom_qmp_phy_probe()
1595 num = of_get_available_child_count(dev->of_node); in qcom_qmp_phy_probe()
1597 if (num > qmp->cfg->nlanes) in qcom_qmp_phy_probe()
1598 return -EINVAL; in qcom_qmp_phy_probe()
1600 qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); in qcom_qmp_phy_probe()
1601 if (!qmp->phys) in qcom_qmp_phy_probe()
1602 return -ENOMEM; in qcom_qmp_phy_probe()
1613 for_each_available_child_of_node(dev->of_node, child) { in qcom_qmp_phy_probe()
1614 /* Create per-lane phy */ in qcom_qmp_phy_probe()
1629 dev_err(qmp->dev, in qcom_qmp_phy_probe()
1639 dev_info(dev, "Registered Qcom-QMP phy\n"); in qcom_qmp_phy_probe()
1649 .name = "qcom-qmp-phy",