Lines Matching +full:gcc +full:- +full:sdx55
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"
74 * if yes, then offset gives index in the reg-layout
106 /* set of registers with offsets different per-PHY */
1430 /* struct qmp_phy_cfg - per-PHY initialization config */
1434 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
1478 * struct qmp_phy - per-lane phy descriptor
1511 * struct qcom_qmp - structure holding QMP phy block attributes
1520 * @phys: array of per-lane phy descriptors
1575 /* usb3 phy on sdx55 doesn't have com_aux clock */
1599 "vdda-phy", "vdda-pll",
2082 if (!(t->lane_mask & lane_mask)) in qmp_usb_configure_lane()
2085 if (t->in_layout) in qmp_usb_configure_lane()
2086 writel(t->val, base + regs[t->offset]); in qmp_usb_configure_lane()
2088 writel(t->val, base + t->offset); in qmp_usb_configure_lane()
2102 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_serdes_init()
2103 void __iomem *serdes = qphy->serdes; in qmp_usb_serdes_init()
2104 const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; in qmp_usb_serdes_init()
2105 int serdes_tbl_num = cfg->serdes_tbl_num; in qmp_usb_serdes_init()
2107 qmp_usb_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); in qmp_usb_serdes_init()
2115 struct qcom_qmp *qmp = qphy->qmp; in qmp_usb_init()
2116 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_init()
2117 void __iomem *pcs = qphy->pcs; in qmp_usb_init()
2118 void __iomem *dp_com = qmp->dp_com; in qmp_usb_init()
2122 ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); in qmp_usb_init()
2124 dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); in qmp_usb_init()
2128 ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_usb_init()
2130 dev_err(qmp->dev, "reset assert failed\n"); in qmp_usb_init()
2134 ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets); in qmp_usb_init()
2136 dev_err(qmp->dev, "reset deassert failed\n"); in qmp_usb_init()
2140 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qmp_usb_init()
2144 if (cfg->has_phy_dp_com_ctrl) { in qmp_usb_init()
2152 /* Default type-c orientation, i.e CC1 */ in qmp_usb_init()
2167 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) in qmp_usb_init()
2169 cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_usb_init()
2170 cfg->pwrdn_ctrl); in qmp_usb_init()
2173 cfg->pwrdn_ctrl); in qmp_usb_init()
2178 reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_usb_init()
2180 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_usb_init()
2188 struct qcom_qmp *qmp = qphy->qmp; in qmp_usb_exit()
2189 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_exit()
2191 reset_control_bulk_assert(cfg->num_resets, qmp->resets); in qmp_usb_exit()
2193 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_usb_exit()
2195 regulator_bulk_disable(cfg->num_vregs, qmp->vregs); in qmp_usb_exit()
2203 struct qcom_qmp *qmp = qphy->qmp; in qmp_usb_power_on()
2204 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_power_on()
2205 void __iomem *tx = qphy->tx; in qmp_usb_power_on()
2206 void __iomem *rx = qphy->rx; in qmp_usb_power_on()
2207 void __iomem *pcs = qphy->pcs; in qmp_usb_power_on()
2214 ret = clk_prepare_enable(qphy->pipe_clk); in qmp_usb_power_on()
2216 dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); in qmp_usb_power_on()
2221 qmp_usb_configure_lane(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num, 1); in qmp_usb_power_on()
2223 if (cfg->lanes >= 2) { in qmp_usb_power_on()
2224 qmp_usb_configure_lane(qphy->tx2, cfg->regs, in qmp_usb_power_on()
2225 cfg->tx_tbl, cfg->tx_tbl_num, 2); in qmp_usb_power_on()
2228 qmp_usb_configure_lane(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num, 1); in qmp_usb_power_on()
2230 if (cfg->lanes >= 2) { in qmp_usb_power_on()
2231 qmp_usb_configure_lane(qphy->rx2, cfg->regs, in qmp_usb_power_on()
2232 cfg->rx_tbl, cfg->rx_tbl_num, 2); in qmp_usb_power_on()
2236 qmp_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); in qmp_usb_power_on()
2238 if (cfg->has_pwrdn_delay) in qmp_usb_power_on()
2239 usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); in qmp_usb_power_on()
2242 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_usb_power_on()
2244 /* start SerDes and Phy-Coding-Sublayer */ in qmp_usb_power_on()
2245 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qmp_usb_power_on()
2247 status = pcs + cfg->regs[QPHY_PCS_STATUS]; in qmp_usb_power_on()
2248 mask = cfg->phy_status; in qmp_usb_power_on()
2254 dev_err(qmp->dev, "phy initialization timed-out\n"); in qmp_usb_power_on()
2261 clk_disable_unprepare(qphy->pipe_clk); in qmp_usb_power_on()
2269 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_power_off()
2271 clk_disable_unprepare(qphy->pipe_clk); in qmp_usb_power_off()
2274 qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); in qmp_usb_power_off()
2276 /* stop SerDes and Phy-Coding-Sublayer */ in qmp_usb_power_off()
2277 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); in qmp_usb_power_off()
2280 if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { in qmp_usb_power_off()
2281 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], in qmp_usb_power_off()
2282 cfg->pwrdn_ctrl); in qmp_usb_power_off()
2284 qphy_clrbits(qphy->pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, in qmp_usb_power_off()
2285 cfg->pwrdn_ctrl); in qmp_usb_power_off()
2320 qphy->mode = mode; in qmp_usb_set_mode()
2327 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_enable_autonomous_mode()
2328 void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs; in qmp_usb_enable_autonomous_mode()
2329 void __iomem *pcs_misc = qphy->pcs_misc; in qmp_usb_enable_autonomous_mode()
2332 if (qphy->mode == PHY_MODE_USB_HOST_SS || in qmp_usb_enable_autonomous_mode()
2333 qphy->mode == PHY_MODE_USB_DEVICE_SS) in qmp_usb_enable_autonomous_mode()
2339 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_enable_autonomous_mode()
2341 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_enable_autonomous_mode()
2343 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qmp_usb_enable_autonomous_mode()
2347 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); in qmp_usb_enable_autonomous_mode()
2356 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_disable_autonomous_mode()
2357 void __iomem *pcs_usb = qphy->pcs_usb ?: qphy->pcs; in qmp_usb_disable_autonomous_mode()
2358 void __iomem *pcs_misc = qphy->pcs_misc; in qmp_usb_disable_autonomous_mode()
2364 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], in qmp_usb_disable_autonomous_mode()
2367 qphy_setbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_disable_autonomous_mode()
2369 qphy_clrbits(pcs_usb, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); in qmp_usb_disable_autonomous_mode()
2375 struct qmp_phy *qphy = qmp->phys[0]; in qmp_usb_runtime_suspend()
2376 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_runtime_suspend()
2378 dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); in qmp_usb_runtime_suspend()
2380 if (!qphy->phy->init_count) { in qmp_usb_runtime_suspend()
2387 clk_disable_unprepare(qphy->pipe_clk); in qmp_usb_runtime_suspend()
2388 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_usb_runtime_suspend()
2396 struct qmp_phy *qphy = qmp->phys[0]; in qmp_usb_runtime_resume()
2397 const struct qmp_phy_cfg *cfg = qphy->cfg; in qmp_usb_runtime_resume()
2400 dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); in qmp_usb_runtime_resume()
2402 if (!qphy->phy->init_count) { in qmp_usb_runtime_resume()
2407 ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); in qmp_usb_runtime_resume()
2411 ret = clk_prepare_enable(qphy->pipe_clk); in qmp_usb_runtime_resume()
2414 clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); in qmp_usb_runtime_resume()
2426 int num = cfg->num_vregs; in qmp_usb_vreg_init()
2429 qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); in qmp_usb_vreg_init()
2430 if (!qmp->vregs) in qmp_usb_vreg_init()
2431 return -ENOMEM; in qmp_usb_vreg_init()
2434 qmp->vregs[i].supply = cfg->vreg_list[i]; in qmp_usb_vreg_init()
2436 return devm_regulator_bulk_get(dev, num, qmp->vregs); in qmp_usb_vreg_init()
2445 qmp->resets = devm_kcalloc(dev, cfg->num_resets, in qmp_usb_reset_init()
2446 sizeof(*qmp->resets), GFP_KERNEL); in qmp_usb_reset_init()
2447 if (!qmp->resets) in qmp_usb_reset_init()
2448 return -ENOMEM; in qmp_usb_reset_init()
2450 for (i = 0; i < cfg->num_resets; i++) in qmp_usb_reset_init()
2451 qmp->resets[i].id = cfg->reset_list[i]; in qmp_usb_reset_init()
2453 ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets); in qmp_usb_reset_init()
2463 int num = cfg->num_clks; in qmp_usb_clk_init()
2466 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); in qmp_usb_clk_init()
2467 if (!qmp->clks) in qmp_usb_clk_init()
2468 return -ENOMEM; in qmp_usb_clk_init()
2471 qmp->clks[i].id = cfg->clk_list[i]; in qmp_usb_clk_init()
2473 return devm_clk_bulk_get(dev, num, qmp->clks); in qmp_usb_clk_init()
2484 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
2485 * controls it. The <s>_pipe_clk coming out of the GCC is requested
2487 * We register the <s>_pipe_clksrc here. The gcc driver takes care
2491 * +---------------+
2492 * | PHY block |<<---------------------------------------+
2494 * | +-------+ | +-----+ |
2495 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
2496 * clk | +-------+ | +-----+
2497 * +---------------+
2505 ret = of_property_read_string(np, "clock-output-names", &init.name); in phy_pipe_clk_register()
2507 dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); in phy_pipe_clk_register()
2511 fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); in phy_pipe_clk_register()
2513 return -ENOMEM; in phy_pipe_clk_register()
2518 fixed->fixed_rate = 125000000; in phy_pipe_clk_register()
2519 fixed->hw.init = &init; in phy_pipe_clk_register()
2521 ret = devm_clk_hw_register(qmp->dev, &fixed->hw); in phy_pipe_clk_register()
2525 ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); in phy_pipe_clk_register()
2533 return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); in phy_pipe_clk_register()
2550 return IOMEM_ERR_PTR(-EINVAL); in qmp_usb_iomap()
2572 if (of_device_is_compatible(dev->of_node, "qcom,sdx65-qmp-usb3-uni-phy")) in qmp_usb_create()
2574 if (of_device_is_compatible(dev->of_node, "qcom,sm8350-qmp-usb3-uni-phy")) in qmp_usb_create()
2579 return -ENOMEM; in qmp_usb_create()
2581 qphy->cfg = cfg; in qmp_usb_create()
2582 qphy->serdes = serdes; in qmp_usb_create()
2585 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. in qmp_usb_create()
2586 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 in qmp_usb_create()
2587 * For single lane PHYs: pcs_misc (optional) -> 3. in qmp_usb_create()
2589 qphy->tx = devm_of_iomap(dev, np, 0, NULL); in qmp_usb_create()
2590 if (IS_ERR(qphy->tx)) in qmp_usb_create()
2591 return PTR_ERR(qphy->tx); in qmp_usb_create()
2593 qphy->rx = devm_of_iomap(dev, np, 1, NULL); in qmp_usb_create()
2594 if (IS_ERR(qphy->rx)) in qmp_usb_create()
2595 return PTR_ERR(qphy->rx); in qmp_usb_create()
2597 qphy->pcs = qmp_usb_iomap(dev, np, 2, exclusive); in qmp_usb_create()
2598 if (IS_ERR(qphy->pcs)) in qmp_usb_create()
2599 return PTR_ERR(qphy->pcs); in qmp_usb_create()
2601 if (cfg->pcs_usb_offset) in qmp_usb_create()
2602 qphy->pcs_usb = qphy->pcs + cfg->pcs_usb_offset; in qmp_usb_create()
2604 if (cfg->lanes >= 2) { in qmp_usb_create()
2605 qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); in qmp_usb_create()
2606 if (IS_ERR(qphy->tx2)) in qmp_usb_create()
2607 return PTR_ERR(qphy->tx2); in qmp_usb_create()
2609 qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); in qmp_usb_create()
2610 if (IS_ERR(qphy->rx2)) in qmp_usb_create()
2611 return PTR_ERR(qphy->rx2); in qmp_usb_create()
2613 qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); in qmp_usb_create()
2615 qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); in qmp_usb_create()
2618 if (IS_ERR(qphy->pcs_misc)) { in qmp_usb_create()
2619 dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); in qmp_usb_create()
2620 qphy->pcs_misc = NULL; in qmp_usb_create()
2623 qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); in qmp_usb_create()
2624 if (IS_ERR(qphy->pipe_clk)) { in qmp_usb_create()
2625 return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), in qmp_usb_create()
2636 qphy->phy = generic_phy; in qmp_usb_create()
2637 qphy->qmp = qmp; in qmp_usb_create()
2638 qmp->phys[id] = qphy; in qmp_usb_create()
2646 .compatible = "qcom,ipq8074-qmp-usb3-phy",
2649 .compatible = "qcom,msm8996-qmp-usb3-phy",
2652 .compatible = "qcom,ipq6018-qmp-usb3-phy",
2655 .compatible = "qcom,sc7180-qmp-usb3-phy",
2658 .compatible = "qcom,sc8180x-qmp-usb3-phy",
2661 .compatible = "qcom,sc8280xp-qmp-usb3-uni-phy",
2664 .compatible = "qcom,sdm845-qmp-usb3-phy",
2667 .compatible = "qcom,sdm845-qmp-usb3-uni-phy",
2670 .compatible = "qcom,msm8998-qmp-usb3-phy",
2673 .compatible = "qcom,sm8150-qmp-usb3-phy",
2676 .compatible = "qcom,sm8150-qmp-usb3-uni-phy",
2679 .compatible = "qcom,sm8250-qmp-usb3-phy",
2682 .compatible = "qcom,sm8250-qmp-usb3-uni-phy",
2685 .compatible = "qcom,sdx55-qmp-usb3-uni-phy",
2688 .compatible = "qcom,sdx65-qmp-usb3-uni-phy",
2691 .compatible = "qcom,sm8350-qmp-usb3-phy",
2694 .compatible = "qcom,sm8350-qmp-usb3-uni-phy",
2697 .compatible = "qcom,sm8450-qmp-usb3-phy",
2700 .compatible = "qcom,qcm2290-qmp-usb3-phy",
2715 struct device *dev = &pdev->dev; in qmp_usb_probe()
2725 return -ENOMEM; in qmp_usb_probe()
2727 qmp->dev = dev; in qmp_usb_probe()
2733 return -EINVAL; in qmp_usb_probe()
2741 if (cfg->has_phy_dp_com_ctrl) { in qmp_usb_probe()
2742 qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); in qmp_usb_probe()
2743 if (IS_ERR(qmp->dp_com)) in qmp_usb_probe()
2744 return PTR_ERR(qmp->dp_com); in qmp_usb_probe()
2760 num = of_get_available_child_count(dev->of_node); in qmp_usb_probe()
2763 return -EINVAL; in qmp_usb_probe()
2765 qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); in qmp_usb_probe()
2766 if (!qmp->phys) in qmp_usb_probe()
2767 return -ENOMEM; in qmp_usb_probe()
2780 for_each_available_child_of_node(dev->of_node, child) { in qmp_usb_probe()
2781 /* Create per-lane phy */ in qmp_usb_probe()
2795 dev_err(qmp->dev, in qmp_usb_probe()
2815 .name = "qcom-qmp-usb-phy",