summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-09-04 13:36:52 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-09-04 13:36:52 -0600
commit64aa98daef383aa85c6abe2e756320e563dbb9f8 (patch)
treed8664d16fb158cef26591dea99bb5621956d5e62 /nuttx
parent8c2e2b96115c5fd5fb1d5e661d2fd96a3ed84906 (diff)
downloadpx4-nuttx-64aa98daef383aa85c6abe2e756320e563dbb9f8.tar.gz
px4-nuttx-64aa98daef383aa85c6abe2e756320e563dbb9f8.tar.bz2
px4-nuttx-64aa98daef383aa85c6abe2e756320e563dbb9f8.zip
SAMA5 UDPHS: More USB fixes mostly related to byte counts, endpoint configuration, and dma configuration
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/arch/arm/src/sama5/chip/sam_udphs.h6
-rw-r--r--nuttx/arch/arm/src/sama5/sam_udphs.c72
2 files changed, 59 insertions, 19 deletions
diff --git a/nuttx/arch/arm/src/sama5/chip/sam_udphs.h b/nuttx/arch/arm/src/sama5/chip/sam_udphs.h
index a05720f27..db1824ed1 100644
--- a/nuttx/arch/arm/src/sama5/chip/sam_udphs.h
+++ b/nuttx/arch/arm/src/sama5/chip/sam_udphs.h
@@ -418,8 +418,8 @@
# define UDPHS_EPTSTA_BUSYBANK_1 (0 << UDPHS_EPTSTA_BUSYBANK_SHIFT) /* 1 busy bank */
# define UDPHS_EPTSTA_BUSYBANK_2 (1 << UDPHS_EPTSTA_BUSYBANK_SHIFT) /* 2 busy banks */
# define UDPHS_EPTSTA_BUSYBANK_3 (2 << UDPHS_EPTSTA_BUSYBANK_SHIFT) /* 3 busy banks */
-#define UDPHS_EPTSTA_BYTECNT_SHIFT (24) /* Bits 24-30: UDPHS Byte Count */
-#define UDPHS_EPTSTA_BYTECNT_MASK (0x7f << UDPHS_EPTSTA_BYTECNT_SHIFT)
+#define UDPHS_EPTSTA_BYTECNT_SHIFT (20) /* Bits 20-30: UDPHS Byte Count */
+#define UDPHS_EPTSTA_BYTECNT_MASK (0x7ff << UDPHS_EPTSTA_BYTECNT_SHIFT)
#define UDPHS_EPTSTA_SHRTPCKT (1 << 31) /* Bit 31: Short Packet */
/* DMA Channel Registers */
@@ -438,7 +438,7 @@
#define UDPHS_DMACONTROL_BURSTLCK (1 << 7) /* Bit 7: Burst Lock Enable */
#define UDPHS_DMACONTROL_BUFLEN_SHIFT (16) /* Bits 16-31: Buffer Byte Length (Write-only) */
#define UDPHS_DMACONTROL_BUFLEN_MASK (0xffff << UDPHS_DMACONTROL_BUFLEN_SHIFT)
-# define UDPHS_DMACONTROL_BUFLEN(n) ((n) << UDPHS_DMACONTROL_BUFLEN_SHIFT)
+# define UDPHS_DMACONTROL_BUFLEN(n) ((uint32_t)(n) << UDPHS_DMACONTROL_BUFLEN_SHIFT)
/* UDPHS DMA Channel Status Register */
diff --git a/nuttx/arch/arm/src/sama5/sam_udphs.c b/nuttx/arch/arm/src/sama5/sam_udphs.c
index fe6d0015d..c63f2a50c 100644
--- a/nuttx/arch/arm/src/sama5/sam_udphs.c
+++ b/nuttx/arch/arm/src/sama5/sam_udphs.c
@@ -980,11 +980,20 @@ static int sam_req_wrdma(struct sam_usbdev_s *priv, struct sam_ep_s *privep,
privreq->inflight = remaining;
}
- /* Single transfer */
+ /* And perform the single DMA transfer.
+ *
+ * 32.6.10.6 Bulk IN or Interrupt IN: Sending a Buffer Using DMA
+ * - END_B_EN: The endpoint can validate the packet (according to the
+ * values programmed in the AUTO_VALID and SHRT_PCKT fields of
+ * UDPHS_EPTCTLx.) ...
+ * - END_BUFFIT: generate an interrupt when the BUFF_COUNT in
+ * UDPHS_DMASTATUSx reaches 0.
+ * - CHANN_ENB: Run and stop at end of buffer
+ */
- sam_dma_single(epno, privreq, UDPHS_DMACONTROL_ENDBEN
- | UDPHS_DMACONTROL_ENDBUFFIT
- | UDPHS_DMACONTROL_CHANNENB);
+ sam_dma_single(epno, privreq,
+ UDPHS_DMACONTROL_ENDBEN | UDPHS_DMACONTROL_ENDBUFFIT |
+ UDPHS_DMACONTROL_CHANNENB);
return OK;
}
@@ -1049,10 +1058,26 @@ static int sam_req_rddma(struct sam_usbdev_s *priv, struct sam_ep_s *privep,
privreq->inflight = remaining;
}
- /* And perform the single DMA transfer */
+ /* And perform the single DMA transfer.
+ *
+ * 32.6.10.12 Bulk OUT or Interrupt OUT: Sending a Buffer Using DMA
+ * - END_B_EN: Can be used for OUT packet truncation (discarding of
+ * unbuffered packet data) at the end of DMA buffer.
+ * - END_BUFFIT: Generate an interrupt when BUFF_COUNT in the
+ * UDPHS_DMASTATUSx register reaches 0.
+ * - END_TR_EN: End of transfer enable, the UDPHS device can put an
+ * end to the current DMA transfer, in case of a short packet.
+ * - END_TR_IT: End of transfer interrupt enable, an interrupt is sent
+ * after the last USB packet has been transferred by the DMA, if the
+ * USB transfer ended with a short packet. (Beneficial when the
+ * receive size is unknown.)
+ * - CHANN_ENB: Run and stop at end of buffer.
+ */
regval = UDPHS_DMACONTROL_ENDBEN | UDPHS_DMACONTROL_ENDBUFFIT |
+ UDPHS_DMACONTROL_ENDTREN | UDPHS_DMACONTROL_ENDTRIT |
UDPHS_DMACONTROL_CHANNENB;
+
sam_dma_single(epno, privreq, regval);
return OK;
}
@@ -2327,6 +2352,7 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
regval = UDPHS_DMACONTROL_ENDTREN | UDPHS_DMACONTROL_ENDTRIT |
UDPHS_DMACONTROL_ENDBEN | UDPHS_DMACONTROL_ENDBUFFIT |
UDPHS_DMACONTROL_CHANNENB;
+
sam_dma_single(epno, privreq, regval);
}
}
@@ -3059,7 +3085,7 @@ sam_ep_reserved(struct sam_usbdev_s *priv, int epno)
}
/****************************************************************************
- * Name: sam_ep_configure
+ * Name: sam_ep_configure_internal
*
* Description:
* This is the internal implementation of the endpoint configuration logic
@@ -3075,17 +3101,23 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
struct sam_usbdev_s *priv;
uintptr_t regaddr;
uint32_t regval;
+ uint16_t maxpacket;
uint8_t epno;
uint8_t eptype;
uint8_t nbtrans;
- uint8_t maxpacket;
bool dirin;
+ uvdbg("len: %02x type: %02x addr: %02x attr: %02x "
+ "maxpacketsize: %02x %02x interval: %02x\n",
+ desc->len, desc->type, desc->addr, desc->attr,
+ desc->mxpacketsize[0], desc->mxpacketsize[1],
+ desc->interval);
+
/* Decode the endpoint descriptor */
epno = USB_EPNO(desc->addr);
dirin = (desc->addr & USB_DIR_MASK) == USB_REQ_DIR_IN;
- eptype = (desc->type & USB_REQ_TYPE_MASK) >> USB_REQ_TYPE_SHIFT;
+ eptype = (desc->attr & USB_EP_ATTR_XFERTYPE_MASK) >> USB_EP_ATTR_XFERTYPE_SHIFT;
maxpacket = GETUINT16(desc->mxpacketsize);
nbtrans = 1;
@@ -3180,7 +3212,7 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
{
regval |= UDPHS_EPTCFG_SIZE_512;
}
- else if (privep->ep.maxpacket <= 1024)
+ else if (maxpacket <= 1024)
{
regval |= UDPHS_EPTCFG_SIZE_1024;
}
@@ -3191,8 +3223,8 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
regval |= UDPHS_EPTCFG_SIZE_8;
}
- regval |= ((uint32_t)dirin << 3) | (eptype << 4) |
- ((privep->bank) << 6) | (nbtrans << 8);
+ regval |= ((uint32_t)dirin << 3) | ((uint32_t)eptype << 4) |
+ ((uint32_t)(privep->bank) << 6) | ((uint32_t)nbtrans << 8);
sam_putreg(regval, regaddr);
/* Verify that the EPT_MAPD flag is set. This flag is set if the
@@ -3206,16 +3238,24 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
return -EINVAL;
}
- /* Enable the endpoint */
+ /* Enable the endpoint. The way that the endpoint is enabled depends of
+ * if the endpoint supports DMA transfers or not.
+ */
- if (eptype == USB_EP_ATTR_XFER_CONTROL)
+ if ((SAM_EPSET_DMA & SAM_EP_BIT(epno)) != 0)
{
- regval = UDPHS_EPTCTL_RXRDYTXKL | UDPHS_EPTCTL_RXSETUP |
- UDPHS_EPTCTL_EPTENABL;
+ /* Select AUTO_VALID so that the hardware will manage RXRDY_TXKL
+ * and TXRDY.
+ */
+
+ regval = UDPHS_EPTCTL_AUTOVALID | UDPHS_EPTCTL_EPTENABL;
}
else
{
- regval = UDPHS_EPTCTL_AUTOVALID | UDPHS_EPTCTL_EPTENABL;
+ /* No DMA... Software will manage RXRDY_TXKL and TXRDY. */
+
+ regval = UDPHS_EPTCTL_RXRDYTXKL | UDPHS_EPTCTL_RXSETUP |
+ UDPHS_EPTCTL_EPTENABL;
}
sam_putreg(regval, SAM_UDPHS_EPTCTLENB(epno));