/* $OpenBSD: bcm2835_dwctwo.c,v 1.2 2017/02/22 04:39:30 jsg Exp $ */ /* * Copyright (c) 2015 Masao Uebayashi * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct bcm_dwctwo_softc { struct dwc2_softc sc_dwc2; struct arm32_bus_dma_tag sc_dmat; struct arm32_dma_range sc_dmarange[1]; void *sc_ih; }; int bcm_dwctwo_match(struct device *, void *, void *); void bcm_dwctwo_attach(struct device *, struct device *, void *); void bcm_dwctwo_deferred(void *); const struct cfattach bcmdwctwo_ca = { sizeof(struct bcm_dwctwo_softc), bcm_dwctwo_match, bcm_dwctwo_attach, }; struct cfdriver dwctwo_cd = { NULL, "dwctwo", DV_DULL }; static struct dwc2_core_params bcm_dwctwo_params = { .otg_cap = 0, /* HNP/SRP capable */ .otg_ver = 0, /* 1.3 */ .dma_enable = 1, .dma_desc_enable = 0, .speed = 0, /* High Speed */ .enable_dynamic_fifo = 1, .en_multiple_tx_fifo = 1, .host_rx_fifo_size = 774, /* 774 DWORDs */ .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */ .host_perio_tx_fifo_size = 512, /* 512 DWORDs */ .max_transfer_size = 65535, .max_packet_count = 511, .host_channels = 8, .phy_type = 1, /* UTMI */ .phy_utmi_width = 8, /* 8 bits */ .phy_ulpi_ddr = 0, /* Single */ .phy_ulpi_ext_vbus = 0, .i2c_enable = 0, .ulpi_fs_ls = 0, .host_support_fs_ls_low_power = 0, .host_ls_low_power_phy_clk = 0, /* 48 MHz */ .ts_dline = 0, .reload_ctl = 0, .ahbcfg = 0x10, .uframe_sched = 1, }; int bcm_dwctwo_match(struct device *parent, void *match, void *aux) { struct fdt_attach_args *faa = (struct fdt_attach_args *)aux; return (OF_is_compatible(faa->fa_node, "brcm,bcm2708-usb") || OF_is_compatible(faa->fa_node, "brcm,bcm2835-usb")); } void bcm_dwctwo_attach(struct device *parent, struct device *self, void *aux) { struct bcm_dwctwo_softc *sc = (struct bcm_dwctwo_softc *)self; struct fdt_attach_args *faa = aux; extern int physmem; printf("\n"); memcpy(&sc->sc_dmat, faa->fa_dmat, sizeof(sc->sc_dmat)); sc->sc_dmarange[0].dr_sysbase = 0; sc->sc_dmarange[0].dr_busbase = 0xC0000000; sc->sc_dmarange[0].dr_len = physmem * PAGE_SIZE; sc->sc_dmat._ranges = sc->sc_dmarange; sc->sc_dmat._nranges = 1; sc->sc_dwc2.sc_iot = faa->fa_iot; sc->sc_dwc2.sc_bus.pipe_size = sizeof(struct usbd_pipe); sc->sc_dwc2.sc_bus.dmatag = &sc->sc_dmat; sc->sc_dwc2.sc_params = &bcm_dwctwo_params; if (bus_space_map(faa->fa_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 0, &sc->sc_dwc2.sc_ioh)) panic("%s: bus_space_map failed!", __func__); sc->sc_ih = arm_intr_establish_fdt_idx(faa->fa_node, 1, IPL_USB, dwc2_intr, (void *)&sc->sc_dwc2, sc->sc_dwc2.sc_bus.bdev.dv_xname); if (sc->sc_ih == NULL) panic("%s: intr_establish failed!", __func__); kthread_create_deferred(bcm_dwctwo_deferred, sc); } void bcm_dwctwo_deferred(void *self) { struct bcm_dwctwo_softc *sc = (struct bcm_dwctwo_softc *)self; int rc; strlcpy(sc->sc_dwc2.sc_vendor, "Broadcom", sizeof(sc->sc_dwc2.sc_vendor)); rc = dwc2_init(&sc->sc_dwc2); if (rc != 0) return; sc->sc_dwc2.sc_child = config_found(&sc->sc_dwc2.sc_bus.bdev, &sc->sc_dwc2.sc_bus, usbctlprint); }