1 /*-
2 * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 /*
27 * Allwinner USB PHY
28 */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/rman.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/gpio.h>
37 #include <machine/bus.h>
38
39 #include <dev/ofw/ofw_bus.h>
40 #include <dev/ofw/ofw_bus_subr.h>
41 #include <dev/gpio/gpiobusvar.h>
42
43 #include <dev/clk/clk.h>
44 #include <dev/hwreset/hwreset.h>
45 #include <dev/regulator/regulator.h>
46 #include <dev/phy/phy_usb.h>
47
48 #include "phynode_if.h"
49
50 enum awusbphy_type {
51 AWUSBPHY_TYPE_A10 = 1,
52 AWUSBPHY_TYPE_A13,
53 AWUSBPHY_TYPE_A20,
54 AWUSBPHY_TYPE_A31,
55 AWUSBPHY_TYPE_H3,
56 AWUSBPHY_TYPE_A64,
57 AWUSBPHY_TYPE_A83T,
58 AWUSBPHY_TYPE_H6,
59 AWUSBPHY_TYPE_D1,
60 };
61
62 struct aw_usbphy_conf {
63 int num_phys;
64 enum awusbphy_type phy_type;
65 bool pmu_unk1;
66 bool phy0_route;
67 };
68
69 static const struct aw_usbphy_conf a10_usbphy_conf = {
70 .num_phys = 3,
71 .phy_type = AWUSBPHY_TYPE_A10,
72 .pmu_unk1 = false,
73 .phy0_route = false,
74 };
75
76 static const struct aw_usbphy_conf a13_usbphy_conf = {
77 .num_phys = 2,
78 .phy_type = AWUSBPHY_TYPE_A13,
79 .pmu_unk1 = false,
80 .phy0_route = false,
81 };
82
83 static const struct aw_usbphy_conf a20_usbphy_conf = {
84 .num_phys = 3,
85 .phy_type = AWUSBPHY_TYPE_A20,
86 .pmu_unk1 = false,
87 .phy0_route = false,
88 };
89
90 static const struct aw_usbphy_conf a31_usbphy_conf = {
91 .num_phys = 3,
92 .phy_type = AWUSBPHY_TYPE_A31,
93 .pmu_unk1 = false,
94 .phy0_route = false,
95 };
96
97 static const struct aw_usbphy_conf h3_usbphy_conf = {
98 .num_phys = 4,
99 .phy_type = AWUSBPHY_TYPE_H3,
100 .pmu_unk1 = true,
101 .phy0_route = true,
102 };
103
104 static const struct aw_usbphy_conf a64_usbphy_conf = {
105 .num_phys = 2,
106 .phy_type = AWUSBPHY_TYPE_A64,
107 .pmu_unk1 = true,
108 .phy0_route = true,
109 };
110
111 static const struct aw_usbphy_conf a83t_usbphy_conf = {
112 .num_phys = 3,
113 .phy_type = AWUSBPHY_TYPE_A83T,
114 .pmu_unk1 = false,
115 .phy0_route = false,
116 };
117
118 static const struct aw_usbphy_conf h6_usbphy_conf = {
119 .num_phys = 4,
120 .phy_type = AWUSBPHY_TYPE_H6,
121 .pmu_unk1 = false,
122 .phy0_route = true,
123 };
124
125 static const struct aw_usbphy_conf d1_usbphy_conf = {
126 .num_phys = 2,
127 .phy_type = AWUSBPHY_TYPE_D1,
128 .pmu_unk1 = true,
129 .phy0_route = true,
130 };
131
132 static struct ofw_compat_data compat_data[] = {
133 { "allwinner,sun4i-a10-usb-phy", (uintptr_t)&a10_usbphy_conf },
134 { "allwinner,sun5i-a13-usb-phy", (uintptr_t)&a13_usbphy_conf },
135 { "allwinner,sun6i-a31-usb-phy", (uintptr_t)&a31_usbphy_conf },
136 { "allwinner,sun7i-a20-usb-phy", (uintptr_t)&a20_usbphy_conf },
137 { "allwinner,sun8i-h3-usb-phy", (uintptr_t)&h3_usbphy_conf },
138 { "allwinner,sun50i-a64-usb-phy", (uintptr_t)&a64_usbphy_conf },
139 { "allwinner,sun8i-a83t-usb-phy", (uintptr_t)&a83t_usbphy_conf },
140 { "allwinner,sun50i-h6-usb-phy", (uintptr_t)&h6_usbphy_conf },
141 { "allwinner,sun20i-d1-usb-phy", (uintptr_t)&d1_usbphy_conf },
142 { NULL, 0 }
143 };
144
145 struct awusbphy_softc {
146 struct resource * phy_ctrl;
147 struct resource ** pmu;
148 regulator_t * reg;
149 gpio_pin_t id_det_pin;
150 int id_det_valid;
151 gpio_pin_t vbus_det_pin;
152 int vbus_det_valid;
153 struct aw_usbphy_conf *phy_conf;
154 int mode;
155 };
156
157 /* Phy class and methods. */
158 static int awusbphy_phy_enable(struct phynode *phy, bool enable);
159 static int awusbphy_get_mode(struct phynode *phy, int *mode);
160 static int awusbphy_set_mode(struct phynode *phy, int mode);
161 static phynode_usb_method_t awusbphy_phynode_methods[] = {
162 PHYNODEMETHOD(phynode_enable, awusbphy_phy_enable),
163 PHYNODEMETHOD(phynode_usb_get_mode, awusbphy_get_mode),
164 PHYNODEMETHOD(phynode_usb_set_mode, awusbphy_set_mode),
165
166 PHYNODEMETHOD_END
167 };
168 DEFINE_CLASS_1(awusbphy_phynode, awusbphy_phynode_class, awusbphy_phynode_methods,
169 sizeof(struct phynode_usb_sc), phynode_usb_class);
170
171 #define RD4(res, o) bus_read_4(res, (o))
172 #define WR4(res, o, v) bus_write_4(res, (o), (v))
173 #define CLR4(res, o, m) WR4(res, o, RD4(res, o) & ~(m))
174 #define SET4(res, o, m) WR4(res, o, RD4(res, o) | (m))
175
176 #define PHY_CSR 0x00
177 #define ID_PULLUP_EN (1 << 17)
178 #define DPDM_PULLUP_EN (1 << 16)
179 #define FORCE_ID (0x3 << 14)
180 #define FORCE_ID_SHIFT 14
181 #define FORCE_ID_LOW 2
182 #define FORCE_ID_HIGH 3
183 #define FORCE_VBUS_VALID (0x3 << 12)
184 #define FORCE_VBUS_VALID_SHIFT 12
185 #define FORCE_VBUS_VALID_LOW 2
186 #define FORCE_VBUS_VALID_HIGH 3
187 #define VBUS_CHANGE_DET (1 << 6)
188 #define ID_CHANGE_DET (1 << 5)
189 #define DPDM_CHANGE_DET (1 << 4)
190 #define OTG_PHY_CFG 0x20
191 #define OTG_PHY_ROUTE_OTG (1 << 0)
192 #define PMU_IRQ_ENABLE 0x00
193 #define PMU_AHB_INCR8 (1 << 10)
194 #define PMU_AHB_INCR4 (1 << 9)
195 #define PMU_AHB_INCRX_ALIGN (1 << 8)
196 #define PMU_ULPI_BYPASS (1 << 0)
197 #define PMU_UNK_H3 0x10
198 #define PMU_UNK_H3_CLR 0x2
199
200 static void
awusbphy_configure(device_t dev,int phyno)201 awusbphy_configure(device_t dev, int phyno)
202 {
203 struct awusbphy_softc *sc;
204
205 sc = device_get_softc(dev);
206
207 if (sc->pmu[phyno] == NULL)
208 return;
209
210 if (sc->phy_conf->pmu_unk1 == true)
211 CLR4(sc->pmu[phyno], PMU_UNK_H3, PMU_UNK_H3_CLR);
212
213 SET4(sc->pmu[phyno], PMU_IRQ_ENABLE, PMU_ULPI_BYPASS |
214 PMU_AHB_INCR8 | PMU_AHB_INCR4 | PMU_AHB_INCRX_ALIGN);
215 }
216
217 static int
awusbphy_init(device_t dev)218 awusbphy_init(device_t dev)
219 {
220 struct awusbphy_softc *sc;
221 phandle_t node;
222 char pname[20];
223 uint32_t val;
224 int error, off, rid;
225 regulator_t reg;
226 hwreset_t rst;
227 clk_t clk;
228
229 sc = device_get_softc(dev);
230 node = ofw_bus_get_node(dev);
231
232 sc->phy_conf = (struct aw_usbphy_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
233
234 /* Get phy_ctrl region */
235 if (ofw_bus_find_string_index(node, "reg-names", "phy_ctrl", &rid) != 0) {
236 device_printf(dev, "Cannot locate phy control resource\n");
237 return (ENXIO);
238 }
239 sc->phy_ctrl = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
240 RF_ACTIVE);
241 if (sc->phy_ctrl == NULL) {
242 device_printf(dev, "Cannot allocate resource\n");
243 return (ENXIO);
244 }
245
246 /* Enable clocks */
247 for (off = 0; clk_get_by_ofw_index(dev, 0, off, &clk) == 0; off++) {
248 error = clk_enable(clk);
249 if (error != 0) {
250 device_printf(dev, "couldn't enable clock %s\n",
251 clk_get_name(clk));
252 return (error);
253 }
254 }
255
256 /* De-assert resets */
257 for (off = 0; hwreset_get_by_ofw_idx(dev, 0, off, &rst) == 0; off++) {
258 error = hwreset_deassert(rst);
259 if (error != 0) {
260 device_printf(dev, "couldn't de-assert reset %d\n",
261 off);
262 return (error);
263 }
264 }
265
266 /* Get GPIOs */
267 error = gpio_pin_get_by_ofw_property(dev, node, "usb0_id_det-gpios",
268 &sc->id_det_pin);
269 if (error == 0)
270 sc->id_det_valid = 1;
271 error = gpio_pin_get_by_ofw_property(dev, node, "usb0_vbus_det-gpios",
272 &sc->vbus_det_pin);
273 if (error == 0)
274 sc->vbus_det_valid = 1;
275
276 sc->reg = malloc(sizeof(*(sc->reg)) * sc->phy_conf->num_phys, M_DEVBUF,
277 M_WAITOK | M_ZERO);
278 sc->pmu = malloc(sizeof(*(sc->pmu)) * sc->phy_conf->num_phys, M_DEVBUF,
279 M_WAITOK | M_ZERO);
280 /* Get regulators */
281 for (off = 0; off < sc->phy_conf->num_phys; off++) {
282 snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off);
283 if (regulator_get_by_ofw_property(dev, 0, pname, ®) == 0)
284 sc->reg[off] = reg;
285
286 snprintf(pname, sizeof(pname), "pmu%d", off);
287 if (ofw_bus_find_string_index(node, "reg-names",
288 pname, &rid) != 0)
289 continue;
290
291 sc->pmu[off] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
292 RF_ACTIVE);
293 if (sc->pmu[off] == NULL) {
294 device_printf(dev, "Cannot allocate resource\n");
295 return (ENXIO);
296 }
297 }
298
299 /* Enable OTG PHY for host mode */
300 val = bus_read_4(sc->phy_ctrl, PHY_CSR);
301 val &= ~(VBUS_CHANGE_DET | ID_CHANGE_DET | DPDM_CHANGE_DET);
302 val |= (ID_PULLUP_EN | DPDM_PULLUP_EN);
303 val &= ~FORCE_ID;
304 val |= (FORCE_ID_LOW << FORCE_ID_SHIFT);
305 val &= ~FORCE_VBUS_VALID;
306 val |= (FORCE_VBUS_VALID_HIGH << FORCE_VBUS_VALID_SHIFT);
307 bus_write_4(sc->phy_ctrl, PHY_CSR, val);
308
309 return (0);
310 }
311
312 static int
awusbphy_vbus_detect(device_t dev,int * val)313 awusbphy_vbus_detect(device_t dev, int *val)
314 {
315 struct awusbphy_softc *sc;
316 bool active;
317 int error;
318
319 sc = device_get_softc(dev);
320
321 if (sc->vbus_det_valid) {
322 error = gpio_pin_is_active(sc->vbus_det_pin, &active);
323 if (error != 0) {
324 device_printf(dev, "Cannot get status of id pin %d\n",
325 error);
326 return (error);
327 }
328 *val = active;
329 return (0);
330 }
331
332 /* TODO check vbus_power-supply. */
333
334 /*
335 * If there is no way to detect, assume present.
336 */
337 *val = 1;
338 return (0);
339 }
340
341 static int
awusbphy_phy_enable(struct phynode * phynode,bool enable)342 awusbphy_phy_enable(struct phynode *phynode, bool enable)
343 {
344 device_t dev;
345 intptr_t phy;
346 struct awusbphy_softc *sc;
347 regulator_t reg;
348 int error, vbus_det;
349
350 dev = phynode_get_device(phynode);
351 phy = phynode_get_id(phynode);
352 sc = device_get_softc(dev);
353
354 if (phy < 0 || phy >= sc->phy_conf->num_phys)
355 return (ERANGE);
356
357 /* Configure PHY */
358 awusbphy_configure(dev, phy);
359
360 /* Regulators are optional. If not found, return success. */
361 reg = sc->reg[phy];
362 if (reg == NULL)
363 return (0);
364
365 if (phy == 0) {
366 /* If an external vbus is detected, do not enable phy 0 */
367 error = awusbphy_vbus_detect(dev, &vbus_det);
368 if (error)
369 goto out;
370
371 /* TODO check vbus_power-supply as well. */
372 if (sc->vbus_det_valid && vbus_det == 1) {
373 if (bootverbose)
374 device_printf(dev, "External VBUS detected, "
375 "not enabling the regulator\n");
376 return (0);
377 }
378 }
379 if (enable) {
380 /* Depending on the PHY we need to route OTG to OHCI/EHCI */
381 error = regulator_enable(reg);
382 } else
383 error = regulator_disable(reg);
384
385 out:
386 if (error != 0) {
387 device_printf(dev,
388 "couldn't %s regulator for phy %jd\n",
389 enable ? "enable" : "disable", (intmax_t)phy);
390 return (error);
391 }
392
393 return (0);
394 }
395
396 static int
awusbphy_get_mode(struct phynode * phynode,int * mode)397 awusbphy_get_mode(struct phynode *phynode, int *mode)
398 {
399 struct awusbphy_softc *sc;
400 device_t dev;
401
402 dev = phynode_get_device(phynode);
403 sc = device_get_softc(dev);
404
405 *mode = sc->mode;
406
407 return (0);
408 }
409
410 static int
awusbphy_set_mode(struct phynode * phynode,int mode)411 awusbphy_set_mode(struct phynode *phynode, int mode)
412 {
413 device_t dev;
414 intptr_t phy;
415 struct awusbphy_softc *sc;
416 uint32_t val;
417 int error, vbus_det;
418
419 dev = phynode_get_device(phynode);
420 phy = phynode_get_id(phynode);
421 sc = device_get_softc(dev);
422
423 if (phy != 0) {
424 if (mode != PHY_USB_MODE_HOST)
425 return (EINVAL);
426 return (0);
427 }
428
429 if (sc->mode == mode)
430 return (0);
431 if (mode == PHY_USB_MODE_OTG) /* TODO */
432 return (EOPNOTSUPP);
433
434 error = awusbphy_vbus_detect(dev, &vbus_det);
435 if (error != 0)
436 return (error);
437
438 val = bus_read_4(sc->phy_ctrl, PHY_CSR);
439 val &= ~(VBUS_CHANGE_DET | ID_CHANGE_DET | DPDM_CHANGE_DET);
440 val |= (ID_PULLUP_EN | DPDM_PULLUP_EN);
441 val &= ~FORCE_VBUS_VALID;
442 val |= (vbus_det ? FORCE_VBUS_VALID_HIGH : FORCE_VBUS_VALID_LOW) <<
443 FORCE_VBUS_VALID_SHIFT;
444 val &= ~FORCE_ID;
445
446 switch (mode) {
447 case PHY_USB_MODE_HOST:
448 val |= (FORCE_ID_LOW << FORCE_ID_SHIFT);
449 if (sc->phy_conf->phy0_route)
450 CLR4(sc->phy_ctrl, OTG_PHY_CFG, OTG_PHY_ROUTE_OTG);
451 break;
452 case PHY_USB_MODE_DEVICE:
453 val |= (FORCE_ID_HIGH << FORCE_ID_SHIFT);
454 if (sc->phy_conf->phy0_route)
455 SET4(sc->phy_ctrl, OTG_PHY_CFG, OTG_PHY_ROUTE_OTG);
456 break;
457 default:
458 return (EINVAL);
459 }
460
461 bus_write_4(sc->phy_ctrl, PHY_CSR, val);
462 sc->mode = mode;
463 return (0);
464 }
465
466 static int
awusbphy_probe(device_t dev)467 awusbphy_probe(device_t dev)
468 {
469 if (!ofw_bus_status_okay(dev))
470 return (ENXIO);
471
472 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
473 return (ENXIO);
474
475 device_set_desc(dev, "Allwinner USB PHY");
476 return (BUS_PROBE_DEFAULT);
477 }
478
479 static int
awusbphy_attach(device_t dev)480 awusbphy_attach(device_t dev)
481 {
482 int error;
483 struct phynode *phynode;
484 struct phynode_init_def phy_init;
485 struct awusbphy_softc *sc;
486 int i;
487
488 sc = device_get_softc(dev);
489 error = awusbphy_init(dev);
490 if (error) {
491 device_printf(dev, "failed to initialize USB PHY, error %d\n",
492 error);
493 return (error);
494 }
495
496 /* Create and register phys. */
497 for (i = 0; i < sc->phy_conf->num_phys; i++) {
498 bzero(&phy_init, sizeof(phy_init));
499 phy_init.id = i;
500 phy_init.ofw_node = ofw_bus_get_node(dev);
501 phynode = phynode_create(dev, &awusbphy_phynode_class,
502 &phy_init);
503 if (phynode == NULL) {
504 device_printf(dev, "failed to create USB PHY\n");
505 return (ENXIO);
506 }
507 if (phynode_register(phynode) == NULL) {
508 device_printf(dev, "failed to create USB PHY\n");
509 return (ENXIO);
510 }
511 }
512
513 return (error);
514 }
515
516 static device_method_t awusbphy_methods[] = {
517 /* Device interface */
518 DEVMETHOD(device_probe, awusbphy_probe),
519 DEVMETHOD(device_attach, awusbphy_attach),
520
521 DEVMETHOD_END
522 };
523
524 static driver_t awusbphy_driver = {
525 "awusbphy",
526 awusbphy_methods,
527 sizeof(struct awusbphy_softc)
528 };
529
530 /* aw_usbphy needs to come up after regulators/gpio/etc, but before ehci/ohci */
531 EARLY_DRIVER_MODULE(awusbphy, simplebus, awusbphy_driver, 0, 0,
532 BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
533 MODULE_VERSION(awusbphy, 1);
534