brintos

brintos / linux-shallow public Read only

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