rk_usb.c revision 1.8 1 /* $NetBSD: rk_usb.c,v 1.8 2021/01/18 02:35:49 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30
31 __KERNEL_RCSID(0, "$NetBSD: rk_usb.c,v 1.8 2021/01/18 02:35:49 thorpej Exp $");
32
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/device.h>
36 #include <sys/intr.h>
37 #include <sys/systm.h>
38 #include <sys/time.h>
39 #include <sys/kmem.h>
40
41 #include <dev/clk/clk_backend.h>
42
43 #include <dev/fdt/fdtvar.h>
44 #include <dev/fdt/syscon.h>
45
46 static int rk_usb_match(device_t, cfdata_t, void *);
47 static void rk_usb_attach(device_t, device_t, void *);
48
49 #define RK3328_CON0_REG 0x100
50 #define RK3328_CON1_REG 0x104
51 #define RK3328_CON2_REG 0x108
52 #define RK3328_USBPHY_COMMONONN __BIT(4)
53
54 #define RK3399_GRF_USB20_PHY0_CON0_REG 0x0e450
55 #define RK3399_GRF_USB20_PHY1_CON0_REG 0x0e460
56 #define RK3399_USBPHY_COMMONONN __BIT(4)
57 #define RK3399_GRF_USB20_PHY0_CON1_REG 0x0e454
58 #define RK3399_GRF_USB20_PHY1_CON1_REG 0x0e464
59 #define RK3399_GRF_USB20_PHY0_CON2_REG 0x0e458
60 #define RK3399_GRF_USB20_PHY1_CON2_REG 0x0e468
61 #define RK3399_USBPHY_SUSPEND_N __BIT(1)
62 #define RK3399_USBPHY_UTMI_SEL __BIT(0)
63
64 #define RK3399_PHY_NO(_sc) ((_sc)->sc_reg == 0xe450 ? 0 : 1)
65
66 enum rk_usb_type {
67 USB_RK3328 = 1,
68 USB_RK3399,
69 };
70
71 static const struct device_compatible_entry compat_data[] = {
72 { .compat = "rockchip,rk3328-usb2phy", .value = USB_RK3328 },
73 { .compat = "rockchip,rk3399-usb2phy", .value = USB_RK3399 },
74
75 { 0 }
76 };
77
78 struct rk_usb_clk {
79 struct clk base;
80 };
81
82 struct rk_usb_softc {
83 device_t sc_dev;
84 struct syscon *sc_syscon;
85 enum rk_usb_type sc_type;
86
87 struct clk_domain sc_clkdom;
88 struct rk_usb_clk sc_usbclk;
89
90 bus_addr_t sc_reg;
91 };
92
93 CFATTACH_DECL_NEW(rk_usb, sizeof(struct rk_usb_softc),
94 rk_usb_match, rk_usb_attach, NULL, NULL);
95
96 static struct clk *
97 rk_usb_clk_get(void *priv, const char *name)
98 {
99 struct rk_usb_softc * const sc = priv;
100
101 if (strcmp(name, sc->sc_usbclk.base.name) != 0)
102 return NULL;
103
104 return &sc->sc_usbclk.base;
105 }
106
107 static void
108 rk_usb_clk_put(void *priv, struct clk *clk)
109 {
110 }
111
112 static u_int
113 rk_usb_clk_get_rate(void *priv, struct clk *clk)
114 {
115 return 480000000;
116 }
117
118 static int
119 rk_usb_clk_enable(void *priv, struct clk *clk)
120 {
121 struct rk_usb_softc * const sc = priv;
122 uint32_t reg, write_mask, write_val;
123
124 switch (sc->sc_type) {
125 case USB_RK3328:
126 reg = RK3328_CON2_REG;
127 write_mask = RK3328_USBPHY_COMMONONN << 16;
128 write_val = 0;
129 break;
130 case USB_RK3399:
131 reg = RK3399_PHY_NO(sc) == 0 ?
132 RK3399_GRF_USB20_PHY0_CON0_REG :
133 RK3399_GRF_USB20_PHY1_CON0_REG;
134 write_mask = RK3399_USBPHY_COMMONONN << 16;
135 write_val = 0;
136 break;
137 default:
138 return ENXIO;
139 }
140
141 syscon_lock(sc->sc_syscon);
142 syscon_write_4(sc->sc_syscon, reg, write_mask | write_val);
143 syscon_unlock(sc->sc_syscon);
144
145 return 0;
146 }
147
148 static int
149 rk_usb_clk_disable(void *priv, struct clk *clk)
150 {
151 struct rk_usb_softc * const sc = priv;
152 uint32_t reg, write_mask, write_val;
153
154 switch (sc->sc_type) {
155 case USB_RK3328:
156 reg = RK3328_CON2_REG;
157 write_mask = RK3328_USBPHY_COMMONONN << 16;
158 write_val = RK3328_USBPHY_COMMONONN;
159 break;
160 case USB_RK3399:
161 reg = RK3399_PHY_NO(sc) == 0 ?
162 RK3399_GRF_USB20_PHY0_CON0_REG :
163 RK3399_GRF_USB20_PHY1_CON0_REG;
164 write_mask = RK3399_USBPHY_COMMONONN << 16;
165 write_val = RK3399_USBPHY_COMMONONN;
166 break;
167 default:
168 return ENXIO;
169 }
170
171 syscon_lock(sc->sc_syscon);
172 syscon_write_4(sc->sc_syscon, reg, write_mask | write_val);
173 syscon_unlock(sc->sc_syscon);
174
175 return 0;
176 }
177
178 static const struct clk_funcs rk_usb_clk_funcs = {
179 .get = rk_usb_clk_get,
180 .put = rk_usb_clk_put,
181 .get_rate = rk_usb_clk_get_rate,
182 .enable = rk_usb_clk_enable,
183 .disable = rk_usb_clk_disable,
184 };
185
186 static struct clk *
187 rk_usb_fdt_decode(device_t dev, int cc_phandle, const void *data, size_t len)
188 {
189 struct rk_usb_softc * const sc = device_private(dev);
190
191 if (len != 0)
192 return NULL;
193
194 return &sc->sc_usbclk.base;
195 }
196
197 static const struct fdtbus_clock_controller_func rk_usb_fdt_funcs = {
198 .decode = rk_usb_fdt_decode
199 };
200
201 static int
202 rk_usb_match(device_t parent, cfdata_t cf, void *aux)
203 {
204 struct fdt_attach_args * const faa = aux;
205
206 return of_match_compat_data(faa->faa_phandle, compat_data);
207 }
208
209 static void
210 rk_usb_attach(device_t parent, device_t self, void *aux)
211 {
212 struct rk_usb_softc * const sc = device_private(self);
213 struct fdt_attach_args * const faa = aux;
214 const int phandle = faa->faa_phandle;
215 struct clk *clk;
216 int child;
217
218 /* Cache the base address of this PHY so we know which instance we are */
219 if (fdtbus_get_reg(phandle, 0, &sc->sc_reg, NULL) != 0) {
220 aprint_error(": couldn't get registers\n");
221 return;
222 }
223
224 clk = fdtbus_clock_get(phandle, "phyclk");
225 if (clk && clk_enable(clk) != 0) {
226 aprint_error(": couldn't enable phy clock\n");
227 return;
228 }
229
230 sc->sc_dev = self;
231 sc->sc_type = of_search_compatible(phandle, compat_data)->value;
232 sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(phandle));
233 if (sc->sc_syscon == NULL) {
234 aprint_error(": couldn't get grf syscon\n");
235 return;
236 }
237
238 const char *clkname = fdtbus_get_string(phandle, "clock-output-names");
239 if (clkname == NULL)
240 clkname = faa->faa_name;
241
242 sc->sc_clkdom.name = device_xname(self);
243 sc->sc_clkdom.funcs = &rk_usb_clk_funcs;
244 sc->sc_clkdom.priv = sc;
245 sc->sc_usbclk.base.domain = &sc->sc_clkdom;
246 sc->sc_usbclk.base.name = kmem_asprintf("%s", clkname);
247 clk_attach(&sc->sc_usbclk.base);
248
249 aprint_naive("\n");
250 aprint_normal(": USB2 PHY\n");
251
252 fdtbus_register_clock_controller(self, phandle, &rk_usb_fdt_funcs);
253
254 for (child = OF_child(phandle); child; child = OF_peer(child)) {
255 if (!fdtbus_status_okay(child))
256 continue;
257
258 struct fdt_attach_args cfaa = *faa;
259 cfaa.faa_phandle = child;
260 cfaa.faa_name = fdtbus_get_string(child, "name");
261 cfaa.faa_quiet = false;
262
263 config_found(self, &cfaa, NULL);
264 }
265 }
266
267 /*
268 * USB PHY
269 */
270
271 static int rk_usbphy_match(device_t, cfdata_t, void *);
272 static void rk_usbphy_attach(device_t, device_t, void *);
273
274 struct rk_usbphy_softc {
275 device_t sc_dev;
276 int sc_phandle;
277 struct fdtbus_regulator *sc_supply;
278 };
279
280 CFATTACH_DECL_NEW(rk_usbphy, sizeof(struct rk_usbphy_softc),
281 rk_usbphy_match, rk_usbphy_attach, NULL, NULL);
282
283 static void *
284 rk_usbphy_acquire(device_t dev, const void *data, size_t len)
285 {
286 struct rk_usbphy_softc * const sc = device_private(dev);
287
288 if (len != 0)
289 return NULL;
290
291 return sc;
292 }
293
294 static void
295 rk_usbphy_release(device_t dev, void *priv)
296 {
297 }
298
299 static int
300 rk_usbphy_otg_enable(device_t dev, void *priv, bool enable)
301 {
302 struct rk_usbphy_softc * const sc = device_private(dev);
303 struct rk_usb_softc * const usb_sc = device_private(device_parent(dev));
304 uint32_t reg, write_mask, write_val;
305 int error;
306
307 switch (usb_sc->sc_type) {
308 case USB_RK3328:
309 reg = RK3328_CON0_REG;
310 write_mask = 0x1ffU << 16;
311 write_val = enable ? 0 : 0x1d1;
312 break;
313 case USB_RK3399:
314 reg = RK3399_PHY_NO(usb_sc) == 0 ?
315 RK3399_GRF_USB20_PHY0_CON1_REG :
316 RK3399_GRF_USB20_PHY1_CON1_REG;
317 write_mask = (RK3399_USBPHY_SUSPEND_N|RK3399_USBPHY_UTMI_SEL) << 16;
318 write_val = enable ? 0 : RK3399_USBPHY_UTMI_SEL;
319 break;
320 default:
321 return ENXIO;
322 }
323
324 if (sc->sc_supply) {
325 error = enable ? fdtbus_regulator_enable(sc->sc_supply) :
326 fdtbus_regulator_disable(sc->sc_supply);
327 if (error != 0)
328 return error;
329 }
330
331 syscon_lock(usb_sc->sc_syscon);
332 syscon_write_4(usb_sc->sc_syscon, reg, write_mask | write_val);
333 syscon_unlock(usb_sc->sc_syscon);
334
335 return 0;
336 }
337
338 static int
339 rk_usbphy_host_enable(device_t dev, void *priv, bool enable)
340 {
341 struct rk_usbphy_softc * const sc = device_private(dev);
342 struct rk_usb_softc * const usb_sc = device_private(device_parent(dev));
343 uint32_t reg, write_mask, write_val;
344 int error;
345
346 switch (usb_sc->sc_type) {
347 case USB_RK3328:
348 reg = RK3328_CON1_REG;
349 write_mask = 0x1ffU << 16;
350 write_val = enable ? 0 : 0x1d1;
351 break;
352 case USB_RK3399:
353 reg = RK3399_PHY_NO(usb_sc) == 0 ?
354 RK3399_GRF_USB20_PHY0_CON2_REG :
355 RK3399_GRF_USB20_PHY1_CON2_REG;
356 write_mask = (RK3399_USBPHY_SUSPEND_N|RK3399_USBPHY_UTMI_SEL) << 16;
357 write_val = enable ? 0 : RK3399_USBPHY_UTMI_SEL;
358 break;
359 default:
360 return ENXIO;
361 }
362
363 if (sc->sc_supply) {
364 error = enable ? fdtbus_regulator_enable(sc->sc_supply) :
365 fdtbus_regulator_disable(sc->sc_supply);
366 if (error != 0)
367 return error;
368 }
369
370 syscon_lock(usb_sc->sc_syscon);
371 syscon_write_4(usb_sc->sc_syscon, reg, write_mask | write_val);
372 syscon_unlock(usb_sc->sc_syscon);
373
374 return 0;
375 }
376
377 const struct fdtbus_phy_controller_func rk_usbphy_otg_funcs = {
378 .acquire = rk_usbphy_acquire,
379 .release = rk_usbphy_release,
380 .enable = rk_usbphy_otg_enable,
381 };
382
383 const struct fdtbus_phy_controller_func rk_usbphy_host_funcs = {
384 .acquire = rk_usbphy_acquire,
385 .release = rk_usbphy_release,
386 .enable = rk_usbphy_host_enable,
387 };
388
389 static int
390 rk_usbphy_match(device_t parent, cfdata_t cf, void *aux)
391 {
392 struct fdt_attach_args * const faa = aux;
393 const int phandle = faa->faa_phandle;
394 const char *name = fdtbus_get_string(phandle, "name");
395
396 if (strcmp(name, "otg-port") == 0 || strcmp(name, "host-port") == 0)
397 return 1;
398
399 return 0;
400 }
401
402 static void
403 rk_usbphy_attach(device_t parent, device_t self, void *aux)
404 {
405 struct rk_usbphy_softc * const sc = device_private(self);
406 struct fdt_attach_args * const faa = aux;
407 const int phandle = faa->faa_phandle;
408 const char *name = fdtbus_get_string(phandle, "name");
409
410 sc->sc_dev = self;
411 sc->sc_phandle = phandle;
412 if (of_hasprop(phandle, "phy-supply")) {
413 sc->sc_supply = fdtbus_regulator_acquire(phandle, "phy-supply");
414 if (sc->sc_supply == NULL) {
415 aprint_error(": couldn't acquire regulator\n");
416 return;
417 }
418 }
419
420 aprint_naive("\n");
421
422 if (strcmp(name, "otg-port") == 0) {
423 aprint_normal(": USB2 OTG port\n");
424 fdtbus_register_phy_controller(self, phandle, &rk_usbphy_otg_funcs);
425 } else if (strcmp(name, "host-port") == 0) {
426 aprint_normal(": USB2 host port\n");
427 fdtbus_register_phy_controller(self, phandle, &rk_usbphy_host_funcs);
428 }
429 }
430