xref: /openbsd/sys/dev/fdt/bcm2835_dwctwo.c (revision a9beb1ed)
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