#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_caps.hnp_support = 0,
.otg_caps.srp_support = 0,
.host_dma = 1,
.dma_desc_enable = 0,
.speed = 0,
.enable_dynamic_fifo = 1,
.en_multiple_tx_fifo = 1,
.host_rx_fifo_size = 774,
.host_nperio_tx_fifo_size = 256,
.host_perio_tx_fifo_size = 512,
.max_transfer_size = 65535,
.max_packet_count = 511,
.host_channels = 8,
.phy_type = 1,
.phy_utmi_width = 8,
.phy_ulpi_ddr = 0,
.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,
.ts_dline = 0,
.reload_ctl = 0,
.ahbcfg = 0x10,
.uframe_sched = 1,
.external_id_pin_ctl = 0,
};
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;
int idx;
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__);
idx = OF_getindex(faa->fa_node, "usb", "interrupt-names");
if (idx == -1)
idx = 1;
sc->sc_ih = fdt_intr_establish_idx(faa->fa_node, idx,
IPL_VM | IPL_MPSAFE, 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);
}