1 /* $OpenBSD: bcm2835_dwctwo.c,v 1.4 2022/09/04 08:42:39 mglocker Exp $ */
2 /*
3 * Copyright (c) 2015 Masao Uebayashi <uebayasi@tombiinc.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 #include <sys/pool.h>
23 #include <sys/kthread.h>
24
25 #include <machine/intr.h>
26 #include <machine/bus.h>
27 #include <machine/fdt.h>
28
29 #include <dev/ofw/openfirm.h>
30 #include <dev/ofw/fdt.h>
31
32 #include <dev/usb/usb.h>
33 #include <dev/usb/usbdi.h>
34 #include <dev/usb/usbdivar.h>
35 #include <dev/usb/usb_mem.h>
36 #include <dev/usb/usb_quirks.h>
37
38 #include <dev/usb/dwc2/dwc2var.h>
39 #include <dev/usb/dwc2/dwc2.h>
40 #include <dev/usb/dwc2/dwc2_core.h>
41
42 struct bcm_dwctwo_softc {
43 struct dwc2_softc sc_dwc2;
44 void *sc_ih;
45 };
46
47 int bcm_dwctwo_match(struct device *, void *, void *);
48 void bcm_dwctwo_attach(struct device *, struct device *, void *);
49 void bcm_dwctwo_deferred(void *);
50
51 const struct cfattach bcmdwctwo_ca = {
52 sizeof(struct bcm_dwctwo_softc), bcm_dwctwo_match, bcm_dwctwo_attach,
53 };
54
55 struct cfdriver dwctwo_cd = {
56 NULL, "dwctwo", DV_DULL
57 };
58
59 static struct dwc2_core_params bcm_dwctwo_params = {
60 .otg_caps.hnp_support = 0, /* HNP/SRP capable */
61 .otg_caps.srp_support = 0,
62 .host_dma = 1,
63 .dma_desc_enable = 0,
64 .speed = 0, /* High Speed */
65 .enable_dynamic_fifo = 1,
66 .en_multiple_tx_fifo = 1,
67 .host_rx_fifo_size = 774, /* 774 DWORDs */
68 .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */
69 .host_perio_tx_fifo_size = 512, /* 512 DWORDs */
70 .max_transfer_size = 65535,
71 .max_packet_count = 511,
72 .host_channels = 8,
73 .phy_type = 1, /* UTMI */
74 .phy_utmi_width = 8, /* 8 bits */
75 .phy_ulpi_ddr = 0, /* Single */
76 .phy_ulpi_ext_vbus = 0,
77 .i2c_enable = 0,
78 .ulpi_fs_ls = 0,
79 .host_support_fs_ls_low_power = 0,
80 .host_ls_low_power_phy_clk = 0, /* 48 MHz */
81 .ts_dline = 0,
82 .reload_ctl = 0,
83 .ahbcfg = 0x10,
84 .uframe_sched = 1,
85 .external_id_pin_ctl = 0,
86 };
87
88 int
bcm_dwctwo_match(struct device * parent,void * match,void * aux)89 bcm_dwctwo_match(struct device *parent, void *match, void *aux)
90 {
91 struct fdt_attach_args *faa = (struct fdt_attach_args *)aux;
92
93 return (OF_is_compatible(faa->fa_node, "brcm,bcm2708-usb") ||
94 OF_is_compatible(faa->fa_node, "brcm,bcm2835-usb"));
95 }
96
97 void
bcm_dwctwo_attach(struct device * parent,struct device * self,void * aux)98 bcm_dwctwo_attach(struct device *parent, struct device *self, void *aux)
99 {
100 struct bcm_dwctwo_softc *sc = (struct bcm_dwctwo_softc *)self;
101 struct fdt_attach_args *faa = aux;
102 int idx;
103
104 printf("\n");
105
106 sc->sc_dwc2.sc_iot = faa->fa_iot;
107 sc->sc_dwc2.sc_bus.pipe_size = sizeof(struct usbd_pipe);
108 sc->sc_dwc2.sc_bus.dmatag = faa->fa_dmat;
109 sc->sc_dwc2.sc_params = &bcm_dwctwo_params;
110
111 if (bus_space_map(faa->fa_iot, faa->fa_reg[0].addr,
112 faa->fa_reg[0].size, 0, &sc->sc_dwc2.sc_ioh))
113 panic("%s: bus_space_map failed!", __func__);
114
115 idx = OF_getindex(faa->fa_node, "usb", "interrupt-names");
116 if (idx == -1)
117 idx = 1;
118
119 sc->sc_ih = fdt_intr_establish_idx(faa->fa_node, idx,
120 IPL_VM | IPL_MPSAFE, dwc2_intr, (void *)&sc->sc_dwc2,
121 sc->sc_dwc2.sc_bus.bdev.dv_xname);
122 if (sc->sc_ih == NULL)
123 panic("%s: intr_establish failed!", __func__);
124
125 kthread_create_deferred(bcm_dwctwo_deferred, sc);
126 }
127
128 void
bcm_dwctwo_deferred(void * self)129 bcm_dwctwo_deferred(void *self)
130 {
131 struct bcm_dwctwo_softc *sc = (struct bcm_dwctwo_softc *)self;
132 int rc;
133
134 strlcpy(sc->sc_dwc2.sc_vendor, "Broadcom",
135 sizeof(sc->sc_dwc2.sc_vendor));
136
137 rc = dwc2_init(&sc->sc_dwc2);
138 if (rc != 0)
139 return;
140
141 sc->sc_dwc2.sc_child = config_found(&sc->sc_dwc2.sc_bus.bdev,
142 &sc->sc_dwc2.sc_bus, usbctlprint);
143 }
144