diff options
author | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2016-03-18 05:38:11 +0000 |
---|---|---|
committer | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2016-03-18 05:38:11 +0000 |
commit | 4fe9bb8c281e32f8554addaa7d4098a336134125 (patch) | |
tree | 1defe2d317755004c8fb8341dcb9eb0852ba5827 | |
parent | bd7f7bd5eb8a950a652060c499cad643741dcac7 (diff) |
add octuctl, a driver for the Octeon II usb controller interface, and
attachments for ehci and ohci.
ok uebayasi@ jasper@ visa@ mpi@
-rw-r--r-- | sys/arch/octeon/conf/GENERIC | 7 | ||||
-rw-r--r-- | sys/arch/octeon/conf/RAMDISK | 9 | ||||
-rw-r--r-- | sys/arch/octeon/conf/files.octeon | 10 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octehci.c | 118 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octeon_iobus.c | 4 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octohci.c | 142 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octuctl.c | 250 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octuctlreg.h | 77 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octuctlvar.h | 32 |
9 files changed, 645 insertions, 4 deletions
diff --git a/sys/arch/octeon/conf/GENERIC b/sys/arch/octeon/conf/GENERIC index 60fa5eac3af..9f6ebf64ba6 100644 --- a/sys/arch/octeon/conf/GENERIC +++ b/sys/arch/octeon/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.24 2016/01/14 17:20:34 visa Exp $ +# $OpenBSD: GENERIC,v 1.25 2016/03/18 05:38:10 jmatthew Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -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 diff --git a/sys/arch/octeon/conf/RAMDISK b/sys/arch/octeon/conf/RAMDISK index cf0a04bf819..a2182722914 100644 --- a/sys/arch/octeon/conf/RAMDISK +++ b/sys/arch/octeon/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.23 2016/01/14 17:20:34 visa Exp $ +# $OpenBSD: RAMDISK,v 1.24 2016/03/18 05:38:10 jmatthew Exp $ machine octeon mips64 maxusers 4 @@ -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? diff --git a/sys/arch/octeon/conf/files.octeon b/sys/arch/octeon/conf/files.octeon index 4db0107193d..08a67b2fc00 100644 --- a/sys/arch/octeon/conf/files.octeon +++ b/sys/arch/octeon/conf/files.octeon @@ -1,4 +1,4 @@ -# $OpenBSD: files.octeon,v 1.28 2016/01/14 17:20:34 visa Exp $ +# $OpenBSD: files.octeon,v 1.29 2016/03/18 05:38:10 jmatthew Exp $ # Standard stanzas config(8) can't run without maxpartitions 16 @@ -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 diff --git a/sys/arch/octeon/dev/octehci.c b/sys/arch/octeon/dev/octehci.c new file mode 100644 index 00000000000..c6cacac6946 --- /dev/null +++ b/sys/arch/octeon/dev/octehci.c @@ -0,0 +1,118 @@ +/* $OpenBSD: octehci.c,v 1.1 2016/03/18 05:38:10 jmatthew Exp $ */ + +/* + * Copyright (c) 2015 Jonathan Matthew <jmatthew@openbsd.org> + * + * 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; + } + + printf("\n"); + if (rc == 0) + config_found(self, &sc->sc_ehci.sc_bus, usbctlprint); + splx(s); +} diff --git a/sys/arch/octeon/dev/octeon_iobus.c b/sys/arch/octeon/dev/octeon_iobus.c index 6dde070207b..7c3193fbb8d 100644 --- a/sys/arch/octeon/dev/octeon_iobus.c +++ b/sys/arch/octeon/dev/octeon_iobus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: octeon_iobus.c,v 1.14 2015/07/20 19:44:32 pirofti Exp $ */ +/* $OpenBSD: octeon_iobus.c,v 1.15 2016/03/18 05:38:10 jmatthew Exp $ */ /* * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se) @@ -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 iobus_addrs[] = { { "octrng", OCTEON_RNG_BASE }, { "dwctwo", USBN_BASE }, { "amdcf", OCTEON_AMDCF_BASE}, + { "octuctl", UCTL_BASE }, }; /* There can only be one. */ diff --git a/sys/arch/octeon/dev/octohci.c b/sys/arch/octeon/dev/octohci.c new file mode 100644 index 00000000000..e23489b7153 --- /dev/null +++ b/sys/arch/octeon/dev/octohci.c @@ -0,0 +1,142 @@ +/* $OpenBSD: octohci.c,v 1.1 2016/03/18 05:38:10 jmatthew Exp $ */ + +/* + * Copyright (c) 2015 Jonathan Matthew <jmatthew@openbsd.org> + * + * 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); + } +} diff --git a/sys/arch/octeon/dev/octuctl.c b/sys/arch/octeon/dev/octuctl.c new file mode 100644 index 00000000000..d2791409bf1 --- /dev/null +++ b/sys/arch/octeon/dev/octuctl.c @@ -0,0 +1,250 @@ +/* $OpenBSD: octuctl.c,v 1.1 2016/03/18 05:38:10 jmatthew Exp $ */ + +/* + * Copyright (c) 2015 Jonathan Matthew <jmatthew@openbsd.org> + * + * 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 <machine/octeon_model.h> + +#include <octeon/dev/iobusvar.h> +#include <octeon/dev/octuctlreg.h> +#include <octeon/dev/octuctlvar.h> + +struct octuctl_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +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 div; + int lastdiv; + int validdiv[] = { 1, 2, 3, 4, 6, 8, 12, INT_MAX }; + int i; + + div = octeon_ioclock_speed() / UCTL_CLK_TARGET_FREQ; + + /* 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(1); + + /* 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(1); + + /* 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); +} diff --git a/sys/arch/octeon/dev/octuctlreg.h b/sys/arch/octeon/dev/octuctlreg.h new file mode 100644 index 00000000000..5ead56add38 --- /dev/null +++ b/sys/arch/octeon/dev/octuctlreg.h @@ -0,0 +1,77 @@ +/* $OpenBSD: octuctlreg.h,v 1.1 2016/03/18 05:38:10 jmatthew Exp $ */ + +/* + * Copyright (c) 2015 Jonathan Matthew <jmatthew@openbsd.org> + * + * 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. + */ + +#ifndef _OCTUCTLREG_H_ +#define _OCTUCTLREG_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_TARGET_FREQ 130000000ull + +#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_ */ diff --git a/sys/arch/octeon/dev/octuctlvar.h b/sys/arch/octeon/dev/octuctlvar.h new file mode 100644 index 00000000000..56a8d189a26 --- /dev/null +++ b/sys/arch/octeon/dev/octuctlvar.h @@ -0,0 +1,32 @@ +/* $OpenBSD: octuctlvar.h,v 1.1 2016/03/18 05:38:10 jmatthew Exp $ */ + +/* + * Copyright (c) 2015 Jonathan Matthew <jmatthew@openbsd.org> + * + * 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. + */ + +#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_ */ |