Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/qualcomm/ipq4018_usb_ss_phy.c
39507 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2019 Michal Meloun <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/systm.h>
30
#include <sys/bus.h>
31
#include <sys/gpio.h>
32
#include <sys/kernel.h>
33
#include <sys/module.h>
34
#include <sys/malloc.h>
35
#include <sys/rman.h>
36
37
#include <machine/bus.h>
38
39
#include <dev/hwreset/hwreset.h>
40
#include <dev/phy/phy_usb.h>
41
#include <dev/regulator/regulator.h>
42
#include <dev/ofw/ofw_bus.h>
43
#include <dev/ofw/ofw_bus_subr.h>
44
45
#include <dev/fdt/simple_mfd.h>
46
#include "phynode_if.h"
47
#include "phynode_usb_if.h"
48
49
static struct ofw_compat_data compat_data[] = {
50
{"qcom,usb-ss-ipq4019-phy", 1},
51
{NULL, 0},
52
};
53
54
struct ipq4018_usb_ss_phy_softc {
55
device_t dev;
56
};
57
58
struct ipq4018_usb_ss_phynode_sc {
59
struct phynode_usb_sc usb_sc;
60
int mode;
61
hwreset_t por_rst;
62
};
63
64
static int
65
ipq4018_usb_ss_phynode_phy_enable(struct phynode *phynode, bool enable)
66
{
67
struct ipq4018_usb_ss_phynode_sc *sc;
68
device_t dev;
69
int rv;
70
71
dev = phynode_get_device(phynode);
72
sc = phynode_get_softc(phynode);
73
74
/*
75
* For power-off - assert por, sleep for 10ms
76
*/
77
rv = hwreset_assert(sc->por_rst);
78
if (rv != 0)
79
goto done;
80
DELAY(10*1000);
81
82
/*
83
* For power-on - power off first, then deassert por.
84
*/
85
if (enable) {
86
rv = hwreset_deassert(sc->por_rst);
87
if (rv != 0)
88
goto done;
89
DELAY(10*1000);
90
}
91
92
done:
93
if (rv != 0) {
94
device_printf(dev, "%s: failed, rv=%d\n", __func__, rv);
95
}
96
return (rv);
97
}
98
99
/* Phy controller class and methods. */
100
static phynode_method_t ipq4018_usb_ss_phynode_methods[] = {
101
PHYNODEUSBMETHOD(phynode_enable, ipq4018_usb_ss_phynode_phy_enable),
102
PHYNODEUSBMETHOD_END
103
};
104
DEFINE_CLASS_1(ipq4018_usb_ss_phynode, ipq4018_usb_ss_phynode_class,
105
ipq4018_usb_ss_phynode_methods,
106
sizeof(struct ipq4018_usb_ss_phynode_sc), phynode_usb_class);
107
108
static int
109
ipq4018_usb_ss_usbphy_init_phy(struct ipq4018_usb_ss_phy_softc *sc,
110
phandle_t node)
111
{
112
struct phynode *phynode;
113
struct phynode_init_def phy_init;
114
struct ipq4018_usb_ss_phynode_sc *phy_sc;
115
int rv;
116
hwreset_t por_rst = NULL;
117
118
/* FDT resources */
119
rv = hwreset_get_by_ofw_name(sc->dev, node, "por_rst", &por_rst);
120
if (rv != 0 && rv != ENOENT) {
121
device_printf(sc->dev, "Cannot get 'por_rst' reset\n");
122
goto fail;
123
}
124
125
/* Create and register phy. */
126
bzero(&phy_init, sizeof(phy_init));
127
phy_init.id = 1;
128
phy_init.ofw_node = node;
129
phynode = phynode_create(sc->dev, &ipq4018_usb_ss_phynode_class,
130
&phy_init);
131
if (phynode == NULL) {
132
device_printf(sc->dev, "Cannot create phy.\n");
133
return (ENXIO);
134
}
135
136
phy_sc = phynode_get_softc(phynode);
137
phy_sc->por_rst = por_rst;
138
139
if (phynode_register(phynode) == NULL) {
140
device_printf(sc->dev, "Cannot register phy.\n");
141
return (ENXIO);
142
}
143
144
(void) ipq4018_usb_ss_phynode_phy_enable(phynode, true);
145
146
return (0);
147
148
fail:
149
if (por_rst != NULL)
150
hwreset_release(por_rst);
151
152
return (ENXIO);
153
}
154
155
static int
156
ipq4018_usb_ss_usbphy_probe(device_t dev)
157
{
158
159
if (!ofw_bus_status_okay(dev))
160
return (ENXIO);
161
162
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
163
return (ENXIO);
164
165
device_set_desc(dev, "IPQ4018/IPQ4019 USB SS PHY");
166
return (BUS_PROBE_DEFAULT);
167
}
168
169
static int
170
ipq4018_usb_ss_usbphy_attach(device_t dev)
171
{
172
struct ipq4018_usb_ss_phy_softc *sc;
173
phandle_t node;
174
int rv;
175
176
sc = device_get_softc(dev);
177
sc->dev = dev;
178
node = ofw_bus_get_node(sc->dev);
179
180
rv = ipq4018_usb_ss_usbphy_init_phy(sc, node);
181
if (rv != 0)
182
goto fail;
183
bus_attach_children(dev);
184
return (0);
185
186
fail:
187
return (ENXIO);
188
}
189
190
static int
191
ipq4018_usb_ss_usbphy_detach(device_t dev)
192
{
193
194
return (0);
195
}
196
197
static device_method_t ipq4018_usb_ss_usbphy_methods[] = {
198
/* Device interface */
199
DEVMETHOD(device_probe, ipq4018_usb_ss_usbphy_probe),
200
DEVMETHOD(device_attach, ipq4018_usb_ss_usbphy_attach),
201
DEVMETHOD(device_detach, ipq4018_usb_ss_usbphy_detach),
202
DEVMETHOD_END
203
};
204
205
static DEFINE_CLASS_0(ipq4018_usb_ss_usbphy, ipq4018_usb_ss_usbphy_driver,
206
ipq4018_usb_ss_usbphy_methods,
207
sizeof(struct ipq4018_usb_ss_phy_softc));
208
EARLY_DRIVER_MODULE(ipq4018_usb_ss_usbphy, simplebus,
209
ipq4018_usb_ss_usbphy_driver, NULL, NULL,
210
BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);
211
212