Lines Matching +full:phy +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Meson GXL and GXM USB2 PHY driver
15 #include <linux/phy/phy.h>
18 /* bits [31:27] are read-only */
66 /* bits [31:14] are read-only */
94 enum phy_mode mode; member
107 static int phy_meson_gxl_usb2_init(struct phy *phy) in phy_meson_gxl_usb2_init() argument
109 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb2_init()
112 ret = reset_control_reset(priv->reset); in phy_meson_gxl_usb2_init()
116 ret = clk_prepare_enable(priv->clk); in phy_meson_gxl_usb2_init()
123 static int phy_meson_gxl_usb2_exit(struct phy *phy) in phy_meson_gxl_usb2_exit() argument
125 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb2_exit()
127 clk_disable_unprepare(priv->clk); in phy_meson_gxl_usb2_exit()
132 static int phy_meson_gxl_usb2_reset(struct phy *phy) in phy_meson_gxl_usb2_reset() argument
134 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb2_reset()
136 if (priv->is_enabled) { in phy_meson_gxl_usb2_reset()
137 /* reset the PHY and wait until settings are stabilized */ in phy_meson_gxl_usb2_reset()
138 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, in phy_meson_gxl_usb2_reset()
141 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, in phy_meson_gxl_usb2_reset()
149 static int phy_meson_gxl_usb2_set_mode(struct phy *phy, in phy_meson_gxl_usb2_set_mode() argument
150 enum phy_mode mode, int submode) in phy_meson_gxl_usb2_set_mode() argument
152 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb2_set_mode()
154 switch (mode) { in phy_meson_gxl_usb2_set_mode()
157 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN, in phy_meson_gxl_usb2_set_mode()
159 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN, in phy_meson_gxl_usb2_set_mode()
161 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, 0); in phy_meson_gxl_usb2_set_mode()
165 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DM_PULLDOWN, in phy_meson_gxl_usb2_set_mode()
167 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_DP_PULLDOWN, in phy_meson_gxl_usb2_set_mode()
169 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_ID_PULLUP, in phy_meson_gxl_usb2_set_mode()
174 return -EINVAL; in phy_meson_gxl_usb2_set_mode()
177 phy_meson_gxl_usb2_reset(phy); in phy_meson_gxl_usb2_set_mode()
179 priv->mode = mode; in phy_meson_gxl_usb2_set_mode()
184 static int phy_meson_gxl_usb2_power_off(struct phy *phy) in phy_meson_gxl_usb2_power_off() argument
186 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb2_power_off()
188 priv->is_enabled = 0; in phy_meson_gxl_usb2_power_off()
190 /* power off the PHY by putting it into reset mode */ in phy_meson_gxl_usb2_power_off()
191 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, in phy_meson_gxl_usb2_power_off()
197 static int phy_meson_gxl_usb2_power_on(struct phy *phy) in phy_meson_gxl_usb2_power_on() argument
199 struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb2_power_on()
202 priv->is_enabled = 1; in phy_meson_gxl_usb2_power_on()
204 /* power on the PHY by taking it out of reset mode */ in phy_meson_gxl_usb2_power_on()
205 regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); in phy_meson_gxl_usb2_power_on()
207 ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode, 0); in phy_meson_gxl_usb2_power_on()
209 phy_meson_gxl_usb2_power_off(phy); in phy_meson_gxl_usb2_power_on()
211 dev_err(&phy->dev, "Failed to initialize PHY with mode %d\n", in phy_meson_gxl_usb2_power_on()
212 priv->mode); in phy_meson_gxl_usb2_power_on()
231 struct device *dev = &pdev->dev; in phy_meson_gxl_usb2_probe()
235 struct phy *phy; in phy_meson_gxl_usb2_probe() local
241 return -ENOMEM; in phy_meson_gxl_usb2_probe()
250 /* start in host mode */ in phy_meson_gxl_usb2_probe()
251 priv->mode = PHY_MODE_USB_HOST; in phy_meson_gxl_usb2_probe()
253 priv->regmap = devm_regmap_init_mmio(dev, base, in phy_meson_gxl_usb2_probe()
255 if (IS_ERR(priv->regmap)) in phy_meson_gxl_usb2_probe()
256 return PTR_ERR(priv->regmap); in phy_meson_gxl_usb2_probe()
258 priv->clk = devm_clk_get_optional(dev, "phy"); in phy_meson_gxl_usb2_probe()
259 if (IS_ERR(priv->clk)) in phy_meson_gxl_usb2_probe()
260 return PTR_ERR(priv->clk); in phy_meson_gxl_usb2_probe()
262 priv->reset = devm_reset_control_get_optional_shared(dev, "phy"); in phy_meson_gxl_usb2_probe()
263 if (IS_ERR(priv->reset)) in phy_meson_gxl_usb2_probe()
264 return PTR_ERR(priv->reset); in phy_meson_gxl_usb2_probe()
266 phy = devm_phy_create(dev, NULL, &phy_meson_gxl_usb2_ops); in phy_meson_gxl_usb2_probe()
267 if (IS_ERR(phy)) { in phy_meson_gxl_usb2_probe()
268 ret = PTR_ERR(phy); in phy_meson_gxl_usb2_probe()
269 if (ret != -EPROBE_DEFER) in phy_meson_gxl_usb2_probe()
270 dev_err(dev, "failed to create PHY\n"); in phy_meson_gxl_usb2_probe()
275 phy_set_drvdata(phy, priv); in phy_meson_gxl_usb2_probe()
283 { .compatible = "amlogic,meson-gxl-usb2-phy", },
291 .name = "phy-meson-gxl-usb2",
298 MODULE_DESCRIPTION("Meson GXL and GXM USB2 PHY driver");