On Thu, Mar 17, 2016 at 11:51:19AM +1000, Jonathan Matthew wrote:
> I've had this sitting around for a while and I figure it's time to get it in
> the tree. Octeon II sensibly got rid of the DWC USB controller and put in
> ehci
> and ohci compliant controllers instead, so all we need to do here is set up a
> few registers in the usb controller interface and attach the standard drivers.
> The diff below adds octuctl, a driver for the usb controller interface, and
> octehci and octohci, which are attachments for ehci and ohci.
>
> I've tested this on a Lanner MR326b, where it allows me to boot off a usb
> stick, and on an Edgerouter Lite, where it makes no difference at all.
>
> ok?
The patch seems to work fine on an EdgeRouter Pro.
OK visa@
> Index: conf/GENERIC
> ===================================================================
> RCS file: /cvs/src/sys/arch/octeon/conf/GENERIC,v
> retrieving revision 1.24
> diff -u -p -u -p -r1.24 GENERIC
> --- conf/GENERIC 14 Jan 2016 17:20:34 -0000 1.24
> +++ conf/GENERIC 17 Mar 2016 01:43:51 -0000
> @@ -64,9 +64,14 @@ wd* at pciide? flags 0x0000
>
> # USB Controllers
> dwctwo0 at iobus? irq 56
> +octuctl0 at iobus? irq 56
> +ehci0 at octuctl?
> +ohci0 at octuctl?
>
> # USB bus support
> usb* at dwctwo?
> +usb* at ehci?
> +usb* at ohci?
>
> # USB devices
> uhub* at usb? # USB Hubs
> Index: conf/RAMDISK
> ===================================================================
> RCS file: /cvs/src/sys/arch/octeon/conf/RAMDISK,v
> retrieving revision 1.23
> diff -u -p -u -p -r1.23 RAMDISK
> --- conf/RAMDISK 14 Jan 2016 17:20:34 -0000 1.23
> +++ conf/RAMDISK 17 Mar 2016 01:43:51 -0000
> @@ -55,7 +55,14 @@ pciide* at pci? flags 0x0000
> wd* at pciide? flags 0x0000
>
> dwctwo0 at iobus0 irq 56
> +octuctl0 at iobus0 irq 56
> +ehci0 at octuctl?
> +ohci0 at octuctl?
> +
> usb* at dwctwo?
> +usb* at ehci?
> +usb* at ohci?
> +
> uhub* at usb?
> uhub* at uhub?
> umass* at uhub?
> Index: conf/files.octeon
> ===================================================================
> RCS file: /cvs/src/sys/arch/octeon/conf/files.octeon,v
> retrieving revision 1.28
> diff -u -p -u -p -r1.28 files.octeon
> --- conf/files.octeon 14 Jan 2016 17:20:34 -0000 1.28
> +++ conf/files.octeon 17 Mar 2016 01:43:51 -0000
> @@ -71,6 +71,14 @@ file arch/octeon/dev/cn30xxsmi.c
> iobus
> attach dwctwo at iobus with octdwctwo
> file arch/octeon/dev/octdwctwo.c octdwctwo
> needs-flag
>
> +device octuctl {}
> +attach octuctl at iobus
> +file arch/octeon/dev/octuctl.c octuctl
> needs-flag
> +attach ehci at octuctl with octehci
> +file arch/octeon/dev/octehci.c octehci
> +attach ohci at octuctl with octohci
> +file arch/octeon/dev/octohci.c octohci
> +
> # On-board CF
> device octcf: disk
> attach octcf at iobus
> Index: dev/octehci.c
> ===================================================================
> RCS file: dev/octehci.c
> diff -N dev/octehci.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/octehci.c 17 Mar 2016 01:43:52 -0000
> @@ -0,0 +1,118 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2015 Jonathan Matthew <[email protected]>
> + *
> + * 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 <machine/intr.h>
> +#include <machine/bus.h>
> +#include <machine/octeonreg.h>
> +#include <machine/octeonvar.h>
> +
> +#include <octeon/dev/octuctlreg.h>
> +#include <octeon/dev/octuctlvar.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdivar.h>
> +
> +#include <sys/rwlock.h>
> +#include <dev/usb/ehcireg.h>
> +#include <dev/usb/ehcivar.h>
> +
> +struct octehci_softc {
> + struct ehci_softc sc_ehci;
> +
> + void *sc_ih;
> +};
> +
> +int octehci_match(struct device *, void *, void *);
> +void octehci_attach(struct device *, struct device *, void *);
> +
> +const struct cfattach octehci_ca = {
> + sizeof(struct octehci_softc), octehci_match, octehci_attach,
> +};
> +
> +struct cfdriver octehci_cd = {
> + NULL, "ehci", DV_DULL
> +};
> +
> +int
> +octehci_match(struct device *parent, void *match, void *aux)
> +{
> + struct octuctl_attach_args *aa = aux;
> +
> + if (strcmp(aa->aa_name, "ehci") != 0)
> + return (0);
> +
> + return (1);
> +}
> +
> +void
> +octehci_attach(struct device *parent, struct device *self, void *aux)
> +{
> + struct octehci_softc *sc = (struct octehci_softc *)self;
> + struct octuctl_attach_args *aa = aux;
> + uint64_t port_ctl;
> + int rc;
> + int s;
> +
> + sc->sc_ehci.iot = aa->aa_bust;
> + sc->sc_ehci.sc_bus.pipe_size = sizeof(struct usbd_pipe);
> + sc->sc_ehci.sc_bus.dmatag = aa->aa_dmat;
> +
> + rc = bus_space_map(sc->sc_ehci.iot, UCTL_EHCI_BASE, UCTL_EHCI_SIZE,
> + 0, &sc->sc_ehci.ioh);
> + KASSERT(rc == 0);
> +
> + port_ctl = bus_space_read_8(aa->aa_octuctl_bust, aa->aa_ioh,
> + UCTL_EHCI_CTL);
> + port_ctl &= ~UCTL_EHCI_CTL_L2C_ADDR_MSB_MASK;
> + port_ctl |= (1 << UCTL_EHCI_CTL_L2C_DESC_EMOD_SHIFT);
> + port_ctl |= (1 << UCTL_EHCI_CTL_L2C_BUFF_EMOD_SHIFT);
> + port_ctl |= UCTL_EHCI_CTL_EHCI_64B_ADDR_EN;
> + bus_space_write_8(aa->aa_octuctl_bust, aa->aa_ioh, UCTL_EHCI_CTL,
> + port_ctl);
> +
> + s = splhardusb();
> + sc->sc_ehci.sc_offs = EREAD1(&sc->sc_ehci, EHCI_CAPLENGTH);
> + EOWRITE2(&sc->sc_ehci, EHCI_USBINTR, 0);
> +
> + sc->sc_ehci.sc_id_vendor = 0;
> + strlcpy(sc->sc_ehci.sc_vendor, "Octeon", sizeof(sc->sc_ehci.sc_vendor));
> +
> + sc->sc_ih = octeon_intr_establish(CIU_INT_USB, IPL_USB, ehci_intr,
> + (void *)&sc->sc_ehci, sc->sc_ehci.sc_bus.bdev.dv_xname);
> + KASSERT(sc->sc_ih != NULL);
> +
> + rc = ehci_init(&sc->sc_ehci);
> + if (rc != USBD_NORMAL_COMPLETION) {
> + printf(": init failed, error=%d\n", rc);
> + octeon_intr_disestablish(sc->sc_ih);
> + bus_space_unmap(sc->sc_ehci.iot, sc->sc_ehci.ioh,
> + UCTL_EHCI_SIZE);
> + splx(s);
> + return;
> + }
> +
> + splx(s);
> + printf("\n");
> + if (rc == 0)
> + config_found(self, &sc->sc_ehci.sc_bus, usbctlprint);
> +}
> Index: dev/octeon_iobus.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/octeon/dev/octeon_iobus.c,v
> retrieving revision 1.14
> diff -u -p -u -p -r1.14 octeon_iobus.c
> --- dev/octeon_iobus.c 20 Jul 2015 19:44:32 -0000 1.14
> +++ dev/octeon_iobus.c 17 Mar 2016 01:43:52 -0000
> @@ -48,6 +48,7 @@
> #include <octeon/dev/iobusvar.h>
> #include <octeon/dev/cn30xxgmxreg.h>
> #include <octeon/dev/octhcireg.h> /* USBN_BASE */
> +#include <octeon/dev/octuctlreg.h>
>
> int iobusmatch(struct device *, void *, void *);
> void iobusattach(struct device *, struct device *, void *);
> @@ -150,6 +151,7 @@ static const struct octeon_iobus_addrs i
> { "octrng", OCTEON_RNG_BASE },
> { "dwctwo", USBN_BASE },
> { "amdcf", OCTEON_AMDCF_BASE},
> + { "octuctl", UCTL_BASE },
> };
>
> /* There can only be one. */
> Index: dev/octohci.c
> ===================================================================
> RCS file: dev/octohci.c
> diff -N dev/octohci.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/octohci.c 17 Mar 2016 01:43:52 -0000
> @@ -0,0 +1,142 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2015 Jonathan Matthew <[email protected]>
> + *
> + * 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 <machine/intr.h>
> +#include <machine/bus.h>
> +#include <machine/octeonreg.h>
> +#include <machine/octeonvar.h>
> +
> +#include <octeon/dev/octuctlreg.h>
> +#include <octeon/dev/octuctlvar.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdivar.h>
> +
> +#include <dev/usb/ohcireg.h>
> +#include <dev/usb/ohcivar.h>
> +
> +struct octohci_softc {
> + struct ohci_softc sc_ohci;
> +
> + void *sc_ih;
> +};
> +
> +int octohci_match(struct device *, void *, void *);
> +void octohci_attach(struct device *, struct device *, void *);
> +void octohci_attach_deferred(struct device *);
> +
> +const struct cfattach octohci_ca = {
> + sizeof(struct octohci_softc), octohci_match, octohci_attach,
> +};
> +
> +struct cfdriver octohci_cd = {
> + NULL, "ohci", DV_DULL
> +};
> +
> +int
> +octohci_match(struct device *parent, void *match, void *aux)
> +{
> + struct octuctl_attach_args *aa = aux;
> +
> + if (strcmp(aa->aa_name, "ohci") != 0)
> + return (0);
> +
> + return (1);
> +}
> +
> +void
> +octohci_attach(struct device *parent, struct device *self, void *aux)
> +{
> + struct octohci_softc *sc = (struct octohci_softc *)self;
> + struct octuctl_attach_args *aa = aux;
> + char *devname;
> + uint64_t port_ctl;
> + int rc;
> + int s;
> +
> + sc->sc_ohci.iot = aa->aa_bust;
> + sc->sc_ohci.sc_bus.pipe_size = sizeof(struct usbd_pipe);
> + sc->sc_ohci.sc_bus.dmatag = aa->aa_dmat;
> +
> + rc = bus_space_map(sc->sc_ohci.iot, UCTL_OHCI_BASE, UCTL_OHCI_SIZE,
> + 0, &sc->sc_ohci.ioh);
> + KASSERT(rc == 0);
> +
> + port_ctl = bus_space_read_8(aa->aa_octuctl_bust, aa->aa_ioh,
> + UCTL_OHCI_CTL);
> + port_ctl &= ~UCTL_OHCI_CTL_L2C_ADDR_MSB_MASK;
> + port_ctl |= (1 << UCTL_OHCI_CTL_L2C_DESC_EMOD_SHIFT);
> + port_ctl |= (1 << UCTL_OHCI_CTL_L2C_BUFF_EMOD_SHIFT);
> + bus_space_write_8(aa->aa_octuctl_bust, aa->aa_ioh, UCTL_OHCI_CTL,
> + port_ctl);
> +
> + s = splusb();
> +
> + sc->sc_ohci.sc_id_vendor = 0;
> + strlcpy(sc->sc_ohci.sc_vendor, "Octeon", sizeof(sc->sc_ohci.sc_vendor));
> +
> + sc->sc_ih = octeon_intr_establish(CIU_INT_USB, IPL_USB, ohci_intr,
> + (void *)&sc->sc_ohci, devname);
> + KASSERT(sc->sc_ih != NULL);
> +
> + if ((ohci_checkrev(&sc->sc_ohci) != USBD_NORMAL_COMPLETION) ||
> + (ohci_handover(&sc->sc_ohci) != USBD_NORMAL_COMPLETION))
> + goto failed;
> +
> + /* ignore interrupts for now */
> + sc->sc_ohci.sc_bus.dying = 1;
> + config_defer(self, octohci_attach_deferred);
> +
> + splx(s);
> + return;
> +
> +failed:
> + octeon_intr_disestablish(sc->sc_ih);
> + bus_space_unmap(sc->sc_ohci.iot, sc->sc_ohci.ioh, UCTL_OHCI_SIZE);
> + splx(s);
> + return;
> +}
> +
> +void
> +octohci_attach_deferred(struct device *self)
> +{
> + struct octohci_softc *sc = (struct octohci_softc *)self;
> + usbd_status r;
> + int s;
> +
> + s = splusb();
> + sc->sc_ohci.sc_bus.dying = 0;
> +
> + r = ohci_init(&sc->sc_ohci);
> + splx(s);
> +
> + if (r != USBD_NORMAL_COMPLETION) {
> + printf("%s: init failed, error=%d\n",
> + sc->sc_ohci.sc_bus.bdev.dv_xname, r);
> + octeon_intr_disestablish(sc->sc_ih);
> + bus_space_unmap(sc->sc_ohci.iot, sc->sc_ohci.ioh,
> + UCTL_OHCI_SIZE);
> + } else {
> + config_found(self, &sc->sc_ohci.sc_bus, usbctlprint);
> + }
> +}
> Index: dev/octuctl.c
> ===================================================================
> RCS file: dev/octuctl.c
> diff -N dev/octuctl.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/octuctl.c 17 Mar 2016 01:43:52 -0000
> @@ -0,0 +1,266 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2015 Jonathan Matthew <[email protected]>
> + *
> + * 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/rwlock.h>
> +
> +#include <machine/intr.h>
> +#include <machine/bus.h>
> +#include <machine/octeonreg.h>
> +#include <machine/octeonvar.h>
> +#include <machine/octeon_model.h>
> +
> +#include <octeon/dev/iobusvar.h>
> +#include <octeon/dev/octuctlreg.h>
> +#include <octeon/dev/octuctlvar.h>
> +
> +#include <dev/usb/usb.h>
> +#include <dev/usb/usbdi.h>
> +#include <dev/usb/usbdivar.h>
> +
> +#include <dev/usb/ehcireg.h>
> +#include <dev/usb/ehcivar.h>
> +#include <dev/usb/ohcireg.h>
> +#include <dev/usb/ohcivar.h>
> +
> +struct octuctl_softc {
> + bus_space_tag_t sc_iot;
> + bus_space_handle_t sc_ioh;
> +
> + void * sc_ehci_ih;
> + void * sc_ohci_ih;
> + struct ehci_softc sc_ehci;
> + struct ohci_softc sc_ohci;
> +};
> +
> +int octuctl_match(struct device *, void *, void *);
> +void octuctl_attach(struct device *, struct device *, void *);
> +
> +const struct cfattach octuctl_ca = {
> + sizeof(struct octuctl_softc), octuctl_match, octuctl_attach,
> +};
> +
> +struct cfdriver octuctl_cd = {
> + NULL, "octuctl", DV_DULL
> +};
> +
> +uint8_t octuctl_read_1(bus_space_tag_t, bus_space_handle_t, bus_size_t);
> +uint16_t octuctl_read_2(bus_space_tag_t, bus_space_handle_t, bus_size_t);
> +uint32_t octuctl_read_4(bus_space_tag_t, bus_space_handle_t, bus_size_t);
> +void octuctl_write_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
> uint8_t);
> +void octuctl_write_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
> uint16_t);
> +void octuctl_write_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
> uint32_t);
> +
> +bus_space_t octuctl_tag = {
> + .bus_base = PHYS_TO_XKPHYS(0, CCA_NC),
> + .bus_private = NULL,
> + ._space_read_1 = octuctl_read_1,
> + ._space_write_1 = octuctl_write_1,
> + ._space_read_2 = octuctl_read_2,
> + ._space_write_2 = octuctl_write_2,
> + ._space_read_4 = octuctl_read_4,
> + ._space_write_4 = octuctl_write_4,
> + ._space_map = iobus_space_map,
> + ._space_unmap = iobus_space_unmap,
> + ._space_subregion = generic_space_region,
> + ._space_vaddr = generic_space_vaddr
> +};
> +
> +uint8_t
> +octuctl_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
> +{
> + return *(volatile uint8_t *)(h + (o^3));
> +}
> +
> +uint16_t
> +octuctl_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
> +{
> + return *(volatile uint16_t *)(h + (o^2));
> +}
> +
> +uint32_t
> +octuctl_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
> +{
> + return *(volatile uint32_t *)(h + o);
> +}
> +
> +void
> +octuctl_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
> uint8_t v)
> +{
> + *(volatile uint8_t *)(h + (o^3)) = v;
> +}
> +
> +void
> +octuctl_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
> uint16_t v)
> +{
> + *(volatile uint16_t *)(h + (o^2)) = v;
> +}
> +
> +void
> +octuctl_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
> uint32_t v)
> +{
> + *(volatile uint32_t *)(h + o) = v;
> +}
> +
> +int
> +octuctl_match(struct device *parent, void *match, void *aux)
> +{
> + int id;
> +
> + id = octeon_get_chipid();
> + switch (octeon_model_family(id)) {
> + case OCTEON_MODEL_FAMILY_CN61XX:
> + return (1);
> + default:
> + return (0);
> + }
> +}
> +
> +int
> +octuctlprint(void *aux, const char *parentname)
> +{
> + return (QUIET);
> +}
> +
> +void
> +octuctl_clock_setup(struct octuctl_softc *sc, uint64_t ctl)
> +{
> + int ioclockdelay;
> + int div;
> + int lastdiv;
> + int validdiv[] = { 1, 2, 3, 4, 6, 8, 12, INT_MAX };
> + int i;
> +
> + ioclockdelay = 64000000ull / octeon_ioclock_speed();
> + div = octeon_ioclock_speed() / 130000000ull;
> +
> + /* start usb controller reset */
> + ctl |= UCTL_CLK_RST_CTL_P_POR;
> + ctl &= ~(UCTL_CLK_RST_CTL_HRST |
> + UCTL_CLK_RST_CTL_P_PRST |
> + UCTL_CLK_RST_CTL_O_CLKDIV_EN |
> + UCTL_CLK_RST_CTL_H_CLKDIV_EN |
> + UCTL_CLK_RST_CTL_H_CLKDIV_RST |
> + UCTL_CLK_RST_CTL_O_CLKDIV_RST);
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + /* set up for 12mhz crystal */
> + ctl &= ~((3 << UCTL_CLK_RST_CTL_P_REFCLK_DIV_SHIFT) |
> + (3 << UCTL_CLK_RST_CTL_P_REFCLK_SEL_SHIFT));
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + /* set clock divider */
> + lastdiv = 1;
> + for (i = 0; i < nitems(validdiv); i++) {
> + if (div < validdiv[i]) {
> + div = lastdiv;
> + break;
> + }
> + lastdiv = validdiv[i];
> + }
> +
> + ctl &= ~(0xf << UCTL_CLK_RST_CTL_H_DIV_SHIFT);
> + ctl |= (div << UCTL_CLK_RST_CTL_H_DIV_SHIFT);
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + /* turn hclk on */
> + ctl = bus_space_read_8(sc->sc_iot, sc->sc_ioh,
> + UCTL_CLK_RST_CTL);
> + ctl |= UCTL_CLK_RST_CTL_H_CLKDIV_EN;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> + ctl |= UCTL_CLK_RST_CTL_H_CLKDIV_RST;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + delay(ioclockdelay);
> +
> + /* power-on-reset finished */
> + ctl &= ~UCTL_CLK_RST_CTL_P_POR;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + delay(1000);
> +
> + /* set up ohci clocks */
> + ctl |= UCTL_CLK_RST_CTL_O_CLKDIV_RST;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> + ctl |= UCTL_CLK_RST_CTL_O_CLKDIV_EN;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + delay(ioclockdelay);
> +
> + /* phy reset */
> + ctl |= UCTL_CLK_RST_CTL_P_PRST;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +
> + delay(1);
> +
> + /* clear host reset */
> + ctl |= UCTL_CLK_RST_CTL_HRST;
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL, ctl);
> +}
> +
> +void
> +octuctl_attach(struct device *parent, struct device *self, void *aux)
> +{
> + struct octuctl_softc *sc = (struct octuctl_softc *)self;
> + struct iobus_attach_args *aa = aux;
> + struct octuctl_attach_args uaa;
> + uint64_t port_ctl;
> + uint64_t ctl;
> + uint64_t preg;
> + uint64_t txvref;
> + int rc;
> + int port;
> +
> + sc->sc_iot = aa->aa_bust;
> + rc = bus_space_map(sc->sc_iot, UCTL_BASE, UCTL_SIZE,
> + 0, &sc->sc_ioh);
> + KASSERT(rc == 0);
> +
> + /* do clock setup if not already done */
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, UCTL_IF_ENA,
> + UCTL_IF_ENA_EN);
> + ctl = bus_space_read_8(sc->sc_iot, sc->sc_ioh, UCTL_CLK_RST_CTL);
> + if ((ctl & UCTL_CLK_RST_CTL_HRST) == 0)
> + octuctl_clock_setup(sc, ctl);
> +
> + /* port phy settings */
> + for (port = 0; port < 2; port++) {
> + preg = UCTL_UPHY_PORTX_STATUS + (port * 8);
> + port_ctl = bus_space_read_8(sc->sc_iot, sc->sc_ioh, preg);
> + txvref = 0xf;
> + port_ctl |= (UCTL_UPHY_PORTX_STATUS_TXPREEMPHTUNE |
> + UCTL_UPHY_PORTX_STATUS_TXRISETUNE |
> + (txvref << UCTL_UPHY_PORTX_STATUS_TXVREF_SHIFT));
> + bus_space_write_8(sc->sc_iot, sc->sc_ioh, preg, port_ctl);
> + }
> +
> + printf("\n");
> +
> + uaa.aa_octuctl_bust = aa->aa_bust;
> + uaa.aa_bust = &octuctl_tag;
> + uaa.aa_dmat = aa->aa_dmat;
> + uaa.aa_ioh = sc->sc_ioh;
> +
> + uaa.aa_name = "ehci";
> + config_found(self, &uaa, octuctlprint);
> +
> + uaa.aa_name = "ohci";
> + config_found(self, &uaa, octuctlprint);
> +}
> Index: dev/octuctlreg.h
> ===================================================================
> RCS file: dev/octuctlreg.h
> diff -N dev/octuctlreg.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/octuctlreg.h 17 Mar 2016 01:43:52 -0000
> @@ -0,0 +1,88 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2015 Jonathan Matthew <[email protected]>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
> + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + */
> +
> +
> +#ifndef _OCTUCTLREG_H_
> +#define _OCTUCTLREG_H_
> +
> +#include <sys/stdint.h>
> +
> +/*
> + * UCTL - octeon II usb controller interface
> + */
> +#define UCTL_BASE 0x000118006f000000ull
> +#define UCTL_SIZE 0x100
> +
> +#define UCTL_EHCI_BASE 0x00016f0000000000ull
> +#define UCTL_EHCI_SIZE 0x100
> +#define UCTL_OHCI_BASE 0x00016f0000000400ull
> +#define UCTL_OHCI_SIZE 0x100
> +
> +#define UCTL_CLK_RST_CTL 0x00
> +#define UCTL_CLK_RST_CTL_HRST (1 << 0)
> +#define UCTL_CLK_RST_CTL_P_PRST (1 << 1)
> +#define UCTL_CLK_RST_CTL_P_POR (1 << 2)
> +#define UCTL_CLK_RST_CTL_P_COM_ON (1 << 3)
> +#define UCTL_CLK_RST_CTL_P_REFCLK_DIV_SHIFT 5
> +#define UCTL_CLK_RST_CTL_P_REFCLK_SEL_SHIFT 7
> +#define UCTL_CLK_RST_CTL_H_DIV_SHIFT 9
> +#define UCTL_CLK_RST_CTL_O_CLKDIV_EN (1 << 13)
> +#define UCTL_CLK_RST_CTL_H_CLKDIV_EN (1 << 14)
> +#define UCTL_CLK_RST_CTL_H_CLKDIV_RST (1 << 15)
> +#define UCTL_CLK_RST_CTL_H_CLKDIV_BYP (1 << 16)
> +#define UCTL_CLK_RST_CTL_O_CLKDIV_RST (1 << 17)
> +#define UCTL_CLK_RST_CTL_APP_START_CLK (1 << 18)
> +#define UCTL_CLK_RST_CTL_OHCI_SUSP_LGCY (1 << 19)
> +#define UCTL_CLK_RST_CTL_OHCI_SM (1 << 20)
> +#define UCTL_CLK_RST_CTL_OHCI_CLKCKTRST (1 << 21)
> +#define UCTL_CLK_RST_CTL_EHCI_SM (1 << 22)
> +
> +#define UCTL_UPHY_STATUS 0x08
> +
> +#define UCTL_UPHY_PORTX_STATUS 0x10
> +#define UCTL_UPHY_PORTX_STATUS_TXVREF_SHIFT 28
> +#define UCTL_UPHY_PORTX_STATUS_TXRISETUNE (1 << 27)
> +#define UCTL_UPHY_PORTX_STATUS_TXPREEMPHTUNE (1 << 26)
> +
> +#define UCTL_IF_ENA 0x30
> +#define UCTL_IF_ENA_EN (1 << 0)
> +
> +#define UCTL_EHCI_CTL 0x80
> +#define UCTL_EHCI_CTL_L2C_ADDR_MSB_MASK 0xff
> +#define UCTL_EHCI_CTL_L2C_ADDR_MSB_SHIFT 0
> +#define UCTL_EHCI_CTL_EHCI_64B_ADDR_EN (1 << 8)
> +#define UCTL_EHCI_CTL_L2C_DESC_EMOD_SHIFT 10
> +#define UCTL_EHCI_CTL_L2C_BUFF_EMOD_SHIFT 12
> +
> +#define UCTL_OHCI_CTL 0x88
> +#define UCTL_OHCI_CTL_L2C_ADDR_MSB_MASK 0xff
> +#define UCTL_OHCI_CTL_L2C_ADDR_MSB_SHIFT 0
> +#define UCTL_OHCI_CTL_L2C_DESC_EMOD_SHIFT 10
> +#define UCTL_OHCI_CTL_L2C_BUFF_EMOD_SHIFT 12
> +
> +#endif /* _OCTUCTLREG_H_ */
> Index: dev/octuctlvar.h
> ===================================================================
> RCS file: dev/octuctlvar.h
> diff -N dev/octuctlvar.h
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ dev/octuctlvar.h 17 Mar 2016 01:43:52 -0000
> @@ -0,0 +1,42 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2015 Jonathan Matthew <[email protected]>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
> + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + */
> +
> +#ifndef _OCTUCTLVAR_H_
> +#define _OCTUCTLVAR_H_
> +
> +#include <machine/bus.h>
> +
> +struct octuctl_attach_args {
> + char *aa_name;
> + bus_space_tag_t aa_octuctl_bust;
> + bus_space_tag_t aa_bust;
> + bus_dma_tag_t aa_dmat;
> + bus_space_handle_t aa_ioh;
> +};
> +
> +#endif /* _OCTUCTLVAR_H_ */
>