827cb03239
I submitted this driver several times before it got accepted. The first series hasn't been accepted but the DTS binding did made it. I then made a second series that added generic reset support to the PHY core, this in turn required a change to the DT binding. This second series seemed to have been ignored, so I did a third one without the change to the PHY core and the DT binding update, and this last attempt finally made it. But two months later the DT binding update from the second series has been integrated too. So now the driver doesn't match the binding and the only DTS using it. This patch fix the driver to match the new binding. Signed-off-by: Alban Bedel <albeu@free.fr> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
109 lines
2.5 KiB
C
109 lines
2.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Atheros AR71XX/9XXX USB PHY driver
|
|
*
|
|
* Copyright (C) 2015-2018 Alban Bedel <albeu@free.fr>
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/phy/phy.h>
|
|
#include <linux/reset.h>
|
|
|
|
struct ath79_usb_phy {
|
|
struct reset_control *reset;
|
|
/* The suspend override logic is inverted, hence the no prefix
|
|
* to make the code a bit easier to understand.
|
|
*/
|
|
struct reset_control *no_suspend_override;
|
|
};
|
|
|
|
static int ath79_usb_phy_power_on(struct phy *phy)
|
|
{
|
|
struct ath79_usb_phy *priv = phy_get_drvdata(phy);
|
|
int err = 0;
|
|
|
|
if (priv->no_suspend_override) {
|
|
err = reset_control_assert(priv->no_suspend_override);
|
|
if (err)
|
|
return err;
|
|
}
|
|
|
|
err = reset_control_deassert(priv->reset);
|
|
if (err && priv->no_suspend_override)
|
|
reset_control_deassert(priv->no_suspend_override);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int ath79_usb_phy_power_off(struct phy *phy)
|
|
{
|
|
struct ath79_usb_phy *priv = phy_get_drvdata(phy);
|
|
int err = 0;
|
|
|
|
err = reset_control_assert(priv->reset);
|
|
if (err)
|
|
return err;
|
|
|
|
if (priv->no_suspend_override) {
|
|
err = reset_control_deassert(priv->no_suspend_override);
|
|
if (err)
|
|
reset_control_deassert(priv->reset);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static const struct phy_ops ath79_usb_phy_ops = {
|
|
.power_on = ath79_usb_phy_power_on,
|
|
.power_off = ath79_usb_phy_power_off,
|
|
.owner = THIS_MODULE,
|
|
};
|
|
|
|
static int ath79_usb_phy_probe(struct platform_device *pdev)
|
|
{
|
|
struct ath79_usb_phy *priv;
|
|
struct phy *phy;
|
|
|
|
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
|
if (!priv)
|
|
return -ENOMEM;
|
|
|
|
priv->reset = devm_reset_control_get(&pdev->dev, "phy");
|
|
if (IS_ERR(priv->reset))
|
|
return PTR_ERR(priv->reset);
|
|
|
|
priv->no_suspend_override = devm_reset_control_get_optional(
|
|
&pdev->dev, "usb-suspend-override");
|
|
if (IS_ERR(priv->no_suspend_override))
|
|
return PTR_ERR(priv->no_suspend_override);
|
|
|
|
phy = devm_phy_create(&pdev->dev, NULL, &ath79_usb_phy_ops);
|
|
if (IS_ERR(phy))
|
|
return PTR_ERR(phy);
|
|
|
|
phy_set_drvdata(phy, priv);
|
|
|
|
return PTR_ERR_OR_ZERO(devm_of_phy_provider_register(
|
|
&pdev->dev, of_phy_simple_xlate));
|
|
}
|
|
|
|
static const struct of_device_id ath79_usb_phy_of_match[] = {
|
|
{ .compatible = "qca,ar7100-usb-phy" },
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(of, ath79_usb_phy_of_match);
|
|
|
|
static struct platform_driver ath79_usb_phy_driver = {
|
|
.probe = ath79_usb_phy_probe,
|
|
.driver = {
|
|
.of_match_table = ath79_usb_phy_of_match,
|
|
.name = "ath79-usb-phy",
|
|
}
|
|
};
|
|
module_platform_driver(ath79_usb_phy_driver);
|
|
|
|
MODULE_DESCRIPTION("ATH79 USB PHY driver");
|
|
MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
|
|
MODULE_LICENSE("GPL");
|