blob: 3b647324e021d6d9ebef6935fa89624dd167b00c [file] [log] [blame]
Robert Marko9190e7b2020-09-10 16:00:04 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019 Sartura Ltd.
4 *
5 * Author: Robert Marko <robert.marko@sartura.hr>
6 *
7 * Based on Linux driver
8 */
9
10#include <clk.h>
Robert Marko9190e7b2020-09-10 16:00:04 +020011#include <dm.h>
12#include <generic-phy.h>
13#include <log.h>
14#include <reset.h>
15#include <asm/io.h>
16#include <linux/delay.h>
17
18struct ipq4019_usb_phy {
19 phys_addr_t base;
20 struct reset_ctl por_rst;
21 struct reset_ctl srif_rst;
22};
23
24static int ipq4019_ss_phy_power_off(struct phy *_phy)
25{
26 struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
27
28 reset_assert(&phy->por_rst);
29 mdelay(10);
30
31 return 0;
32}
33
34static int ipq4019_ss_phy_power_on(struct phy *_phy)
35{
36 struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
37
38 ipq4019_ss_phy_power_off(_phy);
39
40 reset_deassert(&phy->por_rst);
41
42 return 0;
43}
44
45static struct phy_ops ipq4019_usb_ss_phy_ops = {
46 .power_on = ipq4019_ss_phy_power_on,
47 .power_off = ipq4019_ss_phy_power_off,
48};
49
50static int ipq4019_usb_ss_phy_probe(struct udevice *dev)
51{
52 struct ipq4019_usb_phy *phy = dev_get_priv(dev);
53 int ret;
54
55 phy->base = dev_read_addr(dev);
56 if (phy->base == FDT_ADDR_T_NONE)
57 return -EINVAL;
58
59 ret = reset_get_by_name(dev, "por_rst", &phy->por_rst);
60 if (ret)
61 return ret;
62
63 return 0;
64}
65
66static const struct udevice_id ipq4019_usb_ss_phy_ids[] = {
67 { .compatible = "qcom,usb-ss-ipq4019-phy" },
68 { }
69};
70
71U_BOOT_DRIVER(ipq4019_usb_ss_phy) = {
72 .name = "ipq4019-usb-ss-phy",
73 .id = UCLASS_PHY,
74 .of_match = ipq4019_usb_ss_phy_ids,
75 .ops = &ipq4019_usb_ss_phy_ops,
76 .probe = ipq4019_usb_ss_phy_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -070077 .priv_auto = sizeof(struct ipq4019_usb_phy),
Robert Marko9190e7b2020-09-10 16:00:04 +020078};
79
80static int ipq4019_hs_phy_power_off(struct phy *_phy)
81{
82 struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
83
84 reset_assert(&phy->por_rst);
85 mdelay(10);
86
87 reset_assert(&phy->srif_rst);
88 mdelay(10);
89
90 return 0;
91}
92
93static int ipq4019_hs_phy_power_on(struct phy *_phy)
94{
95 struct ipq4019_usb_phy *phy = dev_get_priv(_phy->dev);
96
97 ipq4019_hs_phy_power_off(_phy);
98
99 reset_deassert(&phy->srif_rst);
100 mdelay(10);
101
102 reset_deassert(&phy->por_rst);
103
104 return 0;
105}
106
107static struct phy_ops ipq4019_usb_hs_phy_ops = {
108 .power_on = ipq4019_hs_phy_power_on,
109 .power_off = ipq4019_hs_phy_power_off,
110};
111
112static int ipq4019_usb_hs_phy_probe(struct udevice *dev)
113{
114 struct ipq4019_usb_phy *phy = dev_get_priv(dev);
115 int ret;
116
117 phy->base = dev_read_addr(dev);
118 if (phy->base == FDT_ADDR_T_NONE)
119 return -EINVAL;
120
121 ret = reset_get_by_name(dev, "por_rst", &phy->por_rst);
122 if (ret)
123 return ret;
124
125 ret = reset_get_by_name(dev, "srif_rst", &phy->srif_rst);
126 if (ret)
127 return ret;
128
129 return 0;
130}
131
132static const struct udevice_id ipq4019_usb_hs_phy_ids[] = {
133 { .compatible = "qcom,usb-hs-ipq4019-phy" },
134 { }
135};
136
137U_BOOT_DRIVER(ipq4019_usb_hs_phy) = {
138 .name = "ipq4019-usb-hs-phy",
139 .id = UCLASS_PHY,
140 .of_match = ipq4019_usb_hs_phy_ids,
141 .ops = &ipq4019_usb_hs_phy_ops,
142 .probe = ipq4019_usb_hs_phy_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700143 .priv_auto = sizeof(struct ipq4019_usb_phy),
Robert Marko9190e7b2020-09-10 16:00:04 +0200144};