Lines Matching +full:per +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2009-2018, Linux Foundation. All rights reserved.
4 * Copyright (c) 2018-2020, Linaro Limited
14 #include <linux/phy/phy.h>
20 /* PHY register and bit definitions */
68 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode, in qcom_snps_hsphy_set_mode() argument
71 struct hsphy_priv *priv = phy_get_drvdata(phy); in qcom_snps_hsphy_set_mode()
73 priv->mode = PHY_MODE_INVALID; in qcom_snps_hsphy_set_mode()
76 priv->mode = mode; in qcom_snps_hsphy_set_mode()
86 val = readb(priv->base + PHY_INTR_CLEAR0); in qcom_snps_hsphy_enable_hv_interrupts()
88 writeb(val, priv->base + PHY_INTR_CLEAR0); in qcom_snps_hsphy_enable_hv_interrupts()
90 writeb(0x0, priv->base + PHY_IRQ_CMD); in qcom_snps_hsphy_enable_hv_interrupts()
92 writeb(0x1, priv->base + PHY_IRQ_CMD); in qcom_snps_hsphy_enable_hv_interrupts()
97 val = readb(priv->base + PHY_INTR_MASK0); in qcom_snps_hsphy_enable_hv_interrupts()
98 switch (priv->mode) { in qcom_snps_hsphy_enable_hv_interrupts()
114 writeb(val, priv->base + PHY_INTR_MASK0); in qcom_snps_hsphy_enable_hv_interrupts()
121 val = readb(priv->base + PHY_INTR_MASK0); in qcom_snps_hsphy_disable_hv_interrupts()
123 writeb(val, priv->base + PHY_INTR_MASK0); in qcom_snps_hsphy_disable_hv_interrupts()
126 val = readb(priv->base + PHY_INTR_CLEAR0); in qcom_snps_hsphy_disable_hv_interrupts()
128 writeb(val, priv->base + PHY_INTR_CLEAR0); in qcom_snps_hsphy_disable_hv_interrupts()
130 writeb(0x0, priv->base + PHY_IRQ_CMD); in qcom_snps_hsphy_disable_hv_interrupts()
133 writeb(0x1, priv->base + PHY_IRQ_CMD); in qcom_snps_hsphy_disable_hv_interrupts()
141 val = readb(priv->base + PHY_CTRL_COMMON0); in qcom_snps_hsphy_enter_retention()
143 writeb(val, priv->base + PHY_CTRL_COMMON0); in qcom_snps_hsphy_enter_retention()
150 val = readb(priv->base + PHY_CTRL_COMMON0); in qcom_snps_hsphy_exit_retention()
152 writeb(val, priv->base + PHY_CTRL_COMMON0); in qcom_snps_hsphy_exit_retention()
155 static int qcom_snps_hsphy_power_on(struct phy *phy) in qcom_snps_hsphy_power_on() argument
157 struct hsphy_priv *priv = phy_get_drvdata(phy); in qcom_snps_hsphy_power_on()
160 ret = regulator_bulk_enable(VREG_NUM, priv->vregs); in qcom_snps_hsphy_power_on()
170 static int qcom_snps_hsphy_power_off(struct phy *phy) in qcom_snps_hsphy_power_off() argument
172 struct hsphy_priv *priv = phy_get_drvdata(phy); in qcom_snps_hsphy_power_off()
176 regulator_bulk_disable(VREG_NUM, priv->vregs); in qcom_snps_hsphy_power_off()
185 ret = reset_control_assert(priv->phy_reset); in qcom_snps_hsphy_reset()
191 ret = reset_control_deassert(priv->phy_reset); in qcom_snps_hsphy_reset()
202 const struct hsphy_data *data = priv->data; in qcom_snps_hsphy_init_sequence()
210 seq = data->init_seq; in qcom_snps_hsphy_init_sequence()
212 for (i = 0; i < data->init_seq_num; i++, seq++) { in qcom_snps_hsphy_init_sequence()
213 writeb(seq->val, priv->base + seq->offset); in qcom_snps_hsphy_init_sequence()
214 if (seq->delay) in qcom_snps_hsphy_init_sequence()
215 usleep_range(seq->delay, seq->delay + 10); in qcom_snps_hsphy_init_sequence()
223 ret = reset_control_assert(priv->por_reset); in qcom_snps_hsphy_por_reset()
228 * The Femto PHY is POR reset in the following scenarios. in qcom_snps_hsphy_por_reset()
231 * 2. Low power mode exit from PHY retention. in qcom_snps_hsphy_por_reset()
233 * Ensure that SIDDQ is cleared before bringing the PHY in qcom_snps_hsphy_por_reset()
239 * As per databook, 10 usec delay is required between in qcom_snps_hsphy_por_reset()
240 * PHY POR assert and de-assert. in qcom_snps_hsphy_por_reset()
243 ret = reset_control_deassert(priv->por_reset); in qcom_snps_hsphy_por_reset()
248 * As per databook, it takes 75 usec for PHY to stabilize in qcom_snps_hsphy_por_reset()
256 static int qcom_snps_hsphy_init(struct phy *phy) in qcom_snps_hsphy_init() argument
258 struct hsphy_priv *priv = phy_get_drvdata(phy); in qcom_snps_hsphy_init()
261 ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); in qcom_snps_hsphy_init()
278 clk_bulk_disable_unprepare(priv->num_clks, priv->clks); in qcom_snps_hsphy_init()
282 static int qcom_snps_hsphy_exit(struct phy *phy) in qcom_snps_hsphy_exit() argument
284 struct hsphy_priv *priv = phy_get_drvdata(phy); in qcom_snps_hsphy_exit()
286 clk_bulk_disable_unprepare(priv->num_clks, priv->clks); in qcom_snps_hsphy_exit()
308 struct device *dev = &pdev->dev; in qcom_snps_hsphy_probe()
311 struct phy *phy; in qcom_snps_hsphy_probe() local
317 return -ENOMEM; in qcom_snps_hsphy_probe()
319 priv->base = devm_platform_ioremap_resource(pdev, 0); in qcom_snps_hsphy_probe()
320 if (IS_ERR(priv->base)) in qcom_snps_hsphy_probe()
321 return PTR_ERR(priv->base); in qcom_snps_hsphy_probe()
323 priv->num_clks = ARRAY_SIZE(qcom_snps_hsphy_clks); in qcom_snps_hsphy_probe()
324 priv->clks = devm_kcalloc(dev, priv->num_clks, sizeof(*priv->clks), in qcom_snps_hsphy_probe()
326 if (!priv->clks) in qcom_snps_hsphy_probe()
327 return -ENOMEM; in qcom_snps_hsphy_probe()
329 for (i = 0; i < priv->num_clks; i++) in qcom_snps_hsphy_probe()
330 priv->clks[i].id = qcom_snps_hsphy_clks[i]; in qcom_snps_hsphy_probe()
332 ret = devm_clk_bulk_get(dev, priv->num_clks, priv->clks); in qcom_snps_hsphy_probe()
336 priv->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); in qcom_snps_hsphy_probe()
337 if (IS_ERR(priv->phy_reset)) in qcom_snps_hsphy_probe()
338 return PTR_ERR(priv->phy_reset); in qcom_snps_hsphy_probe()
340 priv->por_reset = devm_reset_control_get_exclusive(dev, "por"); in qcom_snps_hsphy_probe()
341 if (IS_ERR(priv->por_reset)) in qcom_snps_hsphy_probe()
342 return PTR_ERR(priv->por_reset); in qcom_snps_hsphy_probe()
344 priv->vregs[VDD].supply = "vdd"; in qcom_snps_hsphy_probe()
345 priv->vregs[VDDA_1P8].supply = "vdda1p8"; in qcom_snps_hsphy_probe()
346 priv->vregs[VDDA_3P3].supply = "vdda3p3"; in qcom_snps_hsphy_probe()
348 ret = devm_regulator_bulk_get(dev, VREG_NUM, priv->vregs); in qcom_snps_hsphy_probe()
353 priv->data = device_get_match_data(dev); in qcom_snps_hsphy_probe()
355 phy = devm_phy_create(dev, dev->of_node, &qcom_snps_hsphy_ops); in qcom_snps_hsphy_probe()
356 if (IS_ERR(phy)) in qcom_snps_hsphy_probe()
357 return PTR_ERR(phy); in qcom_snps_hsphy_probe()
359 phy_set_drvdata(phy, priv); in qcom_snps_hsphy_probe()
365 ret = regulator_set_load(priv->vregs[VDDA_1P8].consumer, 19000); in qcom_snps_hsphy_probe()
369 ret = regulator_set_load(priv->vregs[VDDA_3P3].consumer, 16000); in qcom_snps_hsphy_probe()
376 regulator_set_load(priv->vregs[VDDA_1P8].consumer, 0); in qcom_snps_hsphy_probe()
383 * is meant to program 'value' into phy register at 'offset' with 'delay'
410 { .compatible = "qcom,usb-hs-28nm-femtophy", .data = &hsphy_data_femtophy, },
418 .name = "qcom,usb-hs-28nm-phy",
424 MODULE_DESCRIPTION("Qualcomm 28nm Hi-Speed USB PHY driver");