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 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 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 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