Lines Matching +full:phy +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0
3 * Meson GXL USB3 PHY and OTG mode detection driver
13 #include <linux/phy/phy.h>
78 /* read-only register */
85 enum phy_mode mode; member
98 static int phy_meson_gxl_usb3_power_on(struct phy *phy) in phy_meson_gxl_usb3_power_on() argument
100 struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb3_power_on()
102 regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_0, in phy_meson_gxl_usb3_power_on()
104 regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_1, in phy_meson_gxl_usb3_power_on()
106 regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_TH_MASK, in phy_meson_gxl_usb3_power_on()
112 static int phy_meson_gxl_usb3_power_off(struct phy *phy) in phy_meson_gxl_usb3_power_off() argument
114 struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb3_power_off()
116 regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_0, 0); in phy_meson_gxl_usb3_power_off()
117 regmap_update_bits(priv->regmap, USB_R5, USB_R5_ID_DIG_EN_1, 0); in phy_meson_gxl_usb3_power_off()
122 static int phy_meson_gxl_usb3_set_mode(struct phy *phy, in phy_meson_gxl_usb3_set_mode() argument
123 enum phy_mode mode, int submode) in phy_meson_gxl_usb3_set_mode() argument
125 struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb3_set_mode()
127 switch (mode) { in phy_meson_gxl_usb3_set_mode()
129 regmap_update_bits(priv->regmap, USB_R0, USB_R0_U2D_ACT, 0); in phy_meson_gxl_usb3_set_mode()
130 regmap_update_bits(priv->regmap, USB_R4, USB_R4_P21_SLEEP_M0, in phy_meson_gxl_usb3_set_mode()
135 regmap_update_bits(priv->regmap, USB_R0, USB_R0_U2D_ACT, in phy_meson_gxl_usb3_set_mode()
137 regmap_update_bits(priv->regmap, USB_R4, USB_R4_P21_SLEEP_M0, in phy_meson_gxl_usb3_set_mode()
142 dev_err(&phy->dev, "unsupported PHY mode %d\n", mode); in phy_meson_gxl_usb3_set_mode()
143 return -EINVAL; in phy_meson_gxl_usb3_set_mode()
146 priv->mode = mode; in phy_meson_gxl_usb3_set_mode()
151 static int phy_meson_gxl_usb3_init(struct phy *phy) in phy_meson_gxl_usb3_init() argument
153 struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb3_init()
156 ret = reset_control_reset(priv->reset); in phy_meson_gxl_usb3_init()
160 ret = clk_prepare_enable(priv->clk_phy); in phy_meson_gxl_usb3_init()
164 ret = clk_prepare_enable(priv->clk_peripheral); in phy_meson_gxl_usb3_init()
168 ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode, 0); in phy_meson_gxl_usb3_init()
172 regmap_update_bits(priv->regmap, USB_R1, in phy_meson_gxl_usb3_init()
179 clk_disable_unprepare(priv->clk_peripheral); in phy_meson_gxl_usb3_init()
181 clk_disable_unprepare(priv->clk_phy); in phy_meson_gxl_usb3_init()
186 static int phy_meson_gxl_usb3_exit(struct phy *phy) in phy_meson_gxl_usb3_exit() argument
188 struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); in phy_meson_gxl_usb3_exit()
190 clk_disable_unprepare(priv->clk_peripheral); in phy_meson_gxl_usb3_exit()
191 clk_disable_unprepare(priv->clk_phy); in phy_meson_gxl_usb3_exit()
207 struct device *dev = &pdev->dev; in phy_meson_gxl_usb3_probe()
208 struct device_node *np = dev->of_node; in phy_meson_gxl_usb3_probe()
211 struct phy *phy; in phy_meson_gxl_usb3_probe() local
218 return -ENOMEM; in phy_meson_gxl_usb3_probe()
225 priv->regmap = devm_regmap_init_mmio(dev, base, in phy_meson_gxl_usb3_probe()
227 if (IS_ERR(priv->regmap)) in phy_meson_gxl_usb3_probe()
228 return PTR_ERR(priv->regmap); in phy_meson_gxl_usb3_probe()
230 priv->clk_phy = devm_clk_get(dev, "phy"); in phy_meson_gxl_usb3_probe()
231 if (IS_ERR(priv->clk_phy)) in phy_meson_gxl_usb3_probe()
232 return PTR_ERR(priv->clk_phy); in phy_meson_gxl_usb3_probe()
234 priv->clk_peripheral = devm_clk_get(dev, "peripheral"); in phy_meson_gxl_usb3_probe()
235 if (IS_ERR(priv->clk_peripheral)) in phy_meson_gxl_usb3_probe()
236 return PTR_ERR(priv->clk_peripheral); in phy_meson_gxl_usb3_probe()
238 priv->reset = devm_reset_control_array_get_shared(dev); in phy_meson_gxl_usb3_probe()
239 if (IS_ERR(priv->reset)) in phy_meson_gxl_usb3_probe()
240 return PTR_ERR(priv->reset); in phy_meson_gxl_usb3_probe()
243 * default to host mode as hardware defaults and/or boot-loader in phy_meson_gxl_usb3_probe()
244 * behavior can result in this PHY starting up in device mode. this in phy_meson_gxl_usb3_probe()
246 * that we reproducibly start in a known mode on all devices. in phy_meson_gxl_usb3_probe()
248 priv->mode = PHY_MODE_USB_HOST; in phy_meson_gxl_usb3_probe()
250 phy = devm_phy_create(dev, np, &phy_meson_gxl_usb3_ops); in phy_meson_gxl_usb3_probe()
251 if (IS_ERR(phy)) { in phy_meson_gxl_usb3_probe()
252 ret = PTR_ERR(phy); in phy_meson_gxl_usb3_probe()
253 if (ret != -EPROBE_DEFER) in phy_meson_gxl_usb3_probe()
254 dev_err(dev, "failed to create PHY\n"); in phy_meson_gxl_usb3_probe()
259 phy_set_drvdata(phy, priv); in phy_meson_gxl_usb3_probe()
267 { .compatible = "amlogic,meson-gxl-usb3-phy", },
275 .name = "phy-meson-gxl-usb3",
282 MODULE_DESCRIPTION("Meson GXL USB3 PHY and OTG detection driver");