Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / phy / mt7620-usb-phy.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
4  *
5  * Author: Weijie Gao <weijie.gao@mediatek.com>
6  */
7
8 #include <clk.h>
9 #include <dm.h>
10 #include <generic-phy.h>
11 #include <misc.h>
12 #include <reset.h>
13 #include <dm/device_compat.h>
14 #include <linux/delay.h>
15 #include <mach/mt7620-sysc.h>
16
17 struct mt7620_usb_phy {
18         struct udevice *sysc;
19         struct clk_bulk clocks;
20         struct reset_ctl_bulk resets;
21 };
22
23 static int mt7620_usb_phy_power_on(struct phy *_phy)
24 {
25         struct mt7620_usb_phy *phy = dev_get_priv(_phy->dev);
26         u32 mode = MT7620_SYSC_USB_HOST_MODE;
27         int ret;
28
29         reset_deassert_bulk(&phy->resets);
30
31         clk_enable_bulk(&phy->clocks);
32
33         mdelay(10);
34
35         ret = misc_ioctl(phy->sysc, MT7620_SYSC_IOCTL_SET_USB_MODE, &mode);
36         if (ret) {
37                 dev_err(_phy->dev,
38                         "mt7620_usbphy: failed to set USB host mode\n");
39                 return ret;
40         }
41
42         mdelay(10);
43
44         return 0;
45 }
46
47 static int mt7620_usb_phy_power_off(struct phy *_phy)
48 {
49         struct mt7620_usb_phy *phy = dev_get_priv(_phy->dev);
50
51         clk_disable_bulk(&phy->clocks);
52
53         reset_assert_bulk(&phy->resets);
54
55         return 0;
56 }
57
58 static int mt7620_usb_phy_probe(struct udevice *dev)
59 {
60         struct mt7620_usb_phy *phy = dev_get_priv(dev);
61         struct ofnode_phandle_args sysc_args;
62         int ret;
63
64         ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "mediatek,sysc", NULL,
65                                              0, 0, &sysc_args);
66         if (ret) {
67                 dev_err(dev, "mt7620_usbphy: sysc property not found\n");
68                 return ret;
69         }
70
71         ret = uclass_get_device_by_ofnode(UCLASS_MISC, sysc_args.node,
72                                           &phy->sysc);
73         if (ret) {
74                 dev_err(dev, "mt7620_usbphy: failed to sysc device\n");
75                 return ret;
76         }
77
78         ret = clk_get_bulk(dev, &phy->clocks);
79         if (ret) {
80                 dev_err(dev, "mt7620_usbphy: failed to get clocks\n");
81                 return ret;
82         }
83
84         ret = reset_get_bulk(dev, &phy->resets);
85         if (ret) {
86                 dev_err(dev, "mt7620_usbphy: failed to get reset control\n");
87                 return ret;
88         }
89
90         return 0;
91 }
92
93 static struct phy_ops mt7620_usb_phy_ops = {
94         .power_on = mt7620_usb_phy_power_on,
95         .power_off = mt7620_usb_phy_power_off,
96 };
97
98 static const struct udevice_id mt7620_usb_phy_ids[] = {
99         { .compatible = "mediatek,mt7620-usbphy" },
100         { }
101 };
102
103 U_BOOT_DRIVER(mt7620_usb_phy) = {
104         .name           = "mt7620_usb_phy",
105         .id             = UCLASS_PHY,
106         .of_match       = mt7620_usb_phy_ids,
107         .ops            = &mt7620_usb_phy_ops,
108         .probe          = mt7620_usb_phy_probe,
109         .priv_auto      = sizeof(struct mt7620_usb_phy),
110 };