^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Atheros AR71XX/9XXX USB PHY driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015-2018 Alban Bedel <albeu@free.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/reset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct ath79_usb_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct reset_control *reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* The suspend override logic is inverted, hence the no prefix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * to make the code a bit easier to understand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct reset_control *no_suspend_override;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static int ath79_usb_phy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct ath79_usb_phy *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (priv->no_suspend_override) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) err = reset_control_assert(priv->no_suspend_override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) err = reset_control_deassert(priv->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (err && priv->no_suspend_override)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) reset_control_deassert(priv->no_suspend_override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int ath79_usb_phy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct ath79_usb_phy *priv = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) err = reset_control_assert(priv->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (priv->no_suspend_override) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) err = reset_control_deassert(priv->no_suspend_override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) reset_control_deassert(priv->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static const struct phy_ops ath79_usb_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .power_on = ath79_usb_phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .power_off = ath79_usb_phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int ath79_usb_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct ath79_usb_phy *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) priv->reset = devm_reset_control_get(&pdev->dev, "phy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (IS_ERR(priv->reset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return PTR_ERR(priv->reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) priv->no_suspend_override = devm_reset_control_get_optional(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) &pdev->dev, "usb-suspend-override");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (IS_ERR(priv->no_suspend_override))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return PTR_ERR(priv->no_suspend_override);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) phy = devm_phy_create(&pdev->dev, NULL, &ath79_usb_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (IS_ERR(phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return PTR_ERR(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) phy_set_drvdata(phy, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return PTR_ERR_OR_ZERO(devm_of_phy_provider_register(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) &pdev->dev, of_phy_simple_xlate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const struct of_device_id ath79_usb_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { .compatible = "qca,ar7100-usb-phy" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MODULE_DEVICE_TABLE(of, ath79_usb_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static struct platform_driver ath79_usb_phy_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .probe = ath79_usb_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .of_match_table = ath79_usb_phy_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .name = "ath79-usb-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) module_platform_driver(ath79_usb_phy_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) MODULE_DESCRIPTION("ATH79 USB PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) MODULE_LICENSE("GPL");