SAMA5 UDPHS: More USB fixes mostly related to byte counts, endpoint configuration, and dma configuration

This commit is contained in:
Gregory Nutt 2013-09-04 13:36:52 -06:00
parent 2d9c62d3ef
commit 75b53ad12b
2 changed files with 59 additions and 19 deletions

View File

@ -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 */

View File

@ -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));