diff --git a/stand/usb/usbcore.mk b/stand/usb/usbcore.mk index 7e0cc989228b..ae80d06a24e7 100644 --- a/stand/usb/usbcore.mk +++ b/stand/usb/usbcore.mk @@ -1,177 +1,169 @@ # # $FreeBSD$ # # Copyright (c) 2013-2020 Hans Petter Selasky. # Copyright (c) 2014 SRI International # All rights reserved. # # This software was developed by SRI International and the University of # Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 # ("CTSRD"), as part of the DARPA CRASH research programme. # # 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. # USBCOREDIR:= ${.PARSEDIR} S=${USBCOREDIR}/../../sys MACHDEP_DIRS= .if defined(HAVE_EXYNOS_EHCI) MACHDEP_DIRS+= ${S}/arm/samsung/exynos .endif .PATH: \ ${USBCOREDIR} \ ${USBCOREDIR}/storage \ ${S}/dev/usb \ ${S}/dev/usb/controller \ ${S}/dev/usb/serial \ ${S}/dev/usb/storage \ ${S}/dev/usb/template \ ${MACHDEP_DIRS} .undef S USB_POOL_SIZE?= 131072 CFLAGS+= -DUSB_MSCTEST_BULK_SIZE=65536 CFLAGS+= -DUSB_POOL_SIZE=${USB_POOL_SIZE} # # BUSDMA implementation # SRCS+= usb_busdma_loader.c # # USB controller drivers # KSRCS+= usb_controller.c .if defined(HAVE_AT91DCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"at91dci\"" KSRCS+= at91dci.c .endif .if defined(HAVE_ATMEGADCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"atmegadci\"" KSRCS+= atmegadci.c .endif .if defined(HAVE_AVR32DCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"avr32dci\"" KSRCS+= avr32dci.c .endif .if defined(HAVE_DWCOTG) CFLAGS += -DUSB_PCI_PROBE_LIST="\"dwcotg\"" KSRCS+= dwcotg.c .endif .if defined(HAVE_MUSBOTG) CFLAGS += -DUSB_PCI_PROBE_LIST="\"musbotg\"" KSRCS+= musbotg.c .endif .if defined(HAVE_EHCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"ehci\"" KSRCS+= ehci.c .endif .if defined(HAVE_EXYNOS_EHCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"combiner\", \"pad\", \"ehci\"" KSRCS+= ehci.c KSRCS+= exynos5_combiner.c KSRCS+= exynos5_pad.c KSRCS+= exynos5_ehci.c .endif .if defined(HAVE_OHCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"ohci\"" KSRCS+= ohci.c .endif .if defined(HAVE_UHCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"uhci\"" KSRCS+= uhci.c .endif .if defined(HAVE_XHCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"xhci\"" KSRCS+= xhci.c .endif .if defined(HAVE_USS820DCI) CFLAGS += -DUSB_PCI_PROBE_LIST="\"uss820dci\"" KSRCS+= uss820dci.c .endif -.if defined(HAVE_SAF1761OTG) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"saf1761otg\"" -CFLAGS += -DUSB_PCI_MEMORY_ADDRESS=0x900000007f100000ULL -CFLAGS += -DUSB_PCI_MEMORY_SIZE=0x40000U -KSRCS+= saf1761_otg.c -KSRCS+= saf1761_otg_boot.c -.endif - # # USB core and templates # KSRCS+= usb_core.c KSRCS+= usb_debug.c KSRCS+= usb_device.c KSRCS+= usb_dynamic.c KSRCS+= usb_error.c KSRCS+= usb_handle_request.c KSRCS+= usb_hid.c KSRCS+= usb_hub.c KSRCS+= usb_lookup.c KSRCS+= usb_msctest.c KSRCS+= usb_parse.c KSRCS+= usb_request.c KSRCS+= usb_transfer.c KSRCS+= usb_util.c KSRCS+= usb_template.c KSRCS+= usb_template_cdce.c KSRCS+= usb_template_msc.c KSRCS+= usb_template_mtp.c KSRCS+= usb_template_modem.c KSRCS+= usb_template_mouse.c KSRCS+= usb_template_kbd.c KSRCS+= usb_template_audio.c KSRCS+= usb_template_phone.c KSRCS+= usb_template_serialnet.c KSRCS+= usb_template_midi.c KSRCS+= usb_template_multi.c KSRCS+= usb_template_cdceem.c # # USB mass storage support # SRCS+= umass_common.c .if defined(HAVE_UMASS_LOADER) CFLAGS+= -I${.CURDIR}/../common SRCS+= umass_loader.c .endif diff --git a/sys/dev/usb/controller/saf1761_otg.c b/sys/dev/usb/controller/saf1761_otg.c deleted file mode 100644 index f5725a3cb48a..000000000000 --- a/sys/dev/usb/controller/saf1761_otg.c +++ /dev/null @@ -1,3657 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2014 Hans Petter Selasky - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -/* - * This file contains the driver for the SAF1761 series USB OTG - * controller. - * - * Datasheet is available from: - * http://www.nxp.com/products/automotive/multimedia/usb/SAF1761BE.html - */ - -#ifdef USB_GLOBAL_INCLUDE_FILE -#include USB_GLOBAL_INCLUDE_FILE -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define USB_DEBUG_VAR saf1761_otg_debug - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#endif /* USB_GLOBAL_INCLUDE_FILE */ - -#include -#include - -#define SAF1761_OTG_BUS2SC(bus) \ - ((struct saf1761_otg_softc *)(((uint8_t *)(bus)) - \ - ((uint8_t *)&(((struct saf1761_otg_softc *)0)->sc_bus)))) - -#define SAF1761_OTG_PC2UDEV(pc) \ - (USB_DMATAG_TO_XROOT((pc)->tag_parent)->udev) - -#define SAF1761_DCINTERRUPT_THREAD_IRQ \ - (SOTG_DCINTERRUPT_IEVBUS | SOTG_DCINTERRUPT_IEBRST | \ - SOTG_DCINTERRUPT_IERESM | SOTG_DCINTERRUPT_IESUSP) - -#ifdef USB_DEBUG -static int saf1761_otg_debug = 0; -static int saf1761_otg_forcefs = 0; - -static -SYSCTL_NODE(_hw_usb, OID_AUTO, saf1761_otg, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, - "USB SAF1761 DCI"); - -SYSCTL_INT(_hw_usb_saf1761_otg, OID_AUTO, debug, CTLFLAG_RWTUN, - &saf1761_otg_debug, 0, "SAF1761 DCI debug level"); -SYSCTL_INT(_hw_usb_saf1761_otg, OID_AUTO, forcefs, CTLFLAG_RWTUN, - &saf1761_otg_forcefs, 0, "SAF1761 DCI force FULL speed"); -#endif - -#define SAF1761_OTG_INTR_ENDPT 1 - -/* prototypes */ - -static const struct usb_bus_methods saf1761_otg_bus_methods; -static const struct usb_pipe_methods saf1761_otg_non_isoc_methods; -static const struct usb_pipe_methods saf1761_otg_device_isoc_methods; -static const struct usb_pipe_methods saf1761_otg_host_isoc_methods; - -static saf1761_otg_cmd_t saf1761_host_setup_tx; -static saf1761_otg_cmd_t saf1761_host_bulk_data_rx; -static saf1761_otg_cmd_t saf1761_host_bulk_data_tx; -static saf1761_otg_cmd_t saf1761_host_intr_data_rx; -static saf1761_otg_cmd_t saf1761_host_intr_data_tx; -static saf1761_otg_cmd_t saf1761_host_isoc_data_rx; -static saf1761_otg_cmd_t saf1761_host_isoc_data_tx; -static saf1761_otg_cmd_t saf1761_device_setup_rx; -static saf1761_otg_cmd_t saf1761_device_data_rx; -static saf1761_otg_cmd_t saf1761_device_data_tx; -static saf1761_otg_cmd_t saf1761_device_data_tx_sync; -static void saf1761_otg_device_done(struct usb_xfer *, usb_error_t); -static void saf1761_otg_do_poll(struct usb_bus *); -static void saf1761_otg_standard_done(struct usb_xfer *); -static void saf1761_otg_intr_set(struct usb_xfer *, uint8_t); -static void saf1761_otg_root_intr(struct saf1761_otg_softc *); -static void saf1761_otg_enable_psof(struct saf1761_otg_softc *, uint8_t); - -/* - * Here is a list of what the SAF1761 chip can support. The main - * limitation is that the sum of the buffer sizes must be less than - * 8192 bytes. - */ -static const struct usb_hw_ep_profile saf1761_otg_ep_profile[] = { - [0] = { - .max_in_frame_size = 64, - .max_out_frame_size = 64, - .is_simplex = 0, - .support_control = 1, - }, - [1] = { - .max_in_frame_size = SOTG_HS_MAX_PACKET_SIZE, - .max_out_frame_size = SOTG_HS_MAX_PACKET_SIZE, - .is_simplex = 0, - .support_interrupt = 1, - .support_bulk = 1, - .support_isochronous = 1, - .support_in = 1, - .support_out = 1, - }, -}; - -static void -saf1761_otg_get_hw_ep_profile(struct usb_device *udev, - const struct usb_hw_ep_profile **ppf, uint8_t ep_addr) -{ - if (ep_addr == 0) { - *ppf = saf1761_otg_ep_profile + 0; - } else if (ep_addr < 8) { - *ppf = saf1761_otg_ep_profile + 1; - } else { - *ppf = NULL; - } -} - -static void -saf1761_otg_pull_up(struct saf1761_otg_softc *sc) -{ - /* activate pullup on D+, if possible */ - - if (!sc->sc_flags.d_pulled_up && sc->sc_flags.port_powered) { - DPRINTF("\n"); - - sc->sc_flags.d_pulled_up = 1; - } -} - -static void -saf1761_otg_pull_down(struct saf1761_otg_softc *sc) -{ - /* release pullup on D+, if possible */ - - if (sc->sc_flags.d_pulled_up) { - DPRINTF("\n"); - - sc->sc_flags.d_pulled_up = 0; - } -} - -static void -saf1761_otg_wakeup_peer(struct saf1761_otg_softc *sc) -{ - uint16_t temp; - - if (!(sc->sc_flags.status_suspend)) - return; - - DPRINTFN(5, "\n"); - - temp = SAF1761_READ_LE_4(sc, SOTG_MODE); - SAF1761_WRITE_LE_4(sc, SOTG_MODE, temp | SOTG_MODE_SNDRSU); - SAF1761_WRITE_LE_4(sc, SOTG_MODE, temp & ~SOTG_MODE_SNDRSU); - - /* Wait 8ms for remote wakeup to complete. */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125); -} - -static uint8_t -saf1761_host_channel_alloc(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t map; - int x; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) - return (0); - - /* check if device is suspended */ - if (SAF1761_OTG_PC2UDEV(td->pc)->flags.self_suspended != 0) - return (1); /* busy - cannot transfer data */ - - switch (td->ep_type) { - case UE_INTERRUPT: - map = ~(sc->sc_host_intr_map | - sc->sc_host_intr_busy_map[0] | - sc->sc_host_intr_busy_map[1]); - /* find first set bit */ - x = ffs(map) - 1; - if (x < 0 || x > 31) - break; - sc->sc_host_intr_map |= (1U << x); - td->channel = 32 + x; - return (0); - case UE_ISOCHRONOUS: - map = ~(sc->sc_host_isoc_map | - sc->sc_host_isoc_busy_map[0] | - sc->sc_host_isoc_busy_map[1]); - /* find first set bit */ - x = ffs(map) - 1; - if (x < 0 || x > 31) - break; - sc->sc_host_isoc_map |= (1U << x); - td->channel = x; - return (0); - default: - map = ~(sc->sc_host_async_map | - sc->sc_host_async_busy_map[0] | - sc->sc_host_async_busy_map[1]); - /* find first set bit */ - x = ffs(map) - 1; - if (x < 0 || x > 31) - break; - sc->sc_host_async_map |= (1U << x); - td->channel = 64 + x; - return (0); - } - return (1); -} - -static void -saf1761_host_channel_free(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t x; - - if (td->channel >= SOTG_HOST_CHANNEL_MAX) - return; - - switch (td->ep_type) { - case UE_INTERRUPT: - x = td->channel - 32; - td->channel = SOTG_HOST_CHANNEL_MAX; - sc->sc_host_intr_map &= ~(1U << x); - sc->sc_host_intr_suspend_map &= ~(1U << x); - sc->sc_host_intr_busy_map[0] |= (1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, - (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); - break; - case UE_ISOCHRONOUS: - x = td->channel; - td->channel = SOTG_HOST_CHANNEL_MAX; - sc->sc_host_isoc_map &= ~(1U << x); - sc->sc_host_isoc_suspend_map &= ~(1U << x); - sc->sc_host_isoc_busy_map[0] |= (1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, - (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); - break; - default: - x = td->channel - 64; - td->channel = SOTG_HOST_CHANNEL_MAX; - sc->sc_host_async_map &= ~(1U << x); - sc->sc_host_async_suspend_map &= ~(1U << x); - sc->sc_host_async_busy_map[0] |= (1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, - (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); - break; - } - saf1761_otg_enable_psof(sc, 1); -} - -static uint32_t -saf1761_peek_host_status_le_4(struct saf1761_otg_softc *sc, uint32_t offset) -{ - uint32_t x = 0; - while (1) { - uint32_t retval; - - SAF1761_WRITE_LE_4(sc, SOTG_MEMORY_REG, offset); - SAF1761_90NS_DELAY(sc); /* read prefetch time is 90ns */ - retval = SAF1761_READ_LE_4(sc, offset); - if (retval != 0) - return (retval); - if (++x == 8) { - DPRINTF("STAUS is zero at offset 0x%x\n", offset); - break; - } - } - return (0); -} - -static void -saf1761_read_host_memory(struct saf1761_otg_softc *sc, - struct saf1761_otg_td *td, uint32_t len) -{ - struct usb_page_search buf_res; - uint32_t offset; - uint32_t count; - - if (len == 0) - return; - - offset = SOTG_DATA_ADDR(td->channel); - SAF1761_WRITE_LE_4(sc, SOTG_MEMORY_REG, offset); - SAF1761_90NS_DELAY(sc); /* read prefetch time is 90ns */ - - /* optimised read first */ - while (len > 0) { - usbd_get_page(td->pc, td->offset, &buf_res); - - /* get correct length */ - if (buf_res.length > len) - buf_res.length = len; - - /* check buffer alignment */ - if (((uintptr_t)buf_res.buffer) & 3) - break; - - count = buf_res.length & ~3; - if (count == 0) - break; - - bus_space_read_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - offset, buf_res.buffer, count / 4); - - len -= count; - offset += count; - - /* update remainder and offset */ - td->remainder -= count; - td->offset += count; - } - - if (len > 0) { - /* use bounce buffer */ - bus_space_read_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - offset, sc->sc_bounce_buffer, (len + 3) / 4); - usbd_copy_in(td->pc, td->offset, - sc->sc_bounce_buffer, len); - - /* update remainder and offset */ - td->remainder -= len; - td->offset += len; - } -} - -static void -saf1761_write_host_memory(struct saf1761_otg_softc *sc, - struct saf1761_otg_td *td, uint32_t len) -{ - struct usb_page_search buf_res; - uint32_t offset; - uint32_t count; - - if (len == 0) - return; - - offset = SOTG_DATA_ADDR(td->channel); - - /* optimised write first */ - while (len > 0) { - usbd_get_page(td->pc, td->offset, &buf_res); - - /* get correct length */ - if (buf_res.length > len) - buf_res.length = len; - - /* check buffer alignment */ - if (((uintptr_t)buf_res.buffer) & 3) - break; - - count = buf_res.length & ~3; - if (count == 0) - break; - - bus_space_write_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - offset, buf_res.buffer, count / 4); - - len -= count; - offset += count; - - /* update remainder and offset */ - td->remainder -= count; - td->offset += count; - } - if (len > 0) { - /* use bounce buffer */ - usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, len); - bus_space_write_region_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - offset, sc->sc_bounce_buffer, (len + 3) / 4); - - /* update remainder and offset */ - td->remainder -= len; - td->offset += len; - } -} - -static uint8_t -saf1761_host_setup_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t status; - uint32_t count; - uint32_t temp; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - goto busy; - } else if (status & SOTG_PTD_DW3_HALTED) { - td->error_any = 1; - } - goto complete; - } - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - count = 8; - - if (count != td->remainder) { - td->error_any = 1; - goto complete; - } - - saf1761_write_host_memory(sc, td, count); - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0); - - temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR_3; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (2 << 10) /* SETUP PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (td->max_packet_size << 18) /* wMaxPacketSize */ | - (count << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, - (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); - - td->toggle = 1; -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static uint8_t -saf1761_host_bulk_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t temp; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - uint32_t status; - uint32_t count; - uint8_t got_short; - - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - temp = saf1761_peek_host_status_le_4(sc, - pdt_addr + SOTG_PTD_DW0); - if (temp & SOTG_PTD_DW0_VALID) { - goto busy; - } else { - status = saf1761_peek_host_status_le_4(sc, - pdt_addr + SOTG_PTD_DW3); - - /* check if still active */ - if (status & SOTG_PTD_DW3_ACTIVE) { - saf1761_host_channel_free(sc, td); - goto retry; - } else if (status & SOTG_PTD_DW3_HALTED) { - if (!(status & SOTG_PTD_DW3_ERRORS)) - td->error_stall = 1; - td->error_any = 1; - goto complete; - } - } - } else if (status & SOTG_PTD_DW3_HALTED) { - if (!(status & SOTG_PTD_DW3_ERRORS)) - td->error_stall = 1; - td->error_any = 1; - goto complete; - } - if (td->dw1_value & SOTG_PTD_DW1_ENABLE_SPLIT) - count = (status & SOTG_PTD_DW3_XFER_COUNT_SPLIT); - else - count = (status & SOTG_PTD_DW3_XFER_COUNT_HS); - got_short = 0; - - /* verify the packet byte count */ - if (count != td->max_packet_size) { - if (count < td->max_packet_size) { - /* we have a short packet */ - td->short_pkt = 1; - got_short = 1; - } else { - /* invalid USB packet */ - td->error_any = 1; - goto complete; - } - } - td->toggle ^= 1; - - /* verify the packet byte count */ - if (count > td->remainder) { - /* invalid USB packet */ - td->error_any = 1; - goto complete; - } - - saf1761_read_host_memory(sc, td, count); - - /* check if we are complete */ - if ((td->remainder == 0) || got_short) { - if (td->short_pkt) - goto complete; - /* else need to receive a zero length packet */ - } - saf1761_host_channel_free(sc, td); - } -retry: - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - /* set toggle, if any */ - if (td->set_toggle) { - td->set_toggle = 0; - td->toggle = 1; - } - - /* receive one more packet */ - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0); - - temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | - SOTG_PTD_DW3_CERR_2; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (1 << 10) /* IN-PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (td->max_packet_size << 18) /* wMaxPacketSize */ | - (td->max_packet_size << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, - (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static uint8_t -saf1761_host_bulk_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t temp; - uint32_t count; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - uint32_t status; - - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - goto busy; - } else if (status & SOTG_PTD_DW3_HALTED) { - if (!(status & SOTG_PTD_DW3_ERRORS)) - td->error_stall = 1; - td->error_any = 1; - goto complete; - } - /* check remainder */ - if (td->remainder == 0) { - if (td->short_pkt) - goto complete; - /* else we need to transmit a short packet */ - } - saf1761_host_channel_free(sc, td); - } - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - count = td->max_packet_size; - if (td->remainder < count) { - /* we have a short packet */ - td->short_pkt = 1; - count = td->remainder; - } - - saf1761_write_host_memory(sc, td, count); - - /* set toggle, if any */ - if (td->set_toggle) { - td->set_toggle = 0; - td->toggle = 1; - } - - /* send one more packet */ - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, 0); - - temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | - SOTG_PTD_DW3_CERR_2; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (0 << 10) /* OUT-PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (td->max_packet_size << 18) /* wMaxPacketSize */ | - (count << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, - (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); - - td->toggle ^= 1; -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static uint8_t -saf1761_host_intr_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t temp; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - uint32_t status; - uint32_t count; - uint8_t got_short; - - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - goto busy; - } else if (status & SOTG_PTD_DW3_HALTED) { - if (!(status & SOTG_PTD_DW3_ERRORS)) - td->error_stall = 1; - td->error_any = 1; - goto complete; - } - if (td->dw1_value & SOTG_PTD_DW1_ENABLE_SPLIT) - count = (status & SOTG_PTD_DW3_XFER_COUNT_SPLIT); - else - count = (status & SOTG_PTD_DW3_XFER_COUNT_HS); - got_short = 0; - - /* verify the packet byte count */ - if (count != td->max_packet_size) { - if (count < td->max_packet_size) { - /* we have a short packet */ - td->short_pkt = 1; - got_short = 1; - } else { - /* invalid USB packet */ - td->error_any = 1; - goto complete; - } - } - td->toggle ^= 1; - - /* verify the packet byte count */ - if (count > td->remainder) { - /* invalid USB packet */ - td->error_any = 1; - goto complete; - } - - saf1761_read_host_memory(sc, td, count); - - /* check if we are complete */ - if ((td->remainder == 0) || got_short) { - if (td->short_pkt) - goto complete; - /* else need to receive a zero length packet */ - } - saf1761_host_channel_free(sc, td); - } - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - /* set toggle, if any */ - if (td->set_toggle) { - td->set_toggle = 0; - td->toggle = 1; - } - - /* receive one more packet */ - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - - if (td->dw1_value & SOTG_PTD_DW1_ENABLE_SPLIT) { - temp = (0xFC << td->uframe) & 0xFF; /* complete split */ - } else { - temp = 0; - } - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, temp); - - temp = (1U << td->uframe); /* start mask or start split */ - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp); - - temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR_3; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | - (td->interval & 0xF8); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (1 << 10) /* IN-PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (td->max_packet_size << 18) /* wMaxPacketSize */ | - (td->max_packet_size << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, - (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static uint8_t -saf1761_host_intr_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t temp; - uint32_t count; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - uint32_t status; - - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - goto busy; - } else if (status & SOTG_PTD_DW3_HALTED) { - if (!(status & SOTG_PTD_DW3_ERRORS)) - td->error_stall = 1; - td->error_any = 1; - goto complete; - } - - /* check remainder */ - if (td->remainder == 0) { - if (td->short_pkt) - goto complete; - /* else we need to transmit a short packet */ - } - saf1761_host_channel_free(sc, td); - } - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - count = td->max_packet_size; - if (td->remainder < count) { - /* we have a short packet */ - td->short_pkt = 1; - count = td->remainder; - } - - saf1761_write_host_memory(sc, td, count); - - /* set toggle, if any */ - if (td->set_toggle) { - td->set_toggle = 0; - td->toggle = 1; - } - - /* send one more packet */ - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - - if (td->dw1_value & SOTG_PTD_DW1_ENABLE_SPLIT) { - temp = (0xFC << td->uframe) & 0xFF; /* complete split */ - } else { - temp = 0; - } - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, temp); - - temp = (1U << td->uframe); /* start mask or start split */ - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp); - - temp = SOTG_PTD_DW3_ACTIVE | (td->toggle << 25) | SOTG_PTD_DW3_CERR_3; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | - (td->interval & 0xF8); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (0 << 10) /* OUT-PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (td->max_packet_size << 18) /* wMaxPacketSize */ | - (count << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, - (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); - - td->toggle ^= 1; -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static uint8_t -saf1761_host_isoc_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t temp; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - uint32_t status; - uint32_t count; - - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - goto busy; - } else if (status & SOTG_PTD_DW3_HALTED) { - goto complete; - } - if (td->dw1_value & SOTG_PTD_DW1_ENABLE_SPLIT) - count = (status & SOTG_PTD_DW3_XFER_COUNT_SPLIT); - else - count = (status & SOTG_PTD_DW3_XFER_COUNT_HS); - - /* verify the packet byte count */ - if (count != td->max_packet_size) { - if (count < td->max_packet_size) { - /* we have a short packet */ - td->short_pkt = 1; - } else { - /* invalid USB packet */ - td->error_any = 1; - goto complete; - } - } - - /* verify the packet byte count */ - if (count > td->remainder) { - /* invalid USB packet */ - td->error_any = 1; - goto complete; - } - - saf1761_read_host_memory(sc, td, count); - goto complete; - } - - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - /* receive one more packet */ - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - - if (td->dw1_value & SOTG_PTD_DW1_ENABLE_SPLIT) { - temp = (0xFC << (td->uframe & 7)) & 0xFF; /* complete split */ - } else { - temp = 0; - } - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, temp); - - temp = (1U << (td->uframe & 7)); /* start mask or start split */ - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp); - - temp = SOTG_PTD_DW3_ACTIVE | SOTG_PTD_DW3_CERR_3; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | - (td->uframe & 0xF8); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (1 << 10) /* IN-PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (td->max_packet_size << 18) /* wMaxPacketSize */ | - (td->max_packet_size << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, - (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static uint8_t -saf1761_host_isoc_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t pdt_addr; - uint32_t temp; - uint32_t count; - - if (td->channel < SOTG_HOST_CHANNEL_MAX) { - uint32_t status; - - pdt_addr = SOTG_PTD(td->channel); - - status = saf1761_peek_host_status_le_4(sc, pdt_addr + SOTG_PTD_DW3); - - DPRINTFN(5, "STATUS=0x%08x\n", status); - - if (status & SOTG_PTD_DW3_ACTIVE) { - goto busy; - } else if (status & SOTG_PTD_DW3_HALTED) { - goto complete; - } - goto complete; - } - if (saf1761_host_channel_alloc(sc, td)) - goto busy; - - count = td->max_packet_size; - if (td->remainder < count) { - /* we have a short packet */ - td->short_pkt = 1; - count = td->remainder; - } - - saf1761_write_host_memory(sc, td, count); - - /* send one more packet */ - - pdt_addr = SOTG_PTD(td->channel); - - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW7, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW6, 0); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW5, 0); - - temp = (1U << (td->uframe & 7)); /* start mask or start split */ - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW4, temp); - - temp = SOTG_PTD_DW3_ACTIVE | SOTG_PTD_DW3_CERR_3; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW3, temp); - - temp = (SOTG_HC_MEMORY_ADDR(SOTG_DATA_ADDR(td->channel)) << 8) | - (td->uframe & 0xF8); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW2, temp); - - temp = td->dw1_value | (0 << 10) /* OUT-PID */ | (td->ep_index >> 1); - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW1, temp); - - temp = (td->ep_index << 31) | (1 << 29) /* pkt-multiplier */ | - (count << 18) /* wMaxPacketSize */ | - (count << 3) /* transfer count */ | - SOTG_PTD_DW0_VALID; - SAF1761_WRITE_LE_4(sc, pdt_addr + SOTG_PTD_DW0, temp); - - /* activate PTD */ - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, - (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); -busy: - return (1); /* busy */ -complete: - saf1761_host_channel_free(sc, td); - return (0); /* complete */ -} - -static void -saf1761_otg_set_address(struct saf1761_otg_softc *sc, uint8_t addr) -{ - DPRINTFN(5, "addr=%d\n", addr); - - SAF1761_WRITE_LE_4(sc, SOTG_ADDRESS, addr | SOTG_ADDRESS_ENABLE); -} - -static void -saf1761_read_device_fifo(struct saf1761_otg_softc *sc, - struct saf1761_otg_td *td, uint32_t len) -{ - struct usb_page_search buf_res; - uint32_t count; - - /* optimised read first */ - while (len > 0) { - usbd_get_page(td->pc, td->offset, &buf_res); - - /* get correct length */ - if (buf_res.length > len) - buf_res.length = len; - - /* check buffer alignment */ - if (((uintptr_t)buf_res.buffer) & 3) - break; - - count = buf_res.length & ~3; - if (count == 0) - break; - - bus_space_read_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - SOTG_DATA_PORT, buf_res.buffer, count / 4); - - len -= count; - - /* update remainder and offset */ - td->remainder -= count; - td->offset += count; - } - - if (len > 0) { - /* use bounce buffer */ - bus_space_read_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - SOTG_DATA_PORT, sc->sc_bounce_buffer, (len + 3) / 4); - usbd_copy_in(td->pc, td->offset, - sc->sc_bounce_buffer, len); - - /* update remainder and offset */ - td->remainder -= len; - td->offset += len; - } -} - -static void -saf1761_write_device_fifo(struct saf1761_otg_softc *sc, - struct saf1761_otg_td *td, uint32_t len) -{ - struct usb_page_search buf_res; - uint32_t count; - - /* optimised write first */ - while (len > 0) { - usbd_get_page(td->pc, td->offset, &buf_res); - - /* get correct length */ - if (buf_res.length > len) - buf_res.length = len; - - /* check buffer alignment */ - if (((uintptr_t)buf_res.buffer) & 3) - break; - - count = buf_res.length & ~3; - if (count == 0) - break; - - bus_space_write_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - SOTG_DATA_PORT, buf_res.buffer, count / 4); - - len -= count; - - /* update remainder and offset */ - td->remainder -= count; - td->offset += count; - } - if (len > 0) { - /* use bounce buffer */ - usbd_copy_out(td->pc, td->offset, sc->sc_bounce_buffer, len); - bus_space_write_multi_4((sc)->sc_io_tag, (sc)->sc_io_hdl, - SOTG_DATA_PORT, sc->sc_bounce_buffer, (len + 3) / 4); - - /* update remainder and offset */ - td->remainder -= len; - td->offset += len; - } -} - -static uint8_t -saf1761_device_setup_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - struct usb_device_request req; - uint32_t count; - - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP); - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) == 0) - goto busy; - - /* get buffer length */ - count &= SOTG_BUF_LENGTH_BUFLEN_MASK; - - DPRINTFN(5, "count=%u rem=%u\n", count, td->remainder); - - /* clear did stall */ - td->did_stall = 0; - - /* clear stall */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, 0); - - /* verify data length */ - if (count != td->remainder) { - DPRINTFN(0, "Invalid SETUP packet " - "length, %d bytes\n", count); - goto busy; - } - if (count != sizeof(req)) { - DPRINTFN(0, "Unsupported SETUP packet " - "length, %d bytes\n", count); - goto busy; - } - /* receive data */ - saf1761_read_device_fifo(sc, td, sizeof(req)); - - /* extract SETUP packet again */ - usbd_copy_out(td->pc, 0, &req, sizeof(req)); - - /* sneak peek the set address request */ - if ((req.bmRequestType == UT_WRITE_DEVICE) && - (req.bRequest == UR_SET_ADDRESS)) { - sc->sc_dv_addr = req.wValue[0] & 0x7F; - DPRINTF("Set address %d\n", sc->sc_dv_addr); - } else { - sc->sc_dv_addr = 0xFF; - } - return (0); /* complete */ - -busy: - /* abort any ongoing transfer */ - if (!td->did_stall) { - DPRINTFN(5, "stalling\n"); - - /* set stall */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL); - - td->did_stall = 1; - } - return (1); /* not complete */ -} - -static uint8_t -saf1761_device_data_rx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t count; - uint8_t got_short = 0; - - if (td->ep_index == 0) { - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP); - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) { - if (td->remainder == 0) { - /* - * We are actually complete and have - * received the next SETUP: - */ - DPRINTFN(5, "faking complete\n"); - return (0); /* complete */ - } - DPRINTFN(5, "SETUP packet while receiving data\n"); - /* - * USB Host Aborted the transfer. - */ - td->error_any = 1; - return (0); /* complete */ - } - } - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (td->ep_index << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - SOTG_EP_INDEX_DIR_OUT); - - /* enable data stage */ - if (td->set_toggle) { - td->set_toggle = 0; - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_DSEN); - } - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) == 0) - return (1); /* not complete */ - - /* get buffer length */ - count &= SOTG_BUF_LENGTH_BUFLEN_MASK; - - DPRINTFN(5, "rem=%u count=0x%04x\n", td->remainder, count); - - /* verify the packet byte count */ - if (count != td->max_packet_size) { - if (count < td->max_packet_size) { - /* we have a short packet */ - td->short_pkt = 1; - got_short = 1; - } else { - /* invalid USB packet */ - td->error_any = 1; - return (0); /* we are complete */ - } - } - /* verify the packet byte count */ - if (count > td->remainder) { - /* invalid USB packet */ - td->error_any = 1; - return (0); /* we are complete */ - } - /* receive data */ - saf1761_read_device_fifo(sc, td, count); - - /* check if we are complete */ - if ((td->remainder == 0) || got_short) { - if (td->short_pkt) { - /* we are complete */ - return (0); - } - /* else need to receive a zero length packet */ - } - return (1); /* not complete */ -} - -static uint8_t -saf1761_device_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t count; - - if (td->ep_index == 0) { - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP); - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) { - DPRINTFN(5, "SETUP abort\n"); - /* - * USB Host Aborted the transfer. - */ - td->error_any = 1; - return (0); /* complete */ - } - } - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (td->ep_index << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - SOTG_EP_INDEX_DIR_IN); - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) - return (1); /* not complete */ - - /* enable data stage */ - if (td->set_toggle) { - td->set_toggle = 0; - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_DSEN); - } - - DPRINTFN(5, "rem=%u\n", td->remainder); - - count = td->max_packet_size; - if (td->remainder < count) { - /* we have a short packet */ - td->short_pkt = 1; - count = td->remainder; - } - /* transmit data */ - saf1761_write_device_fifo(sc, td, count); - - if (td->ep_index == 0) { - if (count < SOTG_FS_MAX_PACKET_SIZE) { - /* set end of packet */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_VENDP); - } - } else { - if (count < SOTG_HS_MAX_PACKET_SIZE) { - /* set end of packet */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_VENDP); - } - } - - /* check remainder */ - if (td->remainder == 0) { - if (td->short_pkt) { - return (0); /* complete */ - } - /* else we need to transmit a short packet */ - } - return (1); /* not complete */ -} - -static uint8_t -saf1761_device_data_tx_sync(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) -{ - uint32_t count; - - if (td->ep_index == 0) { - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, SOTG_EP_INDEX_EP0SETUP); - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) { - DPRINTFN(5, "Faking complete\n"); - return (0); /* complete */ - } - } - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (td->ep_index << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - SOTG_EP_INDEX_DIR_IN); - - count = SAF1761_READ_LE_4(sc, SOTG_BUF_LENGTH); - - /* check buffer status */ - if ((count & SOTG_BUF_LENGTH_FILLED_MASK) != 0) - return (1); /* busy */ - - if (sc->sc_dv_addr != 0xFF) { - /* write function address */ - saf1761_otg_set_address(sc, sc->sc_dv_addr); - } - return (0); /* complete */ -} - -static void -saf1761_otg_xfer_do_fifo(struct saf1761_otg_softc *sc, struct usb_xfer *xfer) -{ - struct saf1761_otg_td *td; - uint8_t toggle; - - DPRINTFN(9, "\n"); - - td = xfer->td_transfer_cache; - if (td == NULL) - return; - - while (1) { - if ((td->func) (sc, td)) { - /* operation in progress */ - break; - } - if (((void *)td) == xfer->td_transfer_last) { - goto done; - } - if (td->error_any) { - goto done; - } else if (td->remainder > 0) { - /* - * We had a short transfer. If there is no alternate - * next, stop processing ! - */ - if (!td->alt_next) { - goto done; - } - } - /* - * Fetch the next transfer descriptor. - */ - toggle = td->toggle; - td = td->obj_next; - td->toggle = toggle; - xfer->td_transfer_cache = td; - } - return; - -done: - /* compute all actual lengths */ - xfer->td_transfer_cache = NULL; - sc->sc_xfer_complete = 1; -} - -static uint8_t -saf1761_otg_xfer_do_complete(struct saf1761_otg_softc *sc, struct usb_xfer *xfer) -{ - struct saf1761_otg_td *td; - - DPRINTFN(9, "\n"); - - td = xfer->td_transfer_cache; - if (td == NULL) { - /* compute all actual lengths */ - saf1761_otg_standard_done(xfer); - return (1); - } - return (0); -} - -static void -saf1761_otg_interrupt_poll_locked(struct saf1761_otg_softc *sc) -{ - struct usb_xfer *xfer; - - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) - saf1761_otg_xfer_do_fifo(sc, xfer); -} - -static void -saf1761_otg_enable_psof(struct saf1761_otg_softc *sc, uint8_t on) -{ - if (on) { - sc->sc_intr_enable |= SOTG_DCINTERRUPT_IEPSOF; - } else { - sc->sc_intr_enable &= ~SOTG_DCINTERRUPT_IEPSOF; - } - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable); -} - -static void -saf1761_otg_wait_suspend(struct saf1761_otg_softc *sc, uint8_t on) -{ - if (on) { - sc->sc_intr_enable |= SOTG_DCINTERRUPT_IESUSP; - sc->sc_intr_enable &= ~SOTG_DCINTERRUPT_IERESM; - } else { - sc->sc_intr_enable &= ~SOTG_DCINTERRUPT_IESUSP; - sc->sc_intr_enable |= SOTG_DCINTERRUPT_IERESM; - } - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable); -} - -static void -saf1761_otg_update_vbus(struct saf1761_otg_softc *sc) -{ - uint16_t status; - - /* read fresh status */ - status = SAF1761_READ_LE_4(sc, SOTG_STATUS); - - DPRINTFN(4, "STATUS=0x%04x\n", status); - - if ((status & SOTG_STATUS_VBUS_VLD) && - (status & SOTG_STATUS_ID)) { - /* VBUS present and device mode */ - if (!sc->sc_flags.status_vbus) { - sc->sc_flags.status_vbus = 1; - - /* complete root HUB interrupt endpoint */ - saf1761_otg_root_intr(sc); - } - } else { - /* VBUS not-present or host mode */ - if (sc->sc_flags.status_vbus) { - sc->sc_flags.status_vbus = 0; - sc->sc_flags.status_bus_reset = 0; - sc->sc_flags.status_suspend = 0; - sc->sc_flags.change_suspend = 0; - sc->sc_flags.change_connect = 1; - - /* complete root HUB interrupt endpoint */ - saf1761_otg_root_intr(sc); - } - } -} - -static void -saf1761_otg_interrupt_complete_locked(struct saf1761_otg_softc *sc) -{ - struct usb_xfer *xfer; -repeat: - /* scan for completion events */ - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - if (saf1761_otg_xfer_do_complete(sc, xfer)) - goto repeat; - } -} - -int -saf1761_otg_filter_interrupt(void *arg) -{ - struct saf1761_otg_softc *sc = arg; - int retval = FILTER_HANDLED; - uint32_t hcstat; - uint32_t status; - - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - hcstat = SAF1761_READ_LE_4(sc, SOTG_HCINTERRUPT); - /* acknowledge all host controller interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_HCINTERRUPT, hcstat); - - status = SAF1761_READ_LE_4(sc, SOTG_DCINTERRUPT); - /* acknowledge all device controller interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT, - status & ~SAF1761_DCINTERRUPT_THREAD_IRQ); - - (void) SAF1761_READ_LE_4(sc, SOTG_ATL_PTD_DONE_PTD); - (void) SAF1761_READ_LE_4(sc, SOTG_INT_PTD_DONE_PTD); - (void) SAF1761_READ_LE_4(sc, SOTG_ISO_PTD_DONE_PTD); - - DPRINTFN(9, "HCINTERRUPT=0x%08x DCINTERRUPT=0x%08x\n", hcstat, status); - - if (status & SOTG_DCINTERRUPT_IEPSOF) { - if ((sc->sc_host_async_busy_map[1] | sc->sc_host_async_busy_map[0] | - sc->sc_host_intr_busy_map[1] | sc->sc_host_intr_busy_map[0] | - sc->sc_host_isoc_busy_map[1] | sc->sc_host_isoc_busy_map[0]) != 0) { - /* busy waiting is active */ - retval = FILTER_SCHEDULE_THREAD; - - sc->sc_host_async_busy_map[1] = sc->sc_host_async_busy_map[0]; - sc->sc_host_async_busy_map[0] = 0; - - sc->sc_host_intr_busy_map[1] = sc->sc_host_intr_busy_map[0]; - sc->sc_host_intr_busy_map[0] = 0; - - sc->sc_host_isoc_busy_map[1] = sc->sc_host_isoc_busy_map[0]; - sc->sc_host_isoc_busy_map[0] = 0; - } else { - /* busy waiting is not active */ - saf1761_otg_enable_psof(sc, 0); - } - } - - if (status & SAF1761_DCINTERRUPT_THREAD_IRQ) - retval = FILTER_SCHEDULE_THREAD; - - /* poll FIFOs, if any */ - saf1761_otg_interrupt_poll_locked(sc); - - if (sc->sc_xfer_complete != 0) - retval = FILTER_SCHEDULE_THREAD; - - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); - - return (retval); -} - -void -saf1761_otg_interrupt(void *arg) -{ - struct saf1761_otg_softc *sc = arg; - uint32_t status; - - USB_BUS_LOCK(&sc->sc_bus); - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - status = SAF1761_READ_LE_4(sc, SOTG_DCINTERRUPT) & - SAF1761_DCINTERRUPT_THREAD_IRQ; - - /* acknowledge all device controller interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT, status); - - DPRINTF("DCINTERRUPT=0x%08x SOF=0x%08x " - "FRINDEX=0x%08x\n", status, - SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM), - SAF1761_READ_LE_4(sc, SOTG_FRINDEX)); - - /* update VBUS and ID bits, if any */ - if (status & SOTG_DCINTERRUPT_IEVBUS) - saf1761_otg_update_vbus(sc); - - if (status & SOTG_DCINTERRUPT_IEBRST) { - /* unlock device */ - SAF1761_WRITE_LE_4(sc, SOTG_UNLOCK_DEVICE, - SOTG_UNLOCK_DEVICE_CODE); - - /* Enable device address */ - SAF1761_WRITE_LE_4(sc, SOTG_ADDRESS, - SOTG_ADDRESS_ENABLE); - - sc->sc_flags.status_bus_reset = 1; - sc->sc_flags.status_suspend = 0; - sc->sc_flags.change_suspend = 0; - sc->sc_flags.change_connect = 1; - - /* disable resume interrupt */ - saf1761_otg_wait_suspend(sc, 1); - /* complete root HUB interrupt endpoint */ - saf1761_otg_root_intr(sc); - } - /* - * If "RESUME" and "SUSPEND" is set at the same time we - * interpret that like "RESUME". Resume is set when there is - * at least 3 milliseconds of inactivity on the USB BUS: - */ - if (status & SOTG_DCINTERRUPT_IERESM) { - /* unlock device */ - SAF1761_WRITE_LE_4(sc, SOTG_UNLOCK_DEVICE, - SOTG_UNLOCK_DEVICE_CODE); - - if (sc->sc_flags.status_suspend) { - sc->sc_flags.status_suspend = 0; - sc->sc_flags.change_suspend = 1; - /* disable resume interrupt */ - saf1761_otg_wait_suspend(sc, 1); - /* complete root HUB interrupt endpoint */ - saf1761_otg_root_intr(sc); - } - } else if (status & SOTG_DCINTERRUPT_IESUSP) { - if (!sc->sc_flags.status_suspend) { - sc->sc_flags.status_suspend = 1; - sc->sc_flags.change_suspend = 1; - /* enable resume interrupt */ - saf1761_otg_wait_suspend(sc, 0); - /* complete root HUB interrupt endpoint */ - saf1761_otg_root_intr(sc); - } - } - - if (sc->sc_xfer_complete != 0) { - sc->sc_xfer_complete = 0; - - /* complete FIFOs, if any */ - saf1761_otg_interrupt_complete_locked(sc); - } - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); - USB_BUS_UNLOCK(&sc->sc_bus); -} - -static void -saf1761_otg_setup_standard_chain_sub(struct saf1761_otg_std_temp *temp) -{ - struct saf1761_otg_td *td; - - /* get current Transfer Descriptor */ - td = temp->td_next; - temp->td = td; - - /* prepare for next TD */ - temp->td_next = td->obj_next; - - /* fill out the Transfer Descriptor */ - td->func = temp->func; - td->pc = temp->pc; - td->offset = temp->offset; - td->remainder = temp->len; - td->error_any = 0; - td->error_stall = 0; - td->set_toggle = 0; - td->did_stall = temp->did_stall; - td->short_pkt = temp->short_pkt; - td->alt_next = temp->setup_alt_next; - td->channel = SOTG_HOST_CHANNEL_MAX; -} - -static void -saf1761_otg_setup_standard_chain(struct usb_xfer *xfer) -{ - struct saf1761_otg_std_temp temp; - struct saf1761_otg_softc *sc; - struct saf1761_otg_td *td; - uint32_t x; - uint8_t ep_no; - uint8_t ep_type; - uint8_t need_sync; - uint8_t is_host; - uint8_t uframe_start; - uint8_t uframe_interval; - - DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n", - xfer->address, UE_GET_ADDR(xfer->endpointno), - xfer->sumlen, usbd_get_speed(xfer->xroot->udev)); - - temp.max_frame_size = xfer->max_frame_size; - - td = xfer->td_start[0]; - xfer->td_transfer_first = td; - xfer->td_transfer_cache = td; - - /* setup temp */ - - temp.pc = NULL; - temp.td = NULL; - temp.td_next = xfer->td_start[0]; - temp.offset = 0; - temp.setup_alt_next = xfer->flags_int.short_frames_ok || - xfer->flags_int.isochronous_xfr; - temp.did_stall = !xfer->flags_int.control_stall; - - is_host = (xfer->xroot->udev->flags.usb_mode == USB_MODE_HOST); - - sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); - ep_no = (xfer->endpointno & UE_ADDR); - ep_type = (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE); - - /* check if we should prepend a setup message */ - - if (xfer->flags_int.control_xfr) { - if (xfer->flags_int.control_hdr) { - if (is_host) - temp.func = &saf1761_host_setup_tx; - else - temp.func = &saf1761_device_setup_rx; - - temp.len = xfer->frlengths[0]; - temp.pc = xfer->frbuffers + 0; - temp.short_pkt = temp.len ? 1 : 0; - /* check for last frame */ - if (xfer->nframes == 1) { - /* no STATUS stage yet, SETUP is last */ - if (xfer->flags_int.control_act) - temp.setup_alt_next = 0; - } - saf1761_otg_setup_standard_chain_sub(&temp); - } - x = 1; - } else { - x = 0; - } - - uframe_start = 0; - uframe_interval = 0; - - if (x != xfer->nframes) { - if (xfer->endpointno & UE_DIR_IN) { - if (is_host) { - if (ep_type == UE_INTERRUPT) { - temp.func = &saf1761_host_intr_data_rx; - } else if (ep_type == UE_ISOCHRONOUS) { - temp.func = &saf1761_host_isoc_data_rx; - uframe_start = (SAF1761_READ_LE_4(sc, SOTG_FRINDEX) + 8) & - (SOTG_FRINDEX_MASK & ~7); - if (xfer->xroot->udev->speed == USB_SPEED_HIGH) - uframe_interval = 1U << xfer->fps_shift; - else - uframe_interval = 8U; - } else { - temp.func = &saf1761_host_bulk_data_rx; - } - need_sync = 0; - } else { - temp.func = &saf1761_device_data_tx; - need_sync = 1; - } - } else { - if (is_host) { - if (ep_type == UE_INTERRUPT) { - temp.func = &saf1761_host_intr_data_tx; - } else if (ep_type == UE_ISOCHRONOUS) { - temp.func = &saf1761_host_isoc_data_tx; - uframe_start = (SAF1761_READ_LE_4(sc, SOTG_FRINDEX) + 8) & - (SOTG_FRINDEX_MASK & ~7); - if (xfer->xroot->udev->speed == USB_SPEED_HIGH) - uframe_interval = 1U << xfer->fps_shift; - else - uframe_interval = 8U; - } else { - temp.func = &saf1761_host_bulk_data_tx; - } - need_sync = 0; - } else { - temp.func = &saf1761_device_data_rx; - need_sync = 0; - } - } - - /* setup "pc" pointer */ - temp.pc = xfer->frbuffers + x; - } else { - need_sync = 0; - } - - while (x != xfer->nframes) { - /* DATA0 / DATA1 message */ - - temp.len = xfer->frlengths[x]; - - x++; - - if (x == xfer->nframes) { - if (xfer->flags_int.control_xfr) { - if (xfer->flags_int.control_act) { - temp.setup_alt_next = 0; - } - } else { - temp.setup_alt_next = 0; - } - } - if (temp.len == 0) { - /* make sure that we send an USB packet */ - - temp.short_pkt = 0; - - } else { - /* regular data transfer */ - - temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1; - } - - saf1761_otg_setup_standard_chain_sub(&temp); - - if (xfer->flags_int.isochronous_xfr) { - temp.offset += temp.len; - - /* stamp the starting point for this transaction */ - temp.td->uframe = uframe_start; - - /* advance to next */ - uframe_start += uframe_interval; - } else { - /* get next Page Cache pointer */ - temp.pc = xfer->frbuffers + x; - } - } - - /* check for control transfer */ - if (xfer->flags_int.control_xfr) { - /* always setup a valid "pc" pointer for status and sync */ - temp.pc = xfer->frbuffers + 0; - temp.len = 0; - temp.short_pkt = 0; - temp.setup_alt_next = 0; - - /* check if we should append a status stage */ - if (!xfer->flags_int.control_act) { - /* - * Send a DATA1 message and invert the current - * endpoint direction. - */ - if (xfer->endpointno & UE_DIR_IN) { - if (is_host) { - temp.func = &saf1761_host_bulk_data_tx; - need_sync = 0; - } else { - temp.func = &saf1761_device_data_rx; - need_sync = 0; - } - } else { - if (is_host) { - temp.func = &saf1761_host_bulk_data_rx; - need_sync = 0; - } else { - temp.func = &saf1761_device_data_tx; - need_sync = 1; - } - } - temp.len = 0; - temp.short_pkt = 0; - - saf1761_otg_setup_standard_chain_sub(&temp); - - /* data toggle should be DATA1 */ - td = temp.td; - td->set_toggle = 1; - - if (need_sync) { - /* we need a SYNC point after TX */ - temp.func = &saf1761_device_data_tx_sync; - saf1761_otg_setup_standard_chain_sub(&temp); - } - } - } else { - if (need_sync) { - temp.pc = xfer->frbuffers + 0; - temp.len = 0; - temp.short_pkt = 0; - temp.setup_alt_next = 0; - - /* we need a SYNC point after TX */ - temp.func = &saf1761_device_data_tx_sync; - saf1761_otg_setup_standard_chain_sub(&temp); - } - } - - /* must have at least one frame! */ - td = temp.td; - xfer->td_transfer_last = td; - - if (is_host) { - /* get first again */ - td = xfer->td_transfer_first; - td->toggle = (xfer->endpoint->toggle_next ? 1 : 0); - } -} - -static void -saf1761_otg_timeout(void *arg) -{ - struct usb_xfer *xfer = arg; - - DPRINTF("xfer=%p\n", xfer); - - USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); - - /* transfer is transferred */ - saf1761_otg_device_done(xfer, USB_ERR_TIMEOUT); -} - -static void -saf1761_otg_intr_set(struct usb_xfer *xfer, uint8_t set) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); - uint8_t ep_no = (xfer->endpointno & UE_ADDR); - uint32_t mask; - - DPRINTFN(15, "endpoint=%d set=%d\n", xfer->endpointno, set); - - if (ep_no == 0) { - mask = SOTG_DCINTERRUPT_IEPRX(0) | - SOTG_DCINTERRUPT_IEPTX(0) | - SOTG_DCINTERRUPT_IEP0SETUP; - } else if (xfer->endpointno & UE_DIR_IN) { - mask = SOTG_DCINTERRUPT_IEPTX(ep_no); - } else { - mask = SOTG_DCINTERRUPT_IEPRX(ep_no); - } - - if (set) - sc->sc_intr_enable |= mask; - else - sc->sc_intr_enable &= ~mask; - - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable); -} - -static void -saf1761_otg_start_standard_chain(struct usb_xfer *xfer) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); - - DPRINTFN(9, "\n"); - - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - /* poll one time */ - saf1761_otg_xfer_do_fifo(sc, xfer); - - if (saf1761_otg_xfer_do_complete(sc, xfer) == 0) { - /* - * Only enable the endpoint interrupt when we are - * actually waiting for data, hence we are dealing - * with level triggered interrupts ! - */ - saf1761_otg_intr_set(xfer, 1); - - /* put transfer on interrupt queue */ - usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); - - /* start timeout, if any */ - if (xfer->timeout != 0) { - usbd_transfer_timeout_ms(xfer, - &saf1761_otg_timeout, xfer->timeout); - } - } - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); -} - -static void -saf1761_otg_root_intr(struct saf1761_otg_softc *sc) -{ - DPRINTFN(9, "\n"); - - USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); - - /* set port bit - we only have one port */ - sc->sc_hub_idata[0] = 0x02; - - uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata, - sizeof(sc->sc_hub_idata)); -} - -static usb_error_t -saf1761_otg_standard_done_sub(struct usb_xfer *xfer) -{ - struct saf1761_otg_td *td; - uint32_t len; - usb_error_t error; - - DPRINTFN(9, "\n"); - - td = xfer->td_transfer_cache; - - do { - len = td->remainder; - - /* store last data toggle */ - xfer->endpoint->toggle_next = td->toggle; - - if (xfer->aframes != xfer->nframes) { - /* - * Verify the length and subtract - * the remainder from "frlengths[]": - */ - if (len > xfer->frlengths[xfer->aframes]) { - td->error_any = 1; - } else { - xfer->frlengths[xfer->aframes] -= len; - } - } - /* Check for transfer error */ - if (td->error_any) { - /* the transfer is finished */ - error = (td->error_stall ? - USB_ERR_STALLED : USB_ERR_IOERROR); - td = NULL; - break; - } - /* Check for short transfer */ - if (len > 0) { - if (xfer->flags_int.short_frames_ok || - xfer->flags_int.isochronous_xfr) { - /* follow alt next */ - if (td->alt_next) { - td = td->obj_next; - } else { - td = NULL; - } - } else { - /* the transfer is finished */ - td = NULL; - } - error = 0; - break; - } - td = td->obj_next; - - /* this USB frame is complete */ - error = 0; - break; - - } while (0); - - /* update transfer cache */ - - xfer->td_transfer_cache = td; - - return (error); -} - -static void -saf1761_otg_standard_done(struct usb_xfer *xfer) -{ - usb_error_t err = 0; - - DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", - xfer, xfer->endpoint); - - /* reset scanner */ - - xfer->td_transfer_cache = xfer->td_transfer_first; - - if (xfer->flags_int.control_xfr) { - if (xfer->flags_int.control_hdr) { - err = saf1761_otg_standard_done_sub(xfer); - } - xfer->aframes = 1; - - if (xfer->td_transfer_cache == NULL) { - goto done; - } - } - while (xfer->aframes != xfer->nframes) { - err = saf1761_otg_standard_done_sub(xfer); - xfer->aframes++; - - if (xfer->td_transfer_cache == NULL) { - goto done; - } - } - - if (xfer->flags_int.control_xfr && - !xfer->flags_int.control_act) { - err = saf1761_otg_standard_done_sub(xfer); - } -done: - saf1761_otg_device_done(xfer, err); -} - -/*------------------------------------------------------------------------* - * saf1761_otg_device_done - * - * NOTE: this function can be called more than one time on the - * same USB transfer! - *------------------------------------------------------------------------*/ -static void -saf1761_otg_device_done(struct usb_xfer *xfer, usb_error_t error) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); - - USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); - - DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n", - xfer, xfer->endpoint, error); - - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { - saf1761_otg_intr_set(xfer, 0); - } else { - struct saf1761_otg_td *td; - - td = xfer->td_transfer_cache; - - if (td != NULL) - saf1761_host_channel_free(sc, td); - } - - /* dequeue transfer and start next transfer */ - usbd_transfer_done(xfer, error); - - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); -} - -static void -saf1761_otg_xfer_stall(struct usb_xfer *xfer) -{ - saf1761_otg_device_done(xfer, USB_ERR_STALLED); -} - -static void -saf1761_otg_set_stall(struct usb_device *udev, - struct usb_endpoint *ep, uint8_t *did_stall) -{ - struct saf1761_otg_softc *sc; - uint8_t ep_no; - uint8_t ep_type; - uint8_t ep_dir; - - USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); - - /* check mode */ - if (udev->flags.usb_mode != USB_MODE_DEVICE) { - /* not supported */ - return; - } - - DPRINTFN(5, "endpoint=%p\n", ep); - - /* set STALL bit */ - sc = SAF1761_OTG_BUS2SC(udev->bus); - - ep_no = (ep->edesc->bEndpointAddress & UE_ADDR); - ep_dir = (ep->edesc->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)); - ep_type = (ep->edesc->bmAttributes & UE_XFERTYPE); - - if (ep_type == UE_CONTROL) { - /* should not happen */ - return; - } - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (ep_no << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - ((ep_dir == UE_DIR_IN) ? SOTG_EP_INDEX_DIR_IN : - SOTG_EP_INDEX_DIR_OUT)); - - /* set stall */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_STALL); - - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); -} - -static void -saf1761_otg_clear_stall_sub_locked(struct saf1761_otg_softc *sc, - uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir) -{ - if (ep_type == UE_CONTROL) { - /* clearing stall is not needed */ - return; - } - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (ep_no << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - ((ep_dir == UE_DIR_IN) ? SOTG_EP_INDEX_DIR_IN : - SOTG_EP_INDEX_DIR_OUT)); - - /* disable endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_TYPE, 0); - /* enable endpoint again - will clear data toggle */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_TYPE, ep_type | SOTG_EP_TYPE_ENABLE); - - /* clear buffer */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, SOTG_CTRL_FUNC_CLBUF); - /* clear stall */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_FUNC, 0); -} - -static void -saf1761_otg_clear_stall(struct usb_device *udev, struct usb_endpoint *ep) -{ - struct saf1761_otg_softc *sc; - struct usb_endpoint_descriptor *ed; - - USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); - - DPRINTFN(5, "endpoint=%p\n", ep); - - /* check mode */ - if (udev->flags.usb_mode != USB_MODE_DEVICE) { - /* not supported */ - return; - } - /* get softc */ - sc = SAF1761_OTG_BUS2SC(udev->bus); - - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - /* get endpoint descriptor */ - ed = ep->edesc; - - /* reset endpoint */ - saf1761_otg_clear_stall_sub_locked(sc, - (ed->bEndpointAddress & UE_ADDR), - (ed->bmAttributes & UE_XFERTYPE), - (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); - - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); -} - -usb_error_t -saf1761_otg_init(struct saf1761_otg_softc *sc) -{ - const struct usb_hw_ep_profile *pf; - uint32_t x; - - DPRINTF("\n"); - - /* set up the bus structure */ - sc->sc_bus.usbrev = USB_REV_2_0; - sc->sc_bus.methods = &saf1761_otg_bus_methods; - - USB_BUS_LOCK(&sc->sc_bus); - - /* Reset Host controller, including HW mode */ - SAF1761_WRITE_LE_4(sc, SOTG_SW_RESET, SOTG_SW_RESET_ALL); - - DELAY(1000); - - /* Reset Host controller, including HW mode */ - SAF1761_WRITE_LE_4(sc, SOTG_SW_RESET, SOTG_SW_RESET_HC); - - /* wait a bit */ - DELAY(1000); - - SAF1761_WRITE_LE_4(sc, SOTG_SW_RESET, 0); - - /* wait a bit */ - DELAY(1000); - - /* Enable interrupts */ - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_GLOBAL_INTR_EN | - SOTG_HW_MODE_CTRL_COMN_INT; - - /* unlock device */ - SAF1761_WRITE_LE_4(sc, SOTG_UNLOCK_DEVICE, SOTG_UNLOCK_DEVICE_CODE); - - /* - * Set correct hardware mode, must be written twice if bus - * width is changed: - */ - SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode); - SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode); - - SAF1761_WRITE_LE_4(sc, SOTG_DCSCRATCH, 0xdeadbeef); - SAF1761_WRITE_LE_4(sc, SOTG_HCSCRATCH, 0xdeadbeef); - - DPRINTF("DCID=0x%08x VEND_PROD=0x%08x HWMODE=0x%08x SCRATCH=0x%08x,0x%08x\n", - SAF1761_READ_LE_4(sc, SOTG_DCCHIP_ID), - SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID), - SAF1761_READ_LE_4(sc, SOTG_HW_MODE_CTRL), - SAF1761_READ_LE_4(sc, SOTG_DCSCRATCH), - SAF1761_READ_LE_4(sc, SOTG_HCSCRATCH)); - - /* reset device controller */ - SAF1761_WRITE_LE_4(sc, SOTG_MODE, SOTG_MODE_SFRESET); - SAF1761_WRITE_LE_4(sc, SOTG_MODE, 0); - - /* wait a bit */ - DELAY(1000); - - /* reset host controller */ - SAF1761_WRITE_LE_4(sc, SOTG_USBCMD, SOTG_USBCMD_HCRESET); - - /* wait for reset to clear */ - for (x = 0; x != 10; x++) { - if ((SAF1761_READ_LE_4(sc, SOTG_USBCMD) & SOTG_USBCMD_HCRESET) == 0) - break; - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 10); - } - - SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode | - SOTG_HW_MODE_CTRL_ALL_ATX_RESET); - - /* wait a bit */ - DELAY(1000); - - SAF1761_WRITE_LE_4(sc, SOTG_HW_MODE_CTRL, sc->sc_hw_mode); - - /* wait a bit */ - DELAY(1000); - - /* do a pulldown */ - saf1761_otg_pull_down(sc); - - /* wait 10ms for pulldown to stabilise */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100); - - for (x = 1;; x++) { - saf1761_otg_get_hw_ep_profile(NULL, &pf, x); - if (pf == NULL) - break; - - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (x << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - SOTG_EP_INDEX_DIR_IN); - - /* select the maximum packet size */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_MAXPACKET, pf->max_in_frame_size); - - /* select the correct endpoint */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_INDEX, - (x << SOTG_EP_INDEX_ENDP_INDEX_SHIFT) | - SOTG_EP_INDEX_DIR_OUT); - - /* select the maximum packet size */ - SAF1761_WRITE_LE_4(sc, SOTG_EP_MAXPACKET, pf->max_out_frame_size); - } - - /* enable interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_MODE, SOTG_MODE_GLINTENA | - SOTG_MODE_CLKAON | SOTG_MODE_WKUPCS); - - sc->sc_interrupt_cfg |= - SOTG_INTERRUPT_CFG_CDBGMOD | - SOTG_INTERRUPT_CFG_DDBGMODIN | - SOTG_INTERRUPT_CFG_DDBGMODOUT; - - /* set default values */ - SAF1761_WRITE_LE_4(sc, SOTG_INTERRUPT_CFG, sc->sc_interrupt_cfg); - - /* enable VBUS and ID interrupt */ - SAF1761_WRITE_LE_4(sc, SOTG_IRQ_ENABLE_SET_CLR, - SOTG_IRQ_ENABLE_CLR(0xFFFF)); - SAF1761_WRITE_LE_4(sc, SOTG_IRQ_ENABLE_SET_CLR, - SOTG_IRQ_ENABLE_SET(SOTG_IRQ_ID | SOTG_IRQ_VBUS_VLD)); - - /* enable interrupts */ - sc->sc_intr_enable = SOTG_DCINTERRUPT_IEVBUS | - SOTG_DCINTERRUPT_IEBRST | SOTG_DCINTERRUPT_IESUSP; - SAF1761_WRITE_LE_4(sc, SOTG_DCINTERRUPT_EN, sc->sc_intr_enable); - - /* - * Connect ATX port 1 to device controller, select external - * charge pump and driver VBUS to +5V: - */ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_SET_CLR, - SOTG_CTRL_CLR(0xFFFF)); -#ifdef __rtems__ - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_SET_CLR, - SOTG_CTRL_SET(SOTG_CTRL_SEL_CP_EXT | SOTG_CTRL_VBUS_DRV)); -#else - SAF1761_WRITE_LE_4(sc, SOTG_CTRL_SET_CLR, - SOTG_CTRL_SET(SOTG_CTRL_SW_SEL_HC_DC | - SOTG_CTRL_BDIS_ACON_EN | SOTG_CTRL_SEL_CP_EXT | - SOTG_CTRL_VBUS_DRV)); -#endif - /* disable device address */ - SAF1761_WRITE_LE_4(sc, SOTG_ADDRESS, 0); - - /* enable host controller clock and preserve reserved bits */ - x = SAF1761_READ_LE_4(sc, SOTG_POWER_DOWN); - SAF1761_WRITE_LE_4(sc, SOTG_POWER_DOWN, x | SOTG_POWER_DOWN_HC_CLK_EN); - - /* wait 10ms for clock */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100); - - /* enable configuration flag */ - SAF1761_WRITE_LE_4(sc, SOTG_CONFIGFLAG, SOTG_CONFIGFLAG_ENABLE); - - /* clear RAM block */ - for (x = 0x400; x != 0x10000; x += 4) - SAF1761_WRITE_LE_4(sc, x, 0); - - /* start the HC */ - SAF1761_WRITE_LE_4(sc, SOTG_USBCMD, SOTG_USBCMD_RS); - - DPRINTF("USBCMD=0x%08x\n", SAF1761_READ_LE_4(sc, SOTG_USBCMD)); - - /* make HC scan all PTDs */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_LAST_PTD, (1 << 31)); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_LAST_PTD, (1 << 31)); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_LAST_PTD, (1 << 31)); - - /* skip all PTDs by default */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, -1U); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, -1U); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, -1U); - - /* activate all PTD types */ - SAF1761_WRITE_LE_4(sc, SOTG_HCBUFFERSTATUS, - SOTG_HCBUFFERSTATUS_ISO_BUF_FILL | - SOTG_HCBUFFERSTATUS_INT_BUF_FILL | - SOTG_HCBUFFERSTATUS_ATL_BUF_FILL); - - /* we don't use the AND mask */ - SAF1761_WRITE_LE_4(sc, SOTG_ISO_IRQ_MASK_AND, 0); - SAF1761_WRITE_LE_4(sc, SOTG_INT_IRQ_MASK_AND, 0); - SAF1761_WRITE_LE_4(sc, SOTG_ATL_IRQ_MASK_AND, 0); - - /* enable all PTD OR interrupts by default */ - SAF1761_WRITE_LE_4(sc, SOTG_ISO_IRQ_MASK_OR, -1U); - SAF1761_WRITE_LE_4(sc, SOTG_INT_IRQ_MASK_OR, -1U); - SAF1761_WRITE_LE_4(sc, SOTG_ATL_IRQ_MASK_OR, -1U); - - /* enable HC interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_HCINTERRUPT_ENABLE, - SOTG_HCINTERRUPT_OTG_IRQ | - SOTG_HCINTERRUPT_ISO_IRQ | - SOTG_HCINTERRUPT_ALT_IRQ | - SOTG_HCINTERRUPT_INT_IRQ); - - /* poll initial VBUS status */ - saf1761_otg_update_vbus(sc); - - USB_BUS_UNLOCK(&sc->sc_bus); - - /* catch any lost interrupts */ - - saf1761_otg_do_poll(&sc->sc_bus); - - return (0); /* success */ -} - -void -saf1761_otg_uninit(struct saf1761_otg_softc *sc) -{ - USB_BUS_LOCK(&sc->sc_bus); - - /* disable all interrupts */ - SAF1761_WRITE_LE_4(sc, SOTG_MODE, 0); - - sc->sc_flags.port_powered = 0; - sc->sc_flags.status_vbus = 0; - sc->sc_flags.status_bus_reset = 0; - sc->sc_flags.status_suspend = 0; - sc->sc_flags.change_suspend = 0; - sc->sc_flags.change_connect = 1; - - saf1761_otg_pull_down(sc); - USB_BUS_UNLOCK(&sc->sc_bus); -} - -static void -saf1761_otg_suspend(struct saf1761_otg_softc *sc) -{ - /* TODO */ -} - -static void -saf1761_otg_resume(struct saf1761_otg_softc *sc) -{ - /* TODO */ -} - -static void -saf1761_otg_do_poll(struct usb_bus *bus) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(bus); - - USB_BUS_LOCK(&sc->sc_bus); - USB_BUS_SPIN_LOCK(&sc->sc_bus); - saf1761_otg_interrupt_poll_locked(sc); - saf1761_otg_interrupt_complete_locked(sc); - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); - USB_BUS_UNLOCK(&sc->sc_bus); -} - -/*------------------------------------------------------------------------* - * saf1761_otg control support - * saf1761_otg interrupt support - * saf1761_otg bulk support - *------------------------------------------------------------------------*/ -static void -saf1761_otg_device_non_isoc_open(struct usb_xfer *xfer) -{ - return; -} - -static void -saf1761_otg_device_non_isoc_close(struct usb_xfer *xfer) -{ - saf1761_otg_device_done(xfer, USB_ERR_CANCELLED); -} - -static void -saf1761_otg_device_non_isoc_enter(struct usb_xfer *xfer) -{ - return; -} - -static void -saf1761_otg_device_non_isoc_start(struct usb_xfer *xfer) -{ - /* setup TDs */ - saf1761_otg_setup_standard_chain(xfer); - saf1761_otg_start_standard_chain(xfer); -} - -static const struct usb_pipe_methods saf1761_otg_non_isoc_methods = -{ - .open = saf1761_otg_device_non_isoc_open, - .close = saf1761_otg_device_non_isoc_close, - .enter = saf1761_otg_device_non_isoc_enter, - .start = saf1761_otg_device_non_isoc_start, -}; - -/*------------------------------------------------------------------------* - * saf1761_otg device side isochronous support - *------------------------------------------------------------------------*/ -static void -saf1761_otg_device_isoc_open(struct usb_xfer *xfer) -{ - return; -} - -static void -saf1761_otg_device_isoc_close(struct usb_xfer *xfer) -{ - saf1761_otg_device_done(xfer, USB_ERR_CANCELLED); -} - -static void -saf1761_otg_device_isoc_enter(struct usb_xfer *xfer) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); - uint32_t nframes; - - DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", - xfer, xfer->endpoint->isoc_next, xfer->nframes); - - /* get the current frame index - we don't need the high bits */ - - nframes = SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM); - - if (usbd_xfer_get_isochronous_start_frame( - xfer, nframes, 0, 1, SOTG_FRAME_NUM_SOFR_MASK, NULL)) - DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); - - /* setup TDs */ - saf1761_otg_setup_standard_chain(xfer); -} - -static void -saf1761_otg_device_isoc_start(struct usb_xfer *xfer) -{ - /* start TD chain */ - saf1761_otg_start_standard_chain(xfer); -} - -static const struct usb_pipe_methods saf1761_otg_device_isoc_methods = -{ - .open = saf1761_otg_device_isoc_open, - .close = saf1761_otg_device_isoc_close, - .enter = saf1761_otg_device_isoc_enter, - .start = saf1761_otg_device_isoc_start, -}; - -/*------------------------------------------------------------------------* - * saf1761_otg host side isochronous support - *------------------------------------------------------------------------*/ -static void -saf1761_otg_host_isoc_open(struct usb_xfer *xfer) -{ - return; -} - -static void -saf1761_otg_host_isoc_close(struct usb_xfer *xfer) -{ - saf1761_otg_device_done(xfer, USB_ERR_CANCELLED); -} - -static void -saf1761_otg_host_isoc_enter(struct usb_xfer *xfer) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(xfer->xroot->bus); - uint32_t nframes; - - DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", - xfer, xfer->endpoint->isoc_next, xfer->nframes); - - /* get the current frame index - we don't need the high bits */ - - nframes = (SAF1761_READ_LE_4(sc, SOTG_FRINDEX) & SOTG_FRINDEX_MASK) >> 3; - - if (usbd_xfer_get_isochronous_start_frame( - xfer, nframes, 0, 1, SOTG_FRINDEX_MASK >> 3, NULL)) - DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); - - /* setup TDs */ - saf1761_otg_setup_standard_chain(xfer); -} - -static void -saf1761_otg_host_isoc_start(struct usb_xfer *xfer) -{ - /* start TD chain */ - saf1761_otg_start_standard_chain(xfer); -} - -static const struct usb_pipe_methods saf1761_otg_host_isoc_methods = -{ - .open = saf1761_otg_host_isoc_open, - .close = saf1761_otg_host_isoc_close, - .enter = saf1761_otg_host_isoc_enter, - .start = saf1761_otg_host_isoc_start, -}; - -/*------------------------------------------------------------------------* - * saf1761_otg root control support - *------------------------------------------------------------------------* - * Simulate a hardware HUB by handling all the necessary requests. - *------------------------------------------------------------------------*/ -#define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) } - -static const struct usb_device_descriptor saf1761_otg_devd = { - .bLength = sizeof(struct usb_device_descriptor), - .bDescriptorType = UDESC_DEVICE, - HSETW(.idVendor, 0x04cc), - HSETW(.idProduct, 0x1761), - .bcdUSB = {0x00, 0x02}, - .bDeviceClass = UDCLASS_HUB, - .bDeviceSubClass = UDSUBCLASS_HUB, - .bDeviceProtocol = UDPROTO_FSHUB, - .bMaxPacketSize = 64, - .bcdDevice = {0x00, 0x01}, - .iManufacturer = 1, - .iProduct = 2, - .bNumConfigurations = 1, -}; - -static const struct usb_device_qualifier saf1761_otg_odevd = { - .bLength = sizeof(struct usb_device_qualifier), - .bDescriptorType = UDESC_DEVICE_QUALIFIER, - .bcdUSB = {0x00, 0x02}, - .bDeviceClass = UDCLASS_HUB, - .bDeviceSubClass = UDSUBCLASS_HUB, - .bDeviceProtocol = UDPROTO_FSHUB, - .bMaxPacketSize0 = 0, - .bNumConfigurations = 0, -}; - -static const struct saf1761_otg_config_desc saf1761_otg_confd = { - .confd = { - .bLength = sizeof(struct usb_config_descriptor), - .bDescriptorType = UDESC_CONFIG, - .wTotalLength[0] = sizeof(saf1761_otg_confd), - .bNumInterface = 1, - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = UC_SELF_POWERED, - .bMaxPower = 0, - }, - .ifcd = { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = UDESC_INTERFACE, - .bNumEndpoints = 1, - .bInterfaceClass = UICLASS_HUB, - .bInterfaceSubClass = UISUBCLASS_HUB, - .bInterfaceProtocol = 0, - }, - - .endpd = { - .bLength = sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = UDESC_ENDPOINT, - .bEndpointAddress = (UE_DIR_IN | SAF1761_OTG_INTR_ENDPT), - .bmAttributes = UE_INTERRUPT, - .wMaxPacketSize[0] = 8, - .bInterval = 255, - }, -}; - -static const struct usb_hub_descriptor_min saf1761_otg_hubd = { - .bDescLength = sizeof(saf1761_otg_hubd), - .bDescriptorType = UDESC_HUB, - .bNbrPorts = SOTG_NUM_PORTS, - HSETW(.wHubCharacteristics, (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL)), - .bPwrOn2PwrGood = 50, - .bHubContrCurrent = 0, - .DeviceRemovable = {0}, /* port is removable */ -}; - -#define STRING_VENDOR \ - "N\0X\0P" - -#define STRING_PRODUCT \ - "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B" - -USB_MAKE_STRING_DESC(STRING_VENDOR, saf1761_otg_vendor); -USB_MAKE_STRING_DESC(STRING_PRODUCT, saf1761_otg_product); - -static usb_error_t -saf1761_otg_roothub_exec(struct usb_device *udev, - struct usb_device_request *req, const void **pptr, uint16_t *plength) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(udev->bus); - const void *ptr; - uint16_t len; - uint16_t value; - uint16_t index; - uint32_t temp; - uint32_t i; - usb_error_t err; - - USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); - - /* buffer reset */ - ptr = (const void *)&sc->sc_hub_temp; - len = 0; - err = 0; - - value = UGETW(req->wValue); - index = UGETW(req->wIndex); - - /* demultiplex the control request */ - - switch (req->bmRequestType) { - case UT_READ_DEVICE: - switch (req->bRequest) { - case UR_GET_DESCRIPTOR: - goto tr_handle_get_descriptor; - case UR_GET_CONFIG: - goto tr_handle_get_config; - case UR_GET_STATUS: - goto tr_handle_get_status; - default: - goto tr_stalled; - } - break; - - case UT_WRITE_DEVICE: - switch (req->bRequest) { - case UR_SET_ADDRESS: - goto tr_handle_set_address; - case UR_SET_CONFIG: - goto tr_handle_set_config; - case UR_CLEAR_FEATURE: - goto tr_valid; /* nop */ - case UR_SET_DESCRIPTOR: - goto tr_valid; /* nop */ - case UR_SET_FEATURE: - default: - goto tr_stalled; - } - break; - - case UT_WRITE_ENDPOINT: - switch (req->bRequest) { - case UR_CLEAR_FEATURE: - switch (UGETW(req->wValue)) { - case UF_ENDPOINT_HALT: - goto tr_handle_clear_halt; - case UF_DEVICE_REMOTE_WAKEUP: - goto tr_handle_clear_wakeup; - default: - goto tr_stalled; - } - break; - case UR_SET_FEATURE: - switch (UGETW(req->wValue)) { - case UF_ENDPOINT_HALT: - goto tr_handle_set_halt; - case UF_DEVICE_REMOTE_WAKEUP: - goto tr_handle_set_wakeup; - default: - goto tr_stalled; - } - break; - case UR_SYNCH_FRAME: - goto tr_valid; /* nop */ - default: - goto tr_stalled; - } - break; - - case UT_READ_ENDPOINT: - switch (req->bRequest) { - case UR_GET_STATUS: - goto tr_handle_get_ep_status; - default: - goto tr_stalled; - } - break; - - case UT_WRITE_INTERFACE: - switch (req->bRequest) { - case UR_SET_INTERFACE: - goto tr_handle_set_interface; - case UR_CLEAR_FEATURE: - goto tr_valid; /* nop */ - case UR_SET_FEATURE: - default: - goto tr_stalled; - } - break; - - case UT_READ_INTERFACE: - switch (req->bRequest) { - case UR_GET_INTERFACE: - goto tr_handle_get_interface; - case UR_GET_STATUS: - goto tr_handle_get_iface_status; - default: - goto tr_stalled; - } - break; - - case UT_WRITE_CLASS_INTERFACE: - case UT_WRITE_VENDOR_INTERFACE: - /* XXX forward */ - break; - - case UT_READ_CLASS_INTERFACE: - case UT_READ_VENDOR_INTERFACE: - /* XXX forward */ - break; - - case UT_WRITE_CLASS_DEVICE: - switch (req->bRequest) { - case UR_CLEAR_FEATURE: - goto tr_valid; - case UR_SET_DESCRIPTOR: - case UR_SET_FEATURE: - break; - default: - goto tr_stalled; - } - break; - - case UT_WRITE_CLASS_OTHER: - switch (req->bRequest) { - case UR_CLEAR_FEATURE: - if (index == SOTG_HOST_PORT_NUM) - goto tr_handle_clear_port_feature_host; - else if (index == SOTG_DEVICE_PORT_NUM) - goto tr_handle_clear_port_feature_device; - else - goto tr_stalled; - case UR_SET_FEATURE: - if (index == SOTG_HOST_PORT_NUM) - goto tr_handle_set_port_feature_host; - else if (index == SOTG_DEVICE_PORT_NUM) - goto tr_handle_set_port_feature_device; - else - goto tr_stalled; - case UR_CLEAR_TT_BUFFER: - case UR_RESET_TT: - case UR_STOP_TT: - goto tr_valid; - - default: - goto tr_stalled; - } - break; - - case UT_READ_CLASS_OTHER: - switch (req->bRequest) { - case UR_GET_TT_STATE: - goto tr_handle_get_tt_state; - case UR_GET_STATUS: - if (index == SOTG_HOST_PORT_NUM) - goto tr_handle_get_port_status_host; - else if (index == SOTG_DEVICE_PORT_NUM) - goto tr_handle_get_port_status_device; - else - goto tr_stalled; - default: - goto tr_stalled; - } - break; - - case UT_READ_CLASS_DEVICE: - switch (req->bRequest) { - case UR_GET_DESCRIPTOR: - goto tr_handle_get_class_descriptor; - case UR_GET_STATUS: - goto tr_handle_get_class_status; - - default: - goto tr_stalled; - } - break; - default: - goto tr_stalled; - } - goto tr_valid; - -tr_handle_get_descriptor: - switch (value >> 8) { - case UDESC_DEVICE: - if (value & 0xff) - goto tr_stalled; - len = sizeof(saf1761_otg_devd); - ptr = (const void *)&saf1761_otg_devd; - goto tr_valid; - case UDESC_DEVICE_QUALIFIER: - if (value & 0xff) - goto tr_stalled; - len = sizeof(saf1761_otg_odevd); - ptr = (const void *)&saf1761_otg_odevd; - goto tr_valid; - case UDESC_CONFIG: - if (value & 0xff) - goto tr_stalled; - len = sizeof(saf1761_otg_confd); - ptr = (const void *)&saf1761_otg_confd; - goto tr_valid; - case UDESC_STRING: - switch (value & 0xff) { - case 0: /* Language table */ - len = sizeof(usb_string_lang_en); - ptr = (const void *)&usb_string_lang_en; - goto tr_valid; - - case 1: /* Vendor */ - len = sizeof(saf1761_otg_vendor); - ptr = (const void *)&saf1761_otg_vendor; - goto tr_valid; - - case 2: /* Product */ - len = sizeof(saf1761_otg_product); - ptr = (const void *)&saf1761_otg_product; - goto tr_valid; - default: - break; - } - break; - default: - goto tr_stalled; - } - goto tr_stalled; - -tr_handle_get_config: - len = 1; - sc->sc_hub_temp.wValue[0] = sc->sc_conf; - goto tr_valid; - -tr_handle_get_status: - len = 2; - USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED); - goto tr_valid; - -tr_handle_set_address: - if (value & 0xFF00) - goto tr_stalled; - - sc->sc_rt_addr = value; - goto tr_valid; - -tr_handle_set_config: - if (value >= 2) - goto tr_stalled; - sc->sc_conf = value; - goto tr_valid; - -tr_handle_get_interface: - len = 1; - sc->sc_hub_temp.wValue[0] = 0; - goto tr_valid; - -tr_handle_get_tt_state: -tr_handle_get_class_status: -tr_handle_get_iface_status: -tr_handle_get_ep_status: - len = 2; - USETW(sc->sc_hub_temp.wValue, 0); - goto tr_valid; - -tr_handle_set_halt: -tr_handle_set_interface: -tr_handle_set_wakeup: -tr_handle_clear_wakeup: -tr_handle_clear_halt: - goto tr_valid; - -tr_handle_clear_port_feature_device: - DPRINTFN(9, "UR_CLEAR_FEATURE on port %d\n", index); - - switch (value) { - case UHF_PORT_SUSPEND: - saf1761_otg_wakeup_peer(sc); - break; - - case UHF_PORT_ENABLE: - sc->sc_flags.port_enabled = 0; - break; - - case UHF_PORT_TEST: - case UHF_PORT_INDICATOR: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_OVER_CURRENT: - case UHF_C_PORT_RESET: - /* nops */ - break; - case UHF_PORT_POWER: - sc->sc_flags.port_powered = 0; - saf1761_otg_pull_down(sc); - break; - case UHF_C_PORT_CONNECTION: - sc->sc_flags.change_connect = 0; - break; - case UHF_C_PORT_SUSPEND: - sc->sc_flags.change_suspend = 0; - break; - default: - err = USB_ERR_IOERROR; - goto tr_valid; - } - goto tr_valid; - -tr_handle_clear_port_feature_host: - DPRINTFN(9, "UR_CLEAR_FEATURE on port %d\n", index); - - temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1); - - switch (value) { - case UHF_PORT_ENABLE: - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PED); - break; - case UHF_PORT_SUSPEND: - if ((temp & SOTG_PORTSC1_SUSP) && (!(temp & SOTG_PORTSC1_FPR))) - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_FPR); - - /* wait 20ms for resume sequence to complete */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50); - - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~(SOTG_PORTSC1_SUSP | - SOTG_PORTSC1_FPR | SOTG_PORTSC1_LS /* High Speed */ )); - - /* 4ms settle time */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 250); - break; - case UHF_PORT_INDICATOR: - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PIC); - break; - case UHF_PORT_TEST: - case UHF_C_PORT_ENABLE: - case UHF_C_PORT_OVER_CURRENT: - case UHF_C_PORT_RESET: - case UHF_C_PORT_SUSPEND: - /* NOPs */ - break; - case UHF_PORT_POWER: - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_PP); - break; - case UHF_C_PORT_CONNECTION: - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp & ~SOTG_PORTSC1_ECSC); - break; - default: - err = USB_ERR_IOERROR; - goto tr_valid; - } - goto tr_valid; - -tr_handle_set_port_feature_device: - DPRINTFN(9, "UR_SET_FEATURE on port %d\n", index); - - switch (value) { - case UHF_PORT_ENABLE: - sc->sc_flags.port_enabled = 1; - break; - case UHF_PORT_SUSPEND: - case UHF_PORT_RESET: - case UHF_PORT_TEST: - case UHF_PORT_INDICATOR: - /* nops */ - break; - case UHF_PORT_POWER: - sc->sc_flags.port_powered = 1; - break; - default: - err = USB_ERR_IOERROR; - goto tr_valid; - } - goto tr_valid; - -tr_handle_set_port_feature_host: - DPRINTFN(9, "UR_SET_FEATURE on port %d\n", index); - - temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1); - - switch (value) { - case UHF_PORT_ENABLE: - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PED); - break; - case UHF_PORT_SUSPEND: - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_SUSP); - break; - case UHF_PORT_RESET: - DPRINTFN(6, "reset port %d\n", index); - - /* Start reset sequence. */ - temp &= ~(SOTG_PORTSC1_PED | SOTG_PORTSC1_PR); - - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PR); - - /* Wait for reset to complete. */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, - USB_MS_TO_TICKS(usb_port_root_reset_delay)); - - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp); - - /* Wait for HC to complete reset. */ - usb_pause_mtx(&sc->sc_bus.bus_mtx, USB_MS_TO_TICKS(2)); - - temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1); - - DPRINTF("After reset, status=0x%08x\n", temp); - if (temp & SOTG_PORTSC1_PR) { - device_printf(sc->sc_bus.bdev, "port reset timeout\n"); - err = USB_ERR_TIMEOUT; - goto tr_valid; - } - if (!(temp & SOTG_PORTSC1_PED)) { - /* Not a high speed device, give up ownership.*/ - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PO); - break; - } - sc->sc_isreset = 1; - DPRINTF("port %d reset, status = 0x%08x\n", index, temp); - break; - case UHF_PORT_POWER: - DPRINTFN(3, "set port power %d\n", index); - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PP); - break; - - case UHF_PORT_TEST: - DPRINTFN(3, "set port test %d\n", index); - break; - - case UHF_PORT_INDICATOR: - DPRINTFN(3, "set port ind %d\n", index); - SAF1761_WRITE_LE_4(sc, SOTG_PORTSC1, temp | SOTG_PORTSC1_PIC); - break; - default: - err = USB_ERR_IOERROR; - goto tr_valid; - } - goto tr_valid; - -tr_handle_get_port_status_device: - - DPRINTFN(9, "UR_GET_PORT_STATUS on port %d\n", index); - - if (sc->sc_flags.status_vbus) { - saf1761_otg_pull_up(sc); - } else { - saf1761_otg_pull_down(sc); - } - - /* Select FULL-speed and Device Side Mode */ - - value = UPS_PORT_MODE_DEVICE; - - if (sc->sc_flags.port_powered) - value |= UPS_PORT_POWER; - - if (sc->sc_flags.port_enabled) - value |= UPS_PORT_ENABLED; - - if (sc->sc_flags.status_vbus && - sc->sc_flags.status_bus_reset) - value |= UPS_CURRENT_CONNECT_STATUS; - - if (sc->sc_flags.status_suspend) - value |= UPS_SUSPEND; - - USETW(sc->sc_hub_temp.ps.wPortStatus, value); - - value = 0; - - if (sc->sc_flags.change_connect) - value |= UPS_C_CONNECT_STATUS; - - if (sc->sc_flags.change_suspend) - value |= UPS_C_SUSPEND; - - USETW(sc->sc_hub_temp.ps.wPortChange, value); - len = sizeof(sc->sc_hub_temp.ps); - goto tr_valid; - -tr_handle_get_port_status_host: - - temp = SAF1761_READ_LE_4(sc, SOTG_PORTSC1); - - DPRINTFN(9, "UR_GET_PORT_STATUS on port %d = 0x%08x\n", index, temp); - - i = UPS_HIGH_SPEED; - - if (temp & SOTG_PORTSC1_ECCS) - i |= UPS_CURRENT_CONNECT_STATUS; - if (temp & SOTG_PORTSC1_PED) - i |= UPS_PORT_ENABLED; - if ((temp & SOTG_PORTSC1_SUSP) && !(temp & SOTG_PORTSC1_FPR)) - i |= UPS_SUSPEND; - if (temp & SOTG_PORTSC1_PR) - i |= UPS_RESET; - if (temp & SOTG_PORTSC1_PP) - i |= UPS_PORT_POWER; - - USETW(sc->sc_hub_temp.ps.wPortStatus, i); - i = 0; - - if (temp & SOTG_PORTSC1_ECSC) - i |= UPS_C_CONNECT_STATUS; - if (temp & SOTG_PORTSC1_FPR) - i |= UPS_C_SUSPEND; - if (sc->sc_isreset) - i |= UPS_C_PORT_RESET; - USETW(sc->sc_hub_temp.ps.wPortChange, i); - len = sizeof(sc->sc_hub_temp.ps); - goto tr_valid; - -tr_handle_get_class_descriptor: - if (value & 0xFF) - goto tr_stalled; - ptr = (const void *)&saf1761_otg_hubd; - len = sizeof(saf1761_otg_hubd); - goto tr_valid; - -tr_stalled: - err = USB_ERR_STALLED; -tr_valid: - *plength = len; - *pptr = ptr; - return (err); -} - -static void -saf1761_otg_xfer_setup(struct usb_setup_params *parm) -{ - struct saf1761_otg_softc *sc; - struct usb_xfer *xfer; - void *last_obj; - uint32_t dw1; - uint32_t ntd; - uint32_t n; - uint8_t ep_no; - uint8_t ep_type; - - sc = SAF1761_OTG_BUS2SC(parm->udev->bus); - xfer = parm->curr_xfer; - - /* - * NOTE: This driver does not use any of the parameters that - * are computed from the following values. Just set some - * reasonable dummies: - */ - parm->hc_max_packet_size = 0x500; - parm->hc_max_packet_count = 1; - parm->hc_max_frame_size = 0x500; - - usbd_transfer_setup_sub(parm); - - /* - * Compute maximum number of TDs: - */ - ep_type = (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE); - - if (ep_type == UE_CONTROL) { - ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ; - - } else { - ntd = xfer->nframes + 1 /* SYNC */ ; - } - - /* - * check if "usbd_transfer_setup_sub" set an error - */ - if (parm->err) - return; - - /* - * allocate transfer descriptors - */ - last_obj = NULL; - - ep_no = xfer->endpointno & UE_ADDR; - - /* - * Check profile stuff - */ - if (parm->udev->flags.usb_mode == USB_MODE_DEVICE) { - const struct usb_hw_ep_profile *pf; - - saf1761_otg_get_hw_ep_profile(parm->udev, &pf, ep_no); - - if (pf == NULL) { - /* should not happen */ - parm->err = USB_ERR_INVAL; - return; - } - } - - dw1 = (xfer->address << 3) | (ep_type << 12); - - switch (parm->udev->speed) { - case USB_SPEED_FULL: - case USB_SPEED_LOW: - /* check if root HUB port is running High Speed */ - if (parm->udev->parent_hs_hub != NULL) { - dw1 |= SOTG_PTD_DW1_ENABLE_SPLIT; - dw1 |= (parm->udev->hs_port_no << 18); - dw1 |= (parm->udev->hs_hub_addr << 25); - if (parm->udev->speed == USB_SPEED_LOW) - dw1 |= (1 << 17); - } - break; - default: - break; - } - - /* align data */ - parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); - - for (n = 0; n != ntd; n++) { - struct saf1761_otg_td *td; - - if (parm->buf) { - td = USB_ADD_BYTES(parm->buf, parm->size[0]); - - /* init TD */ - td->max_packet_size = xfer->max_packet_size; - td->ep_index = ep_no; - td->ep_type = ep_type; - td->dw1_value = dw1; - td->uframe = 0; - - if (ep_type == UE_INTERRUPT) { - if (xfer->interval > 32) - td->interval = (32 / 2) << 3; - else - td->interval = (xfer->interval / 2) << 3; - } else { - td->interval = 0; - } - td->obj_next = last_obj; - - last_obj = td; - } - parm->size[0] += sizeof(*td); - } - - xfer->td_start[0] = last_obj; -} - -static void -saf1761_otg_xfer_unsetup(struct usb_xfer *xfer) -{ -} - -static void -saf1761_otg_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, - struct usb_endpoint *ep) -{ - uint16_t mps; - - DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d\n", - ep, udev->address, - edesc->bEndpointAddress, udev->flags.usb_mode); - - if (udev->parent_hub == NULL) { - /* root HUB has special endpoint handling */ - return; - } - - /* Verify wMaxPacketSize */ - mps = UGETW(edesc->wMaxPacketSize); - if (udev->speed == USB_SPEED_HIGH) { - if ((mps >> 11) & 3) { - DPRINTF("A packet multiplier different from " - "1 is not supported\n"); - return; - } - } - if (mps > SOTG_HS_MAX_PACKET_SIZE) { - DPRINTF("Packet size %d bigger than %d\n", - (int)mps, SOTG_HS_MAX_PACKET_SIZE); - return; - } - if (udev->flags.usb_mode == USB_MODE_DEVICE) { - if (udev->speed != USB_SPEED_FULL && - udev->speed != USB_SPEED_HIGH) { - /* not supported */ - return; - } - switch (edesc->bmAttributes & UE_XFERTYPE) { - case UE_ISOCHRONOUS: - ep->methods = &saf1761_otg_device_isoc_methods; - break; - default: - ep->methods = &saf1761_otg_non_isoc_methods; - break; - } - } else { - switch (edesc->bmAttributes & UE_XFERTYPE) { - case UE_ISOCHRONOUS: - ep->methods = &saf1761_otg_host_isoc_methods; - break; - default: - ep->methods = &saf1761_otg_non_isoc_methods; - break; - } - } -} - -static void -saf1761_otg_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) -{ - struct saf1761_otg_softc *sc = SAF1761_OTG_BUS2SC(bus); - - switch (state) { - case USB_HW_POWER_SUSPEND: - saf1761_otg_suspend(sc); - break; - case USB_HW_POWER_SHUTDOWN: - saf1761_otg_uninit(sc); - break; - case USB_HW_POWER_RESUME: - saf1761_otg_resume(sc); - break; - default: - break; - } -} - -static void -saf1761_otg_device_resume(struct usb_device *udev) -{ - struct saf1761_otg_softc *sc; - struct saf1761_otg_td *td; - struct usb_xfer *xfer; - uint8_t x; - - DPRINTF("\n"); - - if (udev->flags.usb_mode != USB_MODE_HOST) - return; - - sc = SAF1761_OTG_BUS2SC(udev->bus); - - USB_BUS_LOCK(&sc->sc_bus); - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - if (xfer->xroot->udev != udev) - continue; - - td = xfer->td_transfer_cache; - if (td == NULL || td->channel >= SOTG_HOST_CHANNEL_MAX) - continue; - - switch (td->ep_type) { - case UE_INTERRUPT: - x = td->channel - 32; - sc->sc_host_intr_suspend_map &= ~(1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, - (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); - break; - case UE_ISOCHRONOUS: - x = td->channel; - sc->sc_host_isoc_suspend_map &= ~(1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, - (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); - break; - default: - x = td->channel - 64; - sc->sc_host_async_suspend_map &= ~(1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, - (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); - break; - } - } - - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); - USB_BUS_UNLOCK(&sc->sc_bus); - - /* poll all transfers again to restart resumed ones */ - saf1761_otg_do_poll(&sc->sc_bus); -} - -static void -saf1761_otg_device_suspend(struct usb_device *udev) -{ - struct saf1761_otg_softc *sc; - struct saf1761_otg_td *td; - struct usb_xfer *xfer; - uint8_t x; - - DPRINTF("\n"); - - if (udev->flags.usb_mode != USB_MODE_HOST) - return; - - sc = SAF1761_OTG_BUS2SC(udev->bus); - - USB_BUS_LOCK(&sc->sc_bus); - USB_BUS_SPIN_LOCK(&sc->sc_bus); - - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - if (xfer->xroot->udev != udev) - continue; - - td = xfer->td_transfer_cache; - if (td == NULL || td->channel >= SOTG_HOST_CHANNEL_MAX) - continue; - - switch (td->ep_type) { - case UE_INTERRUPT: - x = td->channel - 32; - sc->sc_host_intr_suspend_map |= (1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, - (~sc->sc_host_intr_map) | sc->sc_host_intr_suspend_map); - break; - case UE_ISOCHRONOUS: - x = td->channel; - sc->sc_host_isoc_suspend_map |= (1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, - (~sc->sc_host_isoc_map) | sc->sc_host_isoc_suspend_map); - break; - default: - x = td->channel - 64; - sc->sc_host_async_suspend_map |= (1U << x); - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, - (~sc->sc_host_async_map) | sc->sc_host_async_suspend_map); - break; - } - } - - USB_BUS_SPIN_UNLOCK(&sc->sc_bus); - USB_BUS_UNLOCK(&sc->sc_bus); -} - -static const struct usb_bus_methods saf1761_otg_bus_methods = -{ - .endpoint_init = &saf1761_otg_ep_init, - .xfer_setup = &saf1761_otg_xfer_setup, - .xfer_unsetup = &saf1761_otg_xfer_unsetup, - .get_hw_ep_profile = &saf1761_otg_get_hw_ep_profile, - .xfer_stall = &saf1761_otg_xfer_stall, - .set_stall = &saf1761_otg_set_stall, - .clear_stall = &saf1761_otg_clear_stall, - .roothub_exec = &saf1761_otg_roothub_exec, - .xfer_poll = &saf1761_otg_do_poll, - .set_hw_power_sleep = saf1761_otg_set_hw_power_sleep, - .device_resume = &saf1761_otg_device_resume, - .device_suspend = &saf1761_otg_device_suspend, -}; diff --git a/sys/dev/usb/controller/saf1761_otg.h b/sys/dev/usb/controller/saf1761_otg.h deleted file mode 100644 index 4ab9b629927d..000000000000 --- a/sys/dev/usb/controller/saf1761_otg.h +++ /dev/null @@ -1,175 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2014 Hans Petter Selasky - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 _SAF1761_OTG_H_ -#define _SAF1761_OTG_H_ - -#define SOTG_MAX_DEVICES MIN(USB_MAX_DEVICES, 32) -#define SOTG_FS_MAX_PACKET_SIZE 64 -#define SOTG_HS_MAX_PACKET_SIZE 512 -#define SOTG_NUM_PORTS 2 /* one Device and one Host port */ -#define SOTG_HOST_PORT_NUM 1 -#define SOTG_DEVICE_PORT_NUM 2 -#define SOTG_HOST_CHANNEL_MAX (3 * 32) - -/* Macros used for reading and writing little endian registers */ - -#define SAF1761_READ_LE_4(sc, reg) ({ uint32_t _temp; \ - _temp = bus_space_read_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg)); \ - le32toh(_temp); }) - -#define SAF1761_WRITE_LE_4(sc, reg, data) do { \ - uint32_t _temp = (data); \ - bus_space_write_4((sc)->sc_io_tag, (sc)->sc_io_hdl, (reg), htole32(_temp)); \ -} while (0) - -/* 90ns delay macro */ - -#define SAF1761_90NS_DELAY(sc) do { \ - (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \ - (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \ - (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \ - (void) SAF1761_READ_LE_4(sc, SOTG_VEND_PROD_ID); \ -} while (0) - -struct saf1761_otg_softc; -struct saf1761_otg_td; - -typedef uint8_t (saf1761_otg_cmd_t)(struct saf1761_otg_softc *, struct saf1761_otg_td *td); - -struct saf1761_otg_td { - struct saf1761_otg_td *obj_next; - saf1761_otg_cmd_t *func; - struct usb_page_cache *pc; - uint32_t offset; - uint32_t remainder; - uint32_t dw1_value; - uint16_t max_packet_size; - uint8_t ep_index; - uint8_t ep_type; - uint8_t channel; - uint8_t uframe; - uint8_t interval; - uint8_t error_any:1; - uint8_t error_stall:1; - uint8_t alt_next:1; - uint8_t short_pkt:1; - uint8_t did_stall:1; - uint8_t toggle:1; - uint8_t set_toggle:1; -}; - -struct saf1761_otg_std_temp { - saf1761_otg_cmd_t *func; - struct usb_page_cache *pc; - struct saf1761_otg_td *td; - struct saf1761_otg_td *td_next; - uint32_t len; - uint32_t offset; - uint16_t max_frame_size; - uint8_t short_pkt; - /* - * short_pkt = 0: transfer should be short terminated - * short_pkt = 1: transfer should not be short terminated - */ - uint8_t setup_alt_next; - uint8_t did_stall; -}; - -struct saf1761_otg_config_desc { - struct usb_config_descriptor confd; - struct usb_interface_descriptor ifcd; - struct usb_endpoint_descriptor endpd; -} __packed; - -union saf1761_otg_hub_temp { - uWord wValue; - struct usb_port_status ps; -}; - -struct saf1761_otg_flags { - uint8_t change_connect:1; - uint8_t change_suspend:1; - uint8_t status_suspend:1; /* set if suspended */ - uint8_t status_vbus:1; /* set if present */ - uint8_t status_bus_reset:1; /* set if reset complete */ - uint8_t clocks_off:1; - uint8_t port_powered:1; - uint8_t port_enabled:1; - uint8_t d_pulled_up:1; -}; - -struct saf1761_otg_softc { - struct usb_bus sc_bus; - union saf1761_otg_hub_temp sc_hub_temp; - - struct usb_device *sc_devices[SOTG_MAX_DEVICES]; - struct resource *sc_io_res; - struct resource *sc_irq_res; - void *sc_intr_hdl; - bus_size_t sc_io_size; - bus_space_tag_t sc_io_tag; - bus_space_handle_t sc_io_hdl; - - uint32_t sc_host_async_busy_map[2]; - uint32_t sc_host_async_map; - uint32_t sc_host_async_suspend_map; - uint32_t sc_host_intr_busy_map[2]; - uint32_t sc_host_intr_map; - uint32_t sc_host_intr_suspend_map; - uint32_t sc_host_isoc_busy_map[2]; - uint32_t sc_host_isoc_map; - uint32_t sc_host_isoc_suspend_map; - uint32_t sc_intr_enable; /* enabled interrupts */ - uint32_t sc_hw_mode; /* hardware mode */ - uint32_t sc_interrupt_cfg; /* interrupt configuration */ - uint32_t sc_xfer_complete; - - uint32_t sc_bounce_buffer[1024 / 4]; - - uint8_t sc_rt_addr; /* root HUB address */ - uint8_t sc_dv_addr; /* device address */ - uint8_t sc_conf; /* root HUB config */ - uint8_t sc_isreset; /* host mode */ - - uint8_t sc_hub_idata[1]; - - struct saf1761_otg_flags sc_flags; -}; - -/* prototypes */ - -usb_error_t saf1761_otg_init(struct saf1761_otg_softc *sc); -void saf1761_otg_uninit(struct saf1761_otg_softc *sc); -driver_filter_t saf1761_otg_filter_interrupt; -driver_intr_t saf1761_otg_interrupt; - -#endif /* _SAF1761_OTG_H_ */ diff --git a/sys/dev/usb/controller/saf1761_otg_boot.c b/sys/dev/usb/controller/saf1761_otg_boot.c deleted file mode 100644 index cc9e9a16ef95..000000000000 --- a/sys/dev/usb/controller/saf1761_otg_boot.c +++ /dev/null @@ -1,140 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2014 Hans Petter Selasky - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#include USB_GLOBAL_INCLUDE_FILE - -#include -#include - -static device_probe_t saf1761_otg_fdt_probe; -static device_attach_t saf1761_otg_fdt_attach; -static device_detach_t saf1761_otg_fdt_detach; - -static device_method_t saf1761_otg_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, saf1761_otg_fdt_probe), - DEVMETHOD(device_attach, saf1761_otg_fdt_attach), - DEVMETHOD(device_detach, saf1761_otg_fdt_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - DEVMETHOD_END -}; - -static driver_t saf1761_otg_driver = { - .name = "saf1761otg", - .methods = saf1761_otg_methods, - .size = sizeof(struct saf1761_otg_softc), -}; - -static devclass_t saf1761_otg_devclass; - -DRIVER_MODULE(saf1761otg, pci, saf1761_otg_driver, saf1761_otg_devclass, 0, 0); -MODULE_DEPEND(saf1761otg, usb, 1, 1, 1); - -static int -saf1761_otg_fdt_probe(device_t dev) -{ - if (device_get_unit(dev) != 0) - return (ENXIO); - - device_set_desc(dev, "ISP1761/SAF1761 DCI USB 2.0 Device Controller"); - - return (0); -} - -static int -saf1761_otg_fdt_attach(device_t dev) -{ - struct saf1761_otg_softc *sc = device_get_softc(dev); - int err; - - /* 32-bit data bus */ - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_DATA_BUS_WIDTH; - - /* initialise some bus fields */ - sc->sc_bus.parent = dev; - sc->sc_bus.devices = sc->sc_devices; - sc->sc_bus.devices_max = SOTG_MAX_DEVICES; - sc->sc_bus.dma_bits = 32; - - /* get all DMA memory */ - if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), NULL)) - return (ENOMEM); - - sc->sc_io_res = (void *)1; - sc->sc_io_tag = (void *)1; - sc->sc_io_hdl = (void *)USB_PCI_MEMORY_ADDRESS; - sc->sc_io_size = USB_PCI_MEMORY_SIZE; - - sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); - if (sc->sc_bus.bdev == NULL) - goto error; - - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - device_set_interrupt(dev, &saf1761_otg_filter_interrupt, &saf1761_otg_interrupt, sc); - - err = saf1761_otg_init(sc); - if (err) { - device_printf(dev, "Init failed\n"); - goto error; - } - err = device_probe_and_attach(sc->sc_bus.bdev); - if (err) { - device_printf(dev, "USB probe and attach failed\n"); - goto error; - } - return (0); - -error: - saf1761_otg_fdt_detach(dev); - return (ENXIO); -} - -static int -saf1761_otg_fdt_detach(device_t dev) -{ - struct saf1761_otg_softc *sc = device_get_softc(dev); - - /* during module unload there are lots of children leftover */ - device_delete_children(dev); - - if (sc->sc_irq_res) { - /* - * Only call uninit() after init() - */ - saf1761_otg_uninit(sc); - } - usb_bus_mem_free_all(&sc->sc_bus, NULL); - - return (0); -} diff --git a/sys/dev/usb/controller/saf1761_otg_fdt.c b/sys/dev/usb/controller/saf1761_otg_fdt.c deleted file mode 100644 index 0d7f2933a84e..000000000000 --- a/sys/dev/usb/controller/saf1761_otg_fdt.c +++ /dev/null @@ -1,269 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2014 Hans Petter Selasky - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - */ - -#ifdef USB_GLOBAL_INCLUDE_FILE -#include USB_GLOBAL_INCLUDE_FILE -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#endif /* USB_GLOBAL_INCLUDE_FILE */ - -#include -#include - -static device_probe_t saf1761_otg_fdt_probe; -static device_attach_t saf1761_otg_fdt_attach; -static device_detach_t saf1761_otg_fdt_detach; - -static device_method_t saf1761_otg_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, saf1761_otg_fdt_probe), - DEVMETHOD(device_attach, saf1761_otg_fdt_attach), - DEVMETHOD(device_detach, saf1761_otg_fdt_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - DEVMETHOD_END -}; - -static driver_t saf1761_otg_driver = { - .name = "saf1761otg", - .methods = saf1761_otg_methods, - .size = sizeof(struct saf1761_otg_softc), -}; - -static devclass_t saf1761_otg_devclass; - -DRIVER_MODULE(saf1761otg, simplebus, saf1761_otg_driver, saf1761_otg_devclass, 0, 0); -MODULE_DEPEND(saf1761otg, usb, 1, 1, 1); - -static int -saf1761_otg_fdt_probe(device_t dev) -{ - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "nxp,usb-isp1761")) - return (ENXIO); - - device_set_desc(dev, "ISP1761/SAF1761 DCI USB 2.0 Device Controller"); - - return (0); -} - -static int -saf1761_otg_fdt_attach(device_t dev) -{ - struct saf1761_otg_softc *sc = device_get_softc(dev); - char param[24]; - int err; - int rid; - - /* get configuration from FDT */ - - /* get bus-width, if any */ - if (OF_getprop(ofw_bus_get_node(dev), "bus-width", - ¶m, sizeof(param)) > 0) { - param[sizeof(param) - 1] = 0; - if (strcmp(param, "32") == 0) - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_DATA_BUS_WIDTH; - } else { - /* assume 32-bit data bus */ - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_DATA_BUS_WIDTH; - } - - /* get analog over-current setting */ - if (OF_getprop(ofw_bus_get_node(dev), "analog-oc", - ¶m, sizeof(param)) > 0) { - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_ANA_DIGI_OC; - } - - /* get DACK polarity */ - if (OF_getprop(ofw_bus_get_node(dev), "dack-polarity", - ¶m, sizeof(param)) > 0) { - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_DACK_POL; - } - - /* get DREQ polarity */ - if (OF_getprop(ofw_bus_get_node(dev), "dreq-polarity", - ¶m, sizeof(param)) > 0) { - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_DREQ_POL; - } - - /* get IRQ polarity */ - if (OF_getprop(ofw_bus_get_node(dev), "int-polarity", - ¶m, sizeof(param)) > 0) { - sc->sc_interrupt_cfg |= SOTG_INTERRUPT_CFG_INTPOL; - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_INTR_POL; - } - - /* get IRQ level triggering */ - if (OF_getprop(ofw_bus_get_node(dev), "int-level", - ¶m, sizeof(param)) > 0) { - sc->sc_interrupt_cfg |= SOTG_INTERRUPT_CFG_INTLVL; - sc->sc_hw_mode |= SOTG_HW_MODE_CTRL_INTR_LEVEL; - } - - /* initialise some bus fields */ - sc->sc_bus.parent = dev; - sc->sc_bus.devices = sc->sc_devices; - sc->sc_bus.devices_max = SOTG_MAX_DEVICES; - sc->sc_bus.dma_bits = 32; - - /* get all DMA memory */ - if (usb_bus_mem_alloc_all(&sc->sc_bus, - USB_GET_DMA_TAG(dev), NULL)) { - return (ENOMEM); - } - rid = 0; - sc->sc_io_res = - bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - - if (sc->sc_io_res == NULL) - goto error; - - sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); - sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); - sc->sc_io_size = rman_get_size(sc->sc_io_res); - - /* try to allocate the HC interrupt first */ - rid = 1; - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->sc_irq_res == NULL) { - /* try to allocate a common IRQ second */ - rid = 0; - sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->sc_irq_res == NULL) - goto error; - } - - sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); - if (sc->sc_bus.bdev == NULL) - goto error; - - device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); - - err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY | INTR_MPSAFE, - &saf1761_otg_filter_interrupt, &saf1761_otg_interrupt, sc, &sc->sc_intr_hdl); - if (err) { - sc->sc_intr_hdl = NULL; - goto error; - } - err = saf1761_otg_init(sc); - if (err) { - device_printf(dev, "Init failed\n"); - goto error; - } - err = device_probe_and_attach(sc->sc_bus.bdev); - if (err) { - device_printf(dev, "USB probe and attach failed\n"); - goto error; - } - return (0); - -error: - saf1761_otg_fdt_detach(dev); - return (ENXIO); -} - -static int -saf1761_otg_fdt_detach(device_t dev) -{ - struct saf1761_otg_softc *sc = device_get_softc(dev); - int err; - - /* during module unload there are lots of children leftover */ - device_delete_children(dev); - - if (sc->sc_irq_res && sc->sc_intr_hdl) { - /* - * Only call uninit() after init() - */ - saf1761_otg_uninit(sc); - - err = bus_teardown_intr(dev, sc->sc_irq_res, - sc->sc_intr_hdl); - sc->sc_intr_hdl = NULL; - } - if (sc->sc_irq_res) { - bus_release_resource(dev, SYS_RES_IRQ, 0, - sc->sc_irq_res); - sc->sc_irq_res = NULL; - } - if (sc->sc_io_res) { - bus_release_resource(dev, SYS_RES_MEMORY, 0, - sc->sc_io_res); - sc->sc_io_res = NULL; - } - usb_bus_mem_free_all(&sc->sc_bus, NULL); - - return (0); -} diff --git a/sys/dev/usb/controller/saf1761_otg_reg.h b/sys/dev/usb/controller/saf1761_otg_reg.h deleted file mode 100644 index 5410cb45ecf1..000000000000 --- a/sys/dev/usb/controller/saf1761_otg_reg.h +++ /dev/null @@ -1,274 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2014 Hans Petter Selasky - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 _SAF1761_OTG_REG_H_ -#define _SAF1761_OTG_REG_H_ - -/* Global registers */ - -#define SOTG_VEND_PROD_ID 0x370 -#define SOTG_VEND_ID(x) ((x) & 0xFFFF) -#define SOTG_PROD_ID(x) (((x) >> 16) & 0xFFFF) -#define SOTG_CTRL_SET_CLR 0x374 -#define SOTG_CTRL_SET(x) ((x) & 0xFFFF) -#define SOTG_CTRL_CLR(x) (((x) << 16) & 0xFFFF0000) -#define SOTG_CTRL_OTG_DISABLE (1 << 10) -#define SOTG_CTRL_OTG_SE0_EN (1 << 9) -#define SOTG_CTRL_BDIS_ACON_EN (1 << 8) -#define SOTG_CTRL_SW_SEL_HC_DC (1 << 7) -#define SOTG_CTRL_VBUS_CHRG (1 << 6) -#define SOTG_CTRL_VBUS_DISCHRG (1 << 5) -#define SOTG_CTRL_VBUS_DRV (1 << 4) -#define SOTG_CTRL_SEL_CP_EXT (1 << 3) -#define SOTG_CTRL_DM_PULL_DOWN (1 << 2) -#define SOTG_CTRL_DP_PULL_DOWN (1 << 1) -#define SOTG_CTRL_DP_PULL_UP (1 << 0) -#define SOTG_STATUS 0x378 -#define SOTG_STATUS_B_SE0_SRP (1 << 8) -#define SOTG_STATUS_B_SESS_END (1 << 7) -#define SOTG_STATUS_RMT_CONN (1 << 4) -#define SOTG_STATUS_ID (1 << 3) -#define SOTG_STATUS_DP_SRP (1 << 2) -#define SOTG_STATUS_A_B_SESS_VLD (1 << 1) -#define SOTG_STATUS_VBUS_VLD (1 << 0) -#define SOTG_IRQ_LATCH_SET_CLR 0x37C -#define SOTG_IRQ_LATCH_SET(x) ((x) & 0xFFFF) -#define SOTG_IRQ_LATCH_CLR(x) (((x) << 16) & 0xFFFF0000) -#define SOTG_IRQ_ENABLE_SET_CLR 0x380 -#define SOTG_IRQ_ENABLE_SET(x) ((x) & 0xFFFF) -#define SOTG_IRQ_ENABLE_CLR(x) (((x) << 16) & 0xFFFF0000) -#define SOTG_IRQ_RISE_SET_CLR 0x384 -#define SOTG_IRQ_RISE_SET(x) ((x) & 0xFFFF) -#define SOTG_IRQ_RISE_CLR(x) (((x) << 16) & 0xFFFF0000) -#define SOTG_IRQ_OTG_TMR_TIMEOUT (1 << 9) -#define SOTG_IRQ_B_SE0_SRP (1 << 8) -#define SOTG_IRQ_B_SESS_END (1 << 7) -#define SOTG_IRQ_BDIS_ACON (1 << 6) -#define SOTG_IRQ_OTG_RESUME (1 << 5) -#define SOTG_IRQ_RMT_CONN (1 << 4) -#define SOTG_IRQ_ID (1 << 3) -#define SOTG_IRQ_DP_SRP (1 << 2) -#define SOTG_IRQ_A_B_SESS_VLD (1 << 1) -#define SOTG_IRQ_VBUS_VLD (1 << 0) -#define SOTG_TIMER_LOW_SET_CLR 0x388 -#define SOTG_TIMER_LOW_SET(x) ((x) & 0xFFFF) -#define SOTG_TIMER_LOW_CLR(x) (((x) << 16) & 0xFFFF0000) -#define SOTG_TIMER_HIGH_SET_CLR 0x38C -#define SOTG_TIMER_HIGH_SET(x) ((x) & 0xFFFF) -#define SOTG_TIMER_HIGH_CLR(x) (((x) << 16) & 0xFFFF0000) -#define SOTG_TIMER_HIGH_START (1U << 15) -#define SOTG_MEMORY_REG 0x33c - -/* Peripheral controller specific registers */ - -#define SOTG_ADDRESS 0x200 -#define SOTG_ADDRESS_ENABLE (1 << 7) -#define SOTG_MODE 0x20C -#define SOTG_MODE_DMACLK_ON (1 << 9) -#define SOTG_MODE_VBUSSTAT (1 << 8) -#define SOTG_MODE_CLKAON (1 << 7) -#define SOTG_MODE_SNDRSU (1 << 6) -#define SOTG_MODE_GOSUSP (1 << 5) -#define SOTG_MODE_SFRESET (1 << 4) -#define SOTG_MODE_GLINTENA (1 << 3) -#define SOTG_MODE_WKUPCS (1 << 2) -#define SOTG_INTERRUPT_CFG 0x210 -#define SOTG_INTERRUPT_CFG_DEBUG_SET (1 << 16) -#define SOTG_INTERRUPT_CFG_CDBGMOD (1 << 6) /* ACK only */ -#define SOTG_INTERRUPT_CFG_DDBGMODIN (1 << 4) /* ACK only */ -#define SOTG_INTERRUPT_CFG_DDBGMODOUT (1 << 2) /* ACK and NYET only */ -#define SOTG_INTERRUPT_CFG_INTLVL (1 << 1) -#define SOTG_INTERRUPT_CFG_INTPOL (1 << 0) -#define SOTG_DCINTERRUPT_EN 0x214 -#define SOTG_HW_MODE_CTRL 0x300 -#define SOTG_HW_MODE_CTRL_ALL_ATX_RESET (1 << 31) -#define SOTG_HW_MODE_CTRL_ANA_DIGI_OC (1 << 15) -#define SOTG_HW_MODE_CTRL_DEV_DMA (1 << 11) -#define SOTG_HW_MODE_CTRL_COMN_INT (1 << 10) -#define SOTG_HW_MODE_CTRL_COMN_DMA (1 << 9) -#define SOTG_HW_MODE_CTRL_DATA_BUS_WIDTH (1 << 8) -#define SOTG_HW_MODE_CTRL_DACK_POL (1 << 6) -#define SOTG_HW_MODE_CTRL_DREQ_POL (1 << 5) -#define SOTG_HW_MODE_CTRL_INTR_POL (1 << 2) -#define SOTG_HW_MODE_CTRL_INTR_LEVEL (1 << 1) -#define SOTG_HW_MODE_CTRL_GLOBAL_INTR_EN (1 << 0) -#define SOTG_OTG_CTRL 0x374 -#define SOTG_EP_INDEX 0x22c -#define SOTG_EP_INDEX_EP0SETUP (1 << 5) -#define SOTG_EP_INDEX_ENDP_INDEX_MASK (15 << 1) -#define SOTG_EP_INDEX_ENDP_INDEX_SHIFT 1 -#define SOTG_EP_INDEX_DIR_IN (1 << 0) -#define SOTG_EP_INDEX_DIR_OUT 0 -#define SOTG_CTRL_FUNC 0x228 -#define SOTG_CTRL_FUNC_CLBUF (1 << 4) -#define SOTG_CTRL_FUNC_VENDP (1 << 3) -#define SOTG_CTRL_FUNC_DSEN (1 << 2) -#define SOTG_CTRL_FUNC_STATUS (1 << 1) -#define SOTG_CTRL_FUNC_STALL (1 << 0) -#define SOTG_DATA_PORT 0x220 -#define SOTG_BUF_LENGTH 0x21C -#define SOTG_BUF_LENGTH_BUFLEN_MASK 0xFFFF -#define SOTG_BUF_LENGTH_FILLED_MASK (3 << 16) -#define SOTG_EP_MAXPACKET 0x204 -#define SOTG_EP_TYPE 0x208 -#define SOTG_EP_TYPE_NOEMPPKT (1 << 4) -#define SOTG_EP_TYPE_ENABLE (1 << 3) -#define SOTG_EP_TYPE_DBLBUF (1 << 2) -#define SOTG_EP_TYPE_EP_TYPE (3 << 0) -#define SOTG_DMA_CMD 0x230 -#define SOTG_DMA_XFER_COUNT 0x234 -#define SOTG_DCDMA_CFG 0x238 -#define SOTG_DMA_HW 0x23C -#define SOTG_DMA_IRQ_REASON 0x250 -#define SOTG_DMA_IRQ_ENABLE 0x254 -#define SOTG_DMA_EP 0x258 -#define SOTG_BURST_COUNTER 0x264 -#define SOTG_DCINTERRUPT 0x218 -#define SOTG_DCINTERRUPT_IEPRX(n) (1 << (10 + (2*(n)))) -#define SOTG_DCINTERRUPT_IEPTX(n) (1 << (11 + (2*(n)))) -#define SOTG_DCINTERRUPT_IEP0SETUP (1 << 8) -#define SOTG_DCINTERRUPT_IEVBUS (1 << 7) -#define SOTG_DCINTERRUPT_IEDMA (1 << 6) -#define SOTG_DCINTERRUPT_IEHS_STA (1 << 5) -#define SOTG_DCINTERRUPT_IERESM (1 << 4) -#define SOTG_DCINTERRUPT_IESUSP (1 << 3) -#define SOTG_DCINTERRUPT_IEPSOF (1 << 2) -#define SOTG_DCINTERRUPT_IESOF (1 << 1) -#define SOTG_DCINTERRUPT_IEBRST (1 << 0) -#define SOTG_DCCHIP_ID 0x270 -#define SOTG_FRAME_NUM 0x274 -#define SOTG_FRAME_NUM_MICROSOFR_MASK 0x3800 -#define SOTG_FRAME_NUM_MICROSOFR_SHIFT 11 -#define SOTG_FRAME_NUM_SOFR_MASK 0x7FF -#define SOTG_DCSCRATCH 0x278 -#define SOTG_UNLOCK_DEVICE 0x27C -#define SOTG_UNLOCK_DEVICE_CODE 0xAA37 -#define SOTG_IRQ_PULSE_WIDTH 0x280 -#define SOTG_TEST_MODE 0x284 -#define SOTG_TEST_MODE_FORCEHS (1 << 7) -#define SOTG_TEST_MODE_FORCEFS (1 << 4) -#define SOTG_TEST_MODE_PRBS (1 << 3) -#define SOTG_TEST_MODE_KSTATE (1 << 2) -#define SOTG_TEST_MODE_JSTATE (1 << 1) -#define SOTG_TEST_MODE_SE0_NAK (1 << 0) - -/* Host controller specific registers */ - -#define SOTG_FRINDEX 0x002c -#define SOTG_FRINDEX_MASK 0x3fff -#define SOTG_CONFIGFLAG 0x0060 -#define SOTG_CONFIGFLAG_ENABLE (1 << 0) -#define SOTG_PORTSC1 0x0064 -#define SOTG_PORTSC1_PIC (3 << 14) -#define SOTG_PORTSC1_PO (1 << 13) -#define SOTG_PORTSC1_PP (1 << 12) -#define SOTG_PORTSC1_LS (3 << 10) -#define SOTG_PORTSC1_PR (1 << 8) -#define SOTG_PORTSC1_SUSP (1 << 7) -#define SOTG_PORTSC1_FPR (1 << 6) -#define SOTG_PORTSC1_PED (1 << 2) -#define SOTG_PORTSC1_ECSC (1 << 1) -#define SOTG_PORTSC1_ECCS (1 << 0) -#define SOTG_PTD_DW0 0 -#define SOTG_PTD_DW0_VALID 1U -#define SOTG_PTD_DW1 4 -#define SOTG_PTD_DW1_ENABLE_SPLIT (1 << 14) -#define SOTG_PTD_DW2 8 -#define SOTG_PTD_DW2_RL (0xf << 25) -#define SOTG_PTD_DW3 12 -#define SOTG_PTD_DW3_NRL (0xf << 19) -#define SOTG_PTD_DW3_ACTIVE (1U << 31) -#define SOTG_PTD_DW3_HALTED (1U << 30) -#define SOTG_PTD_DW3_ERRORS (3U << 28) -#define SOTG_PTD_DW3_CERR_3 (3U << 23) -#define SOTG_PTD_DW3_CERR_2 (2U << 23) /* infinite NAKs */ -#define SOTG_PTD_DW3_CERR_1 (1U << 23) -#define SOTG_PTD_DW3_XFER_COUNT_HS 0x7FFF -#define SOTG_PTD_DW3_XFER_COUNT_SPLIT 0x03FF -#define SOTG_PTD_DW4 16 -#define SOTG_PTD_DW5 20 -#define SOTG_PTD_DW6 24 -#define SOTG_PTD_DW7 28 -#define SOTG_DATA_ADDR(x) (0x1000 + (512 * (x))) -#define SOTG_ASYNC_PTD(x) (0xC00 + ((x) * 32)) -#define SOTG_INTR_PTD(x) (0x800 + ((x) * 32)) -#define SOTG_ISOC_PTD(x) (0x400 + ((x) * 32)) -#define SOTG_PTD(x) (0x400 + ((x) * 32)) -#define SOTG_HC_MEMORY_ADDR(x) (((x) - 0x400) >> 3) -#define SOTG_SW_RESET 0x30C -#define SOTG_SW_RESET_HC (1 << 1) -#define SOTG_SW_RESET_ALL (1 << 0) -#define SOTG_POWER_DOWN 0x354 -#define SOTG_POWER_DOWN_PORT3_PD (1 << 12) -#define SOTG_POWER_DOWN_PORT2_PD (1 << 11) -#define SOTG_POWER_DOWN_VBATDET_PWR (1 << 10) -#define SOTG_POWER_DOWN_BIAS_EN (1 << 5) -#define SOTG_POWER_DOWN_VREG_ON (1 << 4) -#define SOTG_POWER_DOWN_OC3_PWR (1 << 3) -#define SOTG_POWER_DOWN_OC2_PWR (1 << 2) -#define SOTG_POWER_DOWN_OC1_PWR (1 << 1) -#define SOTG_POWER_DOWN_HC_CLK_EN (1 << 0) -#define SOTG_USBCMD 0x20 -#define SOTG_USBCMD_LHCR (1 << 7) -#define SOTG_USBCMD_HCRESET (1 << 1) -#define SOTG_USBCMD_RS (1 << 0) -#define SOTG_HCSCRATCH 0x308 -#define SOTG_HCINTERRUPT 0x310 -#define SOTG_HCINTERRUPT_OTG_IRQ (1 << 10) -#define SOTG_HCINTERRUPT_ISO_IRQ (1 << 9) -#define SOTG_HCINTERRUPT_ALT_IRQ (1 << 8) -#define SOTG_HCINTERRUPT_INT_IRQ (1 << 7) -#define SOTG_HCINTERRUPT_CLKREADY (1 << 6) -#define SOTG_HCINTERRUPT_HCSUSP (1 << 5) -#define SOTG_HCINTERRUPT_DMAEOTINT (1 << 3) -#define SOTG_HCINTERRUPT_SOFITLINT (1 << 1) -#define SOTG_HCINTERRUPT_ENABLE 0x314 -#define SOTG_ATL_PTD_DONE_PTD 0x150 -#define SOTG_ATL_PTD_SKIP_PTD 0x154 -#define SOTG_ATL_PTD_LAST_PTD 0x158 -#define SOTG_INT_PTD_DONE_PTD 0x140 -#define SOTG_INT_PTD_SKIP_PTD 0x144 -#define SOTG_INT_PTD_LAST_PTD 0x148 -#define SOTG_ISO_PTD_DONE_PTD 0x130 -#define SOTG_ISO_PTD_SKIP_PTD 0x134 -#define SOTG_ISO_PTD_LAST_PTD 0x138 -#define SOTG_HCBUFFERSTATUS 0x334 -#define SOTG_HCBUFFERSTATUS_ISO_BUF_FILL (1 << 2) -#define SOTG_HCBUFFERSTATUS_INT_BUF_FILL (1 << 1) -#define SOTG_HCBUFFERSTATUS_ATL_BUF_FILL (1 << 0) -#define SOTG_ISO_IRQ_MASK_OR 0x318 -#define SOTG_INT_IRQ_MASK_OR 0x31C -#define SOTG_ATL_IRQ_MASK_OR 0x320 -#define SOTG_ISO_IRQ_MASK_AND 0x324 -#define SOTG_INT_IRQ_MASK_AND 0x328 -#define SOTG_ATL_IRQ_MASK_AND 0x32C - -#endif /* _SAF1761_OTG_REG_H_ */ diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile index 1a34b221efa0..b4c663551d62 100644 --- a/sys/modules/usb/Makefile +++ b/sys/modules/usb/Makefile @@ -1,114 +1,107 @@ # # $FreeBSD$ # # Copyright (c) 2008 Hans Petter Selasky. All rights reserved. # # 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. # SYSDIR?=${SRCTOP}/sys .include "${SYSDIR}/conf/kern.opts.mk" # # Check for common USB debug flags to pass when building the USB # modules in this directory: # .if defined(USB_DEBUG) MAKE+=" DEBUG_FLAGS+=-DUSB_DEBUG" .endif .if defined(USB_DEBUG) && defined(USB_REQ_DEBUG) MAKE+=" DEBUG_FLAGS+=-DUSB_REQ_DEBUG" .endif # Modules that include binary-only blobs of microcode should be selectable by # MK_SOURCELESS_UCODE option (see below). SUBDIR = usb SUBDIR += ${_dwc_otg} ehci ${_musb} ohci uhci xhci ${_uss820dci} \ - ${_atmegadci} ${_avr32dci} ${_rsu} ${_rsufw} ${_saf1761otg} + ${_atmegadci} ${_avr32dci} ${_rsu} ${_rsufw} SUBDIR += ${_rum} ${_run} ${_runfw} ${_uath} upgt usie ural ${_zyd} ${_urtw} SUBDIR += atp cfumass uhid uhid_snes ukbd ums udbp uep wmt wsp ugold uled \ usbhid SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \ umct umcs umodem umoscom uplcom uslcom uvisor uvscom SUBDIR += cp2112 SUBDIR += udl SUBDIR += uether aue axe axge cdce cdceem cue ${_kue} mos rue smsc udav uhso \ ipheth SUBDIR += muge SUBDIR += ure urndis SUBDIR += usfs umass urio SUBDIR += ${_uacpi} SUBDIR += quirk template SUBDIR += ${_g_audio} ${_g_keyboard} ${_g_modem} ${_g_mouse} .if ${MK_USB_GADGET_EXAMPLES} == "yes" _g_audio= g_audio _g_keyboard= g_keyboard _g_modem= g_modem _g_mouse= g_mouse .endif .if ${MK_SOURCELESS_UCODE} != "no" _rum= rum _uath= uath _zyd= zyd _kue= kue _run= run _rsu= rsu - -.if ${MACHINE_CPUARCH} != "mips" _rsufw= rsufw _runfw= runfw .endif -.endif .if ${MACHINE_CPUARCH} == "amd64" _urtw= urtw .endif .if ${MACHINE_CPUARCH} == "arm" _atmegadci= atmegadci _dwc_otg= dwc_otg _musb= musb _uss820dci= uss820dci .endif .if ${MACHINE_CPUARCH} == "i386" _urtw= urtw .endif .if ${MACHINE_CPUARCH} == "avr32" _avr32dci= avr32dci .endif -.if ${MACHINE_CPUARCH} == "mips" -_saf1761otg= saf1761otg -.endif - .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \ ${MACHINE_CPUARCH} == "i386" _uacpi= uacpi .endif .include diff --git a/sys/modules/usb/saf1761otg/Makefile b/sys/modules/usb/saf1761otg/Makefile deleted file mode 100644 index 446e750f3f61..000000000000 --- a/sys/modules/usb/saf1761otg/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# -# $FreeBSD$ -# -# Copyright (c) 2014 Hans Petter Selasky. All rights reserved. -# -# This software was developed by SRI International and the University of -# Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) -# ("CTSRD"), as part of the DARPA CRASH research programme. -# -# 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. -# - -S= ${SRCTOP}/sys - -.PATH: $S/dev/usb/controller - -KMOD= saf1761otg -SRCS= bus_if.h device_if.h usb_if.h \ - opt_bus.h opt_usb.h ofw_bus_if.h \ - saf1761_otg.c saf1761_otg_fdt.c \ - pci_if.h - -.include