diff options
Diffstat (limited to 'sys/arch/arm64/dev/bcm2835_dwctwo.c')
-rw-r--r-- | sys/arch/arm64/dev/bcm2835_dwctwo.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/sys/arch/arm64/dev/bcm2835_dwctwo.c b/sys/arch/arm64/dev/bcm2835_dwctwo.c new file mode 100644 index 00000000000..7305ac2745a --- /dev/null +++ b/sys/arch/arm64/dev/bcm2835_dwctwo.c @@ -0,0 +1,133 @@ +/* $OpenBSD: bcm2835_dwctwo.c,v 1.1 2017/01/23 08:05:47 kettenis Exp $ */ +/* + * Copyright (c) 2015 Masao Uebayashi <uebayasi@tombiinc.com> + * + * 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/pool.h> +#include <sys/kthread.h> + +#include <machine/intr.h> +#include <machine/bus.h> +#include <machine/fdt.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/fdt.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdivar.h> +#include <dev/usb/usb_mem.h> +#include <dev/usb/usb_quirks.h> + +#include <dev/usb/dwc2/dwc2var.h> +#include <dev/usb/dwc2/dwc2.h> +#include <dev/usb/dwc2/dwc2_core.h> + +struct bcm_dwctwo_softc { + struct dwc2_softc sc_dwc2; + 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; + + printf("\n"); + + 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 = faa->fa_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; + + 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); +} |