From owner-svn-src-head@FreeBSD.ORG Wed May 28 16:28:23 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 836BE95C; Wed, 28 May 2014 16:28:23 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 64D9C294B; Wed, 28 May 2014 16:28:23 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s4SGSNDV046502; Wed, 28 May 2014 16:28:23 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s4SGSMsH046497; Wed, 28 May 2014 16:28:22 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201405281628.s4SGSMsH046497@svn.freebsd.org> From: Hans Petter Selasky Date: Wed, 28 May 2014 16:28:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r266812 - head/sys/dev/usb/controller X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 May 2014 16:28:23 -0000 Author: hselasky Date: Wed May 28 16:28:22 2014 New Revision: 266812 URL: http://svnweb.freebsd.org/changeset/base/266812 Log: Fixes for ISP/SAF1761 host mode: - Make the USB hardware skip PTDs which are not allocated. - Peek host memory twice. Sometimes the PTD status is incorrectly returned as zero. - Ensure the host channel is always freed when software TD is completing. - Add correct configuration of interrupt polarity and type. - Set CERR to 2 for asynchronous traffic to avoid having to reactivate the PTD when a NAK token is received. - Fix detection of STALL PID. Sponsored by: DARPA, AFRL Modified: head/sys/dev/usb/controller/saf1761_otg.c head/sys/dev/usb/controller/saf1761_otg_fdt.c head/sys/dev/usb/controller/saf1761_otg_reg.h Modified: head/sys/dev/usb/controller/saf1761_otg.c ============================================================================== --- head/sys/dev/usb/controller/saf1761_otg.c Wed May 28 15:24:30 2014 (r266811) +++ head/sys/dev/usb/controller/saf1761_otg.c Wed May 28 16:28:22 2014 (r266812) @@ -252,25 +252,24 @@ saf1761_host_channel_free(struct saf1761 if (td->channel >= SOTG_HOST_CHANNEL_MAX) return; - /* disable channel */ - SAF1761_WRITE_LE_4(sc, SOTG_PTD(td->channel) + SOTG_PTD_DW3, 0); - SAF1761_WRITE_LE_4(sc, SOTG_PTD(td->channel) + SOTG_PTD_DW0, 0); - switch (td->ep_type) { case UE_INTERRUPT: x = td->channel - 32; - sc->sc_host_intr_map &= ~(1 << x); td->channel = SOTG_HOST_CHANNEL_MAX; + sc->sc_host_intr_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, ~sc->sc_host_intr_map); break; case UE_ISOCHRONOUS: x = td->channel; - sc->sc_host_isoc_map &= ~(1 << x); td->channel = SOTG_HOST_CHANNEL_MAX; + sc->sc_host_isoc_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map); break; default: x = td->channel - 64; - sc->sc_host_async_map &= ~(1 << x); td->channel = SOTG_HOST_CHANNEL_MAX; + sc->sc_host_async_map &= ~(1 << x); + SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, ~sc->sc_host_async_map); break; } } @@ -401,19 +400,16 @@ saf1761_host_setup_tx(struct saf1761_otg pdt_addr = SOTG_PTD(td->channel); status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3); + if (status == 0) + status = saf1761_peek_host_memory_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_stall = 1; - td->error_any = 1; - } else if (status & SOTG_PTD_DW3_ERRORS) { td->error_any = 1; } - count = (status & SOTG_PTD_DW3_XFER_COUNT); - - saf1761_host_channel_free(sc, td); goto complete; } if (saf1761_host_channel_alloc(sc, td)) @@ -435,7 +431,7 @@ saf1761_host_setup_tx(struct saf1761_otg 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; + 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; @@ -450,10 +446,14 @@ saf1761_host_setup_tx(struct saf1761_otg 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); + td->toggle = 1; busy: return (1); /* busy */ complete: + saf1761_host_channel_free(sc, td); return (0); /* complete */ } @@ -471,15 +471,16 @@ saf1761_host_bulk_data_rx(struct saf1761 pdt_addr = SOTG_PTD(td->channel); status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3); + if (status == 0) + status = saf1761_peek_host_memory_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_stall = 1; - td->error_any = 1; - goto complete; - } else if (status & SOTG_PTD_DW3_ERRORS) { + if (!(status & SOTG_PTD_DW3_ERRORS)) + td->error_stall = 1; td->error_any = 1; goto complete; } @@ -509,14 +510,13 @@ saf1761_host_bulk_data_rx(struct saf1761 saf1761_read_host_memory(sc, td, count); - saf1761_host_channel_free(sc, td); - /* 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; @@ -536,10 +536,11 @@ saf1761_host_bulk_data_rx(struct saf1761 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; + 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; + 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); @@ -550,9 +551,13 @@ saf1761_host_bulk_data_rx(struct saf1761 (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); busy: return (1); /* busy */ complete: + saf1761_host_channel_free(sc, td); return (0); /* complete */ } @@ -569,25 +574,26 @@ saf1761_host_bulk_data_tx(struct saf1761 pdt_addr = SOTG_PTD(td->channel); status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3); + if (status == 0) + status = saf1761_peek_host_memory_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_stall = 1; - td->error_any = 1; - } else if (status & SOTG_PTD_DW3_ERRORS) { + if (!(status & SOTG_PTD_DW3_ERRORS)) + td->error_stall = 1; td->error_any = 1; + goto complete; } - - saf1761_host_channel_free(sc, td); - /* 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; @@ -616,10 +622,11 @@ saf1761_host_bulk_data_tx(struct saf1761 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; + 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; + 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); @@ -631,10 +638,14 @@ saf1761_host_bulk_data_tx(struct saf1761 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); + td->toggle ^= 1; busy: return (1); /* busy */ complete: + saf1761_host_channel_free(sc, td); return (0); /* complete */ } @@ -652,16 +663,19 @@ saf1761_host_intr_data_rx(struct saf1761 pdt_addr = SOTG_PTD(td->channel); status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3); + if (status == 0) + status = saf1761_peek_host_memory_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_stall = 1; + if (!(status & SOTG_PTD_DW3_ERRORS)) + td->error_stall = 1; td->error_any = 1; goto complete; } - count = (status & SOTG_PTD_DW3_XFER_COUNT); got_short = 0; @@ -688,14 +702,13 @@ saf1761_host_intr_data_rx(struct saf1761 saf1761_read_host_memory(sc, td, count); - saf1761_host_channel_free(sc, td); - /* 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; @@ -719,7 +732,7 @@ saf1761_host_intr_data_rx(struct saf1761 temp = (1U << td->uframe); /* 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; + 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); @@ -733,9 +746,13 @@ saf1761_host_intr_data_rx(struct saf1761 (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); busy: return (1); /* busy */ complete: + saf1761_host_channel_free(sc, td); return (0); /* complete */ } @@ -752,23 +769,27 @@ saf1761_host_intr_data_tx(struct saf1761 pdt_addr = SOTG_PTD(td->channel); status = saf1761_peek_host_memory_le_4(sc, pdt_addr + SOTG_PTD_DW3); + if (status == 0) + status = saf1761_peek_host_memory_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_stall = 1; + if (!(status & SOTG_PTD_DW3_ERRORS)) + td->error_stall = 1; td->error_any = 1; + goto complete; } - saf1761_host_channel_free(sc, td); - /* 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; @@ -801,7 +822,7 @@ saf1761_host_intr_data_tx(struct saf1761 temp = (1U << td->uframe); /* 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; + 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); @@ -816,22 +837,32 @@ saf1761_host_intr_data_tx(struct saf1761 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); + 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) { + /* activate PTD */ + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map); + return (1); /* busy */ } static uint8_t saf1761_host_isoc_data_tx(struct saf1761_otg_softc *sc, struct saf1761_otg_td *td) { + /* activate PTD */ + SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, ~sc->sc_host_isoc_map); + return (1); /* busy */ } @@ -1319,10 +1350,13 @@ saf1761_otg_interrupt(struct saf1761_otg SAF1761_READ_LE_4(sc, SOTG_FRAME_NUM), SAF1761_READ_LE_4(sc, SOTG_FRINDEX)); + (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); + /* update VBUS and ID bits, if any */ - if (status & SOTG_DCINTERRUPT_IEVBUS) { + if (status & SOTG_DCINTERRUPT_IEVBUS) saf1761_otg_update_vbus(sc); - } if (status & SOTG_DCINTERRUPT_IEBRST) { /* unlock device */ @@ -1431,7 +1465,8 @@ saf1761_otg_setup_standard_chain(struct temp.td = NULL; temp.td_next = xfer->td_start[0]; temp.offset = 0; - temp.setup_alt_next = xfer->flags_int.short_frames_ok; + 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); @@ -1732,7 +1767,8 @@ saf1761_otg_standard_done_sub(struct usb } /* Check for short transfer */ if (len > 0) { - if (xfer->flags_int.short_frames_ok) { + if (xfer->flags_int.short_frames_ok || + xfer->flags_int.isochronous_xfr) { /* follow alt next */ if (td->alt_next) { td = td->obj_next; @@ -2048,12 +2084,13 @@ saf1761_otg_init(struct saf1761_otg_soft 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, - SOTG_INTERRUPT_CFG_CDBGMOD | - SOTG_INTERRUPT_CFG_DDBGMODIN | - SOTG_INTERRUPT_CFG_DDBGMODOUT | - sc->sc_interrupt_cfg); + 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, @@ -2099,15 +2136,15 @@ saf1761_otg_init(struct saf1761_otg_soft DPRINTF("USBCMD=0x%08x\n", SAF1761_READ_LE_4(sc, SOTG_USBCMD)); - /* activate all PTDs */ + /* 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 no PTDs */ - SAF1761_WRITE_LE_4(sc, SOTG_ATL_PTD_SKIP_PTD, 0); - SAF1761_WRITE_LE_4(sc, SOTG_INT_PTD_SKIP_PTD, 0); - SAF1761_WRITE_LE_4(sc, SOTG_ISO_PTD_SKIP_PTD, 0); + /* 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, @@ -2115,6 +2152,16 @@ saf1761_otg_init(struct saf1761_otg_soft 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 | Modified: head/sys/dev/usb/controller/saf1761_otg_fdt.c ============================================================================== --- head/sys/dev/usb/controller/saf1761_otg_fdt.c Wed May 28 15:24:30 2014 (r266811) +++ head/sys/dev/usb/controller/saf1761_otg_fdt.c Wed May 28 16:28:22 2014 (r266812) @@ -160,12 +160,14 @@ saf1761_otg_fdt_attach(device_t dev) 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 */ @@ -182,23 +184,30 @@ saf1761_otg_fdt_attach(device_t dev) sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (!sc->sc_io_res) { + 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); - rid = 0; + /* 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) { - goto error; + /* 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)) { + 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_BIO | INTR_MPSAFE, Modified: head/sys/dev/usb/controller/saf1761_otg_reg.h ============================================================================== --- head/sys/dev/usb/controller/saf1761_otg_reg.h Wed May 28 15:24:30 2014 (r266811) +++ head/sys/dev/usb/controller/saf1761_otg_reg.h Wed May 28 16:28:22 2014 (r266812) @@ -84,7 +84,7 @@ #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_START_TMR (1U << 15) +#define SOTG_TIMER_HIGH_START (1U << 15) #define SOTG_MEMORY_REG 0x33c /* Peripheral controller specific registers */ @@ -102,9 +102,9 @@ #define SOTG_MODE_WKUPCS (1 << 2) #define SOTG_INTERRUPT_CFG 0x210 #define SOTG_INTERRUPT_CFG_DEBUG_SET (1 << 16) -#define SOTG_INTERRUPT_CFG_CDBGMOD (3 << 6) -#define SOTG_INTERRUPT_CFG_DDBGMODIN (3 << 4) -#define SOTG_INTERRUPT_CFG_DDBGMODOUT (3 << 2) +#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 @@ -201,11 +201,15 @@ #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 (3U << 23) +#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 0x7FFF #define SOTG_PTD_DW4 16 #define SOTG_PTD_DW5 20 @@ -245,15 +249,24 @@ #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_ */