Lines Matching +full:meson +full:- +full:gxbb +full:- +full:usb2 +full:- +full:phy
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Meson8, Meson8b and GXBB USB2 PHY driver
16 #include <linux/phy/phy.h>
50 /* bits [31:26], [24:21] and [15:3] seem to be read-only */
140 static int phy_meson8b_usb2_power_on(struct phy *phy) in phy_meson8b_usb2_power_on() argument
142 struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson8b_usb2_power_on()
146 if (!IS_ERR_OR_NULL(priv->reset)) { in phy_meson8b_usb2_power_on()
147 ret = reset_control_reset(priv->reset); in phy_meson8b_usb2_power_on()
149 dev_err(&phy->dev, "Failed to trigger USB reset\n"); in phy_meson8b_usb2_power_on()
154 ret = clk_prepare_enable(priv->clk_usb_general); in phy_meson8b_usb2_power_on()
156 dev_err(&phy->dev, "Failed to enable USB general clock\n"); in phy_meson8b_usb2_power_on()
157 reset_control_rearm(priv->reset); in phy_meson8b_usb2_power_on()
161 ret = clk_prepare_enable(priv->clk_usb); in phy_meson8b_usb2_power_on()
163 dev_err(&phy->dev, "Failed to enable USB DDR clock\n"); in phy_meson8b_usb2_power_on()
164 clk_disable_unprepare(priv->clk_usb_general); in phy_meson8b_usb2_power_on()
165 reset_control_rearm(priv->reset); in phy_meson8b_usb2_power_on()
169 regmap_update_bits(priv->regmap, REG_CONFIG, REG_CONFIG_CLK_32k_ALTSEL, in phy_meson8b_usb2_power_on()
172 regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_REF_CLK_SEL_MASK, in phy_meson8b_usb2_power_on()
175 regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_FSEL_MASK, in phy_meson8b_usb2_power_on()
178 /* reset the PHY */ in phy_meson8b_usb2_power_on()
179 regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, in phy_meson8b_usb2_power_on()
182 regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, 0); in phy_meson8b_usb2_power_on()
185 regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_SOF_TOGGLE_OUT, in phy_meson8b_usb2_power_on()
188 if (priv->dr_mode == USB_DR_MODE_HOST) { in phy_meson8b_usb2_power_on()
189 regmap_update_bits(priv->regmap, REG_DBG_UART, in phy_meson8b_usb2_power_on()
192 if (priv->match->host_enable_aca) { in phy_meson8b_usb2_power_on()
193 regmap_update_bits(priv->regmap, REG_ADP_BC, in phy_meson8b_usb2_power_on()
199 regmap_read(priv->regmap, REG_ADP_BC, ®); in phy_meson8b_usb2_power_on()
201 dev_warn(&phy->dev, "USB ID detect failed!\n"); in phy_meson8b_usb2_power_on()
202 clk_disable_unprepare(priv->clk_usb); in phy_meson8b_usb2_power_on()
203 clk_disable_unprepare(priv->clk_usb_general); in phy_meson8b_usb2_power_on()
204 reset_control_rearm(priv->reset); in phy_meson8b_usb2_power_on()
205 return -EINVAL; in phy_meson8b_usb2_power_on()
213 static int phy_meson8b_usb2_power_off(struct phy *phy) in phy_meson8b_usb2_power_off() argument
215 struct phy_meson8b_usb2_priv *priv = phy_get_drvdata(phy); in phy_meson8b_usb2_power_off()
217 if (priv->dr_mode == USB_DR_MODE_HOST) in phy_meson8b_usb2_power_off()
218 regmap_update_bits(priv->regmap, REG_DBG_UART, in phy_meson8b_usb2_power_off()
222 clk_disable_unprepare(priv->clk_usb); in phy_meson8b_usb2_power_off()
223 clk_disable_unprepare(priv->clk_usb_general); in phy_meson8b_usb2_power_off()
224 reset_control_rearm(priv->reset); in phy_meson8b_usb2_power_off()
226 /* power off the PHY by putting it into reset mode */ in phy_meson8b_usb2_power_off()
227 regmap_update_bits(priv->regmap, REG_CTRL, REG_CTRL_POWER_ON_RESET, in phy_meson8b_usb2_power_off()
242 struct phy *phy; in phy_meson8b_usb2_probe() local
246 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in phy_meson8b_usb2_probe()
248 return -ENOMEM; in phy_meson8b_usb2_probe()
254 priv->match = device_get_match_data(&pdev->dev); in phy_meson8b_usb2_probe()
255 if (!priv->match) in phy_meson8b_usb2_probe()
256 return -ENODEV; in phy_meson8b_usb2_probe()
258 priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, in phy_meson8b_usb2_probe()
260 if (IS_ERR(priv->regmap)) in phy_meson8b_usb2_probe()
261 return PTR_ERR(priv->regmap); in phy_meson8b_usb2_probe()
263 priv->clk_usb_general = devm_clk_get(&pdev->dev, "usb_general"); in phy_meson8b_usb2_probe()
264 if (IS_ERR(priv->clk_usb_general)) in phy_meson8b_usb2_probe()
265 return PTR_ERR(priv->clk_usb_general); in phy_meson8b_usb2_probe()
267 priv->clk_usb = devm_clk_get(&pdev->dev, "usb"); in phy_meson8b_usb2_probe()
268 if (IS_ERR(priv->clk_usb)) in phy_meson8b_usb2_probe()
269 return PTR_ERR(priv->clk_usb); in phy_meson8b_usb2_probe()
271 priv->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL); in phy_meson8b_usb2_probe()
272 if (IS_ERR(priv->reset)) in phy_meson8b_usb2_probe()
273 return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset), in phy_meson8b_usb2_probe()
276 priv->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1); in phy_meson8b_usb2_probe()
277 if (priv->dr_mode == USB_DR_MODE_UNKNOWN) { in phy_meson8b_usb2_probe()
278 dev_err(&pdev->dev, in phy_meson8b_usb2_probe()
280 return -EINVAL; in phy_meson8b_usb2_probe()
283 phy = devm_phy_create(&pdev->dev, NULL, &phy_meson8b_usb2_ops); in phy_meson8b_usb2_probe()
284 if (IS_ERR(phy)) { in phy_meson8b_usb2_probe()
285 return dev_err_probe(&pdev->dev, PTR_ERR(phy), in phy_meson8b_usb2_probe()
286 "failed to create PHY\n"); in phy_meson8b_usb2_probe()
289 phy_set_drvdata(phy, priv); in phy_meson8b_usb2_probe()
292 devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); in phy_meson8b_usb2_probe()
307 .compatible = "amlogic,meson8-usb2-phy",
311 .compatible = "amlogic,meson8b-usb2-phy",
315 .compatible = "amlogic,meson8m2-usb2-phy",
319 .compatible = "amlogic,meson-gxbb-usb2-phy",
329 .name = "phy-meson-usb2",
336 MODULE_DESCRIPTION("Meson8, Meson8b, Meson8m2 and GXBB USB2 PHY driver");