1 // SPDX-License-Identifier: GPL-2.0+
3 * Atheros AR71XX/9XXX USB PHY driver
5 * Copyright (C) 2015-2018 Alban Bedel <albeu@free.fr>
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>
14 struct ath79_usb_phy
{
15 struct reset_control
*reset
;
16 /* The suspend override logic is inverted, hence the no prefix
17 * to make the code a bit easier to understand.
19 struct reset_control
*no_suspend_override
;
22 static int ath79_usb_phy_power_on(struct phy
*phy
)
24 struct ath79_usb_phy
*priv
= phy_get_drvdata(phy
);
27 if (priv
->no_suspend_override
) {
28 err
= reset_control_assert(priv
->no_suspend_override
);
33 err
= reset_control_deassert(priv
->reset
);
34 if (err
&& priv
->no_suspend_override
)
35 reset_control_deassert(priv
->no_suspend_override
);
40 static int ath79_usb_phy_power_off(struct phy
*phy
)
42 struct ath79_usb_phy
*priv
= phy_get_drvdata(phy
);
45 err
= reset_control_assert(priv
->reset
);
49 if (priv
->no_suspend_override
) {
50 err
= reset_control_deassert(priv
->no_suspend_override
);
52 reset_control_deassert(priv
->reset
);
58 static const struct phy_ops ath79_usb_phy_ops
= {
59 .power_on
= ath79_usb_phy_power_on
,
60 .power_off
= ath79_usb_phy_power_off
,
64 static int ath79_usb_phy_probe(struct platform_device
*pdev
)
66 struct ath79_usb_phy
*priv
;
69 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
73 priv
->reset
= devm_reset_control_get(&pdev
->dev
, "phy");
74 if (IS_ERR(priv
->reset
))
75 return PTR_ERR(priv
->reset
);
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
);
82 phy
= devm_phy_create(&pdev
->dev
, NULL
, &ath79_usb_phy_ops
);
86 phy_set_drvdata(phy
, priv
);
88 return PTR_ERR_OR_ZERO(devm_of_phy_provider_register(
89 &pdev
->dev
, of_phy_simple_xlate
));
92 static const struct of_device_id ath79_usb_phy_of_match
[] = {
93 { .compatible
= "qca,ar7100-usb-phy" },
96 MODULE_DEVICE_TABLE(of
, ath79_usb_phy_of_match
);
98 static struct platform_driver ath79_usb_phy_driver
= {
99 .probe
= ath79_usb_phy_probe
,
101 .of_match_table
= ath79_usb_phy_of_match
,
102 .name
= "ath79-usb-phy",
105 module_platform_driver(ath79_usb_phy_driver
);
107 MODULE_DESCRIPTION("ATH79 USB PHY driver");
108 MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
109 MODULE_LICENSE("GPL");