summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-09-02 16:59:07 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-09-02 16:59:07 -0600
commit45cc20eb38d458e9c24b36a1ac7d8a4d38992e21 (patch)
tree7fb8310b548a7f60b4e71ffb34cd0714d70cbbdb
parentf9fa75622bdc84806e8bcfebde810e7246b3a65d (diff)
downloadpx4-nuttx-45cc20eb38d458e9c24b36a1ac7d8a4d38992e21.tar.gz
px4-nuttx-45cc20eb38d458e9c24b36a1ac7d8a4d38992e21.tar.bz2
px4-nuttx-45cc20eb38d458e9c24b36a1ac7d8a4d38992e21.zip
SAMA5 UDPHS: Changes from initial debug session. Still a long way to go
-rw-r--r--nuttx/arch/arm/src/sama5/sam_udphs.c161
1 files changed, 89 insertions, 72 deletions
diff --git a/nuttx/arch/arm/src/sama5/sam_udphs.c b/nuttx/arch/arm/src/sama5/sam_udphs.c
index 483af21a8..cc1445d9d 100644
--- a/nuttx/arch/arm/src/sama5/sam_udphs.c
+++ b/nuttx/arch/arm/src/sama5/sam_udphs.c
@@ -197,16 +197,17 @@
#define SAM_TRACEINTID_INTERRUPT 0x0018
#define SAM_TRACEINTID_INTSOF 0x0019
#define SAM_TRACEINTID_NOSTDREQ 0x001a
-#define SAM_TRACEINTID_RXRDY 0x001b
-#define SAM_TRACEINTID_RXSETUP 0x001c
-#define SAM_TRACEINTID_SETADDRESS 0x001d
-#define SAM_TRACEINTID_SETCONFIG 0x001e
-#define SAM_TRACEINTID_SETFEATURE 0x001f
-#define SAM_TRACEINTID_STALLSNT 0x0020
-#define SAM_TRACEINTID_SYNCHFRAME 0x0021
-#define SAM_TRACEINTID_TXRDY 0x0022
-#define SAM_TRACEINTID_UPSTRRES 0x0023
-#define SAM_TRACEINTID_WAKEUP 0x0024
+#define SAM_TRACEINTID_PENDING 0x001b
+#define SAM_TRACEINTID_RXRDY 0x001c
+#define SAM_TRACEINTID_RXSETUP 0x001d
+#define SAM_TRACEINTID_SETADDRESS 0x001e
+#define SAM_TRACEINTID_SETCONFIG 0x001f
+#define SAM_TRACEINTID_SETFEATURE 0x0020
+#define SAM_TRACEINTID_STALLSNT 0x0021
+#define SAM_TRACEINTID_SYNCHFRAME 0x0022
+#define SAM_TRACEINTID_TXRDY 0x0023
+#define SAM_TRACEINTID_UPSTRRES 0x0024
+#define SAM_TRACEINTID_WAKEUP 0x0025
/* Ever-present MIN and MAX macros */
@@ -624,6 +625,7 @@ const struct trace_msg_t g_usb_trace_strings_intdecode[] =
TRACE_STR(SAM_TRACEINTID_INTERRUPT),
TRACE_STR(SAM_TRACEINTID_INTSOF),
TRACE_STR(SAM_TRACEINTID_NOSTDREQ),
+ TRACE_STR(SAM_TRACEINTID_PENDING),
TRACE_STR(SAM_TRACEINTID_RXRDY),
TRACE_STR(SAM_TRACEINTID_RXSETUP),
TRACE_STR(SAM_TRACEINTID_SETADDRESS),
@@ -2335,7 +2337,6 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
{
struct sam_ep_s *privep;
- struct sam_req_s *privreq;
uint32_t eptsta;
uint32_t eptype;
uint32_t regval;
@@ -2347,11 +2348,6 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
privep = &priv->eplist[epno];
- /* Get the request from the head of the endpoint request queue */
-
- privreq = sam_rqpeek(privep);
- DEBUGASSERT(privreq);
-
/* Get the endpoint status */
eptsta = sam_getreg(SAM_UDPHS_EPTSTA(epno));
@@ -2585,7 +2581,6 @@ static int sam_udphs_interrupt(int irq, void *context)
struct sam_usbdev_s *priv = &g_udphs;
uint32_t intsta;
- uint32_t ien;
uint32_t pending;
uint32_t regval;
int i;
@@ -2595,8 +2590,8 @@ static int sam_udphs_interrupt(int irq, void *context)
intsta = sam_getreg(SAM_UDPHS_INTSTA);
usbtrace(TRACE_INTENTRY(SAM_TRACEINTID_INTERRUPT), intsta);
- ien = sam_getreg(SAM_UDPHS_IEN);
- pending = intsta & ien;
+ regval = sam_getreg(SAM_UDPHS_IEN);
+ pending = intsta & regval;
/* Handle all pending UDPHS interrupts (and new interrupts that become
* pending)
@@ -2604,7 +2599,7 @@ static int sam_udphs_interrupt(int irq, void *context)
while (pending)
{
- usbtrace(TRACE_INTENTRY(SAM_TRACEINTID_INTERRUPT), intsta);
+ usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_PENDING), (uint16_t)pending);
/* Suspend, treated last */
@@ -2614,7 +2609,7 @@ static int sam_udphs_interrupt(int irq, void *context)
/* Enable wakeup interrupts */
- regval = ien;
+ regval = sam_getreg(SAM_UDPHS_IEN);
regval &= ~UDPHS_INT_DETSUSPD;
regval |= (UDPHS_INT_WAKEUP | UDPHS_INT_ENDOFRSM);
sam_putreg(regval, SAM_UDPHS_IEN);
@@ -2650,24 +2645,40 @@ static int sam_udphs_interrupt(int irq, void *context)
/* Enable suspend interrupts */
- ien &= ~UDPHS_INT_WAKEUP;
- ien |= (UDPHS_INT_ENDOFRSM | UDPHS_INT_DETSUSPD);
- sam_putreg(ien, SAM_UDPHS_IEN);
+ regval = sam_getreg(SAM_UDPHS_IEN);
+ regval &= ~UDPHS_INT_WAKEUP;
+ regval |= (UDPHS_INT_ENDOFRSM | UDPHS_INT_DETSUSPD);
+ sam_putreg(regval, SAM_UDPHS_IEN);
}
- /* Bus reset */
+ /* End of Reset. "Set by hardware when an End Of Reset has been detected
+ * by the UDPHS controller."
+ *
+ * Paragraph 32.6.14.4 From Powered State to Default State (reset)
+ * "After its connection to a USB host, the USB device waits for an
+ * end-of-bus reset. The unmasked flag ENDRESET is set in the
+ * UDPHS_IEN register and an interrupt is triggered.
+ *
+ * "Once the ENDRESET interrupt has been triggered, the device
+ * enters Default State. In this state, the UDPHS software must:
+ *
+ * - Enable the default endpoint, setting the EPT_ENABL flag in
+ * the UDPHS_EPTCTLENB[0] register and, optionally, enabling
+ * the interrupt for endpoint 0 by writing 1 in EPT_0 of the
+ * UDPHS_IEN register. The enumeration then begins by a control
+ * transfer.
+ * - Configure the Interrupt Mask Register which has been reset
+ * by the USB reset detection
+ * - Enable the transceiver.
+ *
+ * "In this state, the EN_UDPHS bit in UDPHS_CTRL register must be
+ * enabled."
+ */
if ((pending & UDPHS_INT_ENDRESET) != 0)
{
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_ENDRESET), (uint16_t)pending);
- /* Clear and enable the suspend interrupt */
-
- sam_putreg(UDPHS_INT_WAKEUP | UDPHS_INT_DETSUSPD, SAM_UDPHS_CLRINT);
-
- ien |= UDPHS_INT_DETSUSPD;
- sam_putreg(ien, SAM_UDPHS_IEN);
-
/* Handle the reset */
sam_reset(priv);
@@ -2689,7 +2700,7 @@ static int sam_udphs_interrupt(int irq, void *context)
/* DMA interrupts */
- if ((pending & UDPHS_INT_DMA_MASK) != 0)
+ else if ((pending & UDPHS_INT_DMA_MASK) != 0)
{
for (i = 1; i <= SAM_UDPHS_NDMACHANNELS; i++)
{
@@ -2703,9 +2714,9 @@ static int sam_udphs_interrupt(int irq, void *context)
/* Endpoint Interrupts */
- if ((pending & UDPHS_INT_EPT_MASK) != 0)
+ else if ((pending & UDPHS_INT_EPT_MASK) != 0)
{
- for (i = 1; i <= SAM_UDPHS_NENDPOINTS; i++)
+ for (i = 0; i < SAM_UDPHS_NENDPOINTS; i++)
{
if ((pending & UDPHS_INT_EPT(i)) != 0)
{
@@ -2718,8 +2729,8 @@ static int sam_udphs_interrupt(int irq, void *context)
/* Re-sample the set of pending interrupts */
intsta = sam_getreg(SAM_UDPHS_INTSTA);
- ien = sam_getreg(SAM_UDPHS_IEN);
- pending = intsta & ien;
+ regval = sam_getreg(SAM_UDPHS_IEN);
+ pending = intsta & regval;
}
usbtrace(TRACE_INTEXIT(SAM_TRACEINTID_INTERRUPT), intsta);
@@ -2977,6 +2988,7 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
const struct usb_epdesc_s *desc)
{
struct sam_usbdev_s *priv;
+ uintptr_t regaddr;
uint32_t regval;
uint8_t epno;
uint8_t eptype;
@@ -3054,55 +3066,58 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
/* Configure the endpoint */
+ regaddr = SAM_UDPHS_EPTCFG(epno);
+ regval = sam_getreg(regaddr) & UDPHS_EPTCFG_MAPD;
+
if (maxpacket <= 8)
{
- regval = UDPHS_EPTCFG_SIZE_8;
+ regval |= UDPHS_EPTCFG_SIZE_8;
}
else if (maxpacket <= 16)
{
- regval = UDPHS_EPTCFG_SIZE_16;
+ regval |= UDPHS_EPTCFG_SIZE_16;
}
else if (maxpacket <= 32)
{
- regval = UDPHS_EPTCFG_SIZE_32;
+ regval |= UDPHS_EPTCFG_SIZE_32;
}
else if (maxpacket <= 64)
{
- regval = UDPHS_EPTCFG_SIZE_64;
+ regval |= UDPHS_EPTCFG_SIZE_64;
}
else if (maxpacket <= 128)
{
- regval = UDPHS_EPTCFG_SIZE_128;
+ regval |= UDPHS_EPTCFG_SIZE_128;
}
else if (maxpacket <= 256)
{
- regval = UDPHS_EPTCFG_SIZE_256;
+ regval |= UDPHS_EPTCFG_SIZE_256;
}
else if (maxpacket <= 512)
{
- regval = UDPHS_EPTCFG_SIZE_512;
+ regval |= UDPHS_EPTCFG_SIZE_512;
}
else if (privep->ep.maxpacket <= 1024)
{
- regval = UDPHS_EPTCFG_SIZE_1024;
+ regval |= UDPHS_EPTCFG_SIZE_1024;
}
else
{
usbtrace(TRACE_DEVERROR(SAM_TRACEERR_BADEPTYPE), eptype);
DEBUGPANIC();
- regval = UDPHS_EPTCFG_SIZE_8;
+ regval |= UDPHS_EPTCFG_SIZE_8;
}
regval |= ((uint32_t)dirin << 3) | (eptype << 4) |
((privep->bank) << 6) | (nbtrans << 8);
- sam_putreg(regval, SAM_UDPHS_EPTCFG(epno));
+ sam_putreg(regval, regaddr);
/* Verify that the EPT_MAPD flag is set. This flag is set if the
* endpoint size and the number of banks are correct compared to
* the FIFO maximum capacity and the maximum number of allowed banks.
*/
- if ((sam_getreg(SAM_UDPHS_EPTCFG(epno)) & UDPHS_EPTCFG_MAPD) == 0)
+ if ((sam_getreg(regaddr) & UDPHS_EPTCFG_MAPD) == 0)
{
usbtrace(TRACE_DEVERROR(SAM_TRACEERR_EPTCFGMAPD), epno);
return -EINVAL;
@@ -3112,16 +3127,16 @@ static int sam_ep_configure_internal(struct sam_ep_s *privep,
if (eptype == USB_EP_ATTR_XFER_CONTROL)
{
- sam_putreg(UDPHS_EPTCTL_RXRDYTXKL | UDPHS_EPTCTL_RXSETUP |
- UDPHS_EPTCTL_EPTENABL,
- SAM_UDPHS_EPTCTLENB(epno));
+ regval = UDPHS_EPTCTL_RXRDYTXKL | UDPHS_EPTCTL_RXSETUP |
+ UDPHS_EPTCTL_EPTENABL;
}
else
{
- sam_putreg(UDPHS_EPTCTL_AUTOVALID | UDPHS_EPTCTL_EPTENABL,
- SAM_UDPHS_EPTCTLENB(epno));
+ regval = UDPHS_EPTCTL_AUTOVALID | UDPHS_EPTCTL_EPTENABL;
}
+ sam_putreg(regval, SAM_UDPHS_EPTCTLENB(epno));
+
/* If this was the last endpoint, then the class driver is fully
* configured.
*/
@@ -3812,6 +3827,7 @@ static int sam_pullup(FAR struct usbdev_s *dev, bool enable)
static void sam_reset(struct sam_usbdev_s *priv)
{
+ uint32_t regval;
uint8_t epno;
/* Make sure that clocking is enabled to the UDPHS peripheral.
@@ -3869,6 +3885,20 @@ static void sam_reset(struct sam_usbdev_s *priv)
/* Re-configure the USB controller in its initial, unconnected state */
priv->usbdev.speed = USB_SPEED_FULL;
+
+ /* Clear all pending interrupt status */
+
+ regval = UDPHS_INT_UPSTRRES | UDPHS_INT_ENDOFRSM | UDPHS_INT_WAKEUP |
+ UDPHS_INT_ENDRESET | UDPHS_INT_INTSOF | UDPHS_INT_MICROSOF |
+ UDPHS_INT_DETSUSPD;
+ sam_putreg(regval, SAM_UDPHS_CLRINT);
+
+ /* Enable normal operational interrupts (including endpoint 0) */
+
+ regval = UDPHS_INT_ENDOFRSM | UDPHS_INT_WAKEUP | UDPHS_INT_DETSUSPD |
+ UDPHS_INT_EPT0;
+ sam_putreg(regval, SAM_UDPHS_IEN);
+
sam_dumpep(priv, EP0);
}
@@ -3992,18 +4022,6 @@ static void sam_hw_setup(struct sam_usbdev_s *priv)
sam_putreg(0, SAM_UDPHS_IEN);
- /* Clear all pending interrupt status */
-
- regval = UDPHS_INT_UPSTRRES | UDPHS_INT_ENDOFRSM | UDPHS_INT_WAKEUP |
- UDPHS_INT_ENDRESET | UDPHS_INT_INTSOF | UDPHS_INT_MICROSOF |
- UDPHS_INT_DETSUSPD;
- sam_putreg(regval, SAM_UDPHS_CLRINT);
-
- /* Enable interrupts */
-
- regval = UDPHS_INT_ENDOFRSM | UDPHS_INT_WAKEUP | UDPHS_INT_DETSUSPD;
- sam_putreg(regval, SAM_UDPHS_IEN);
-
/* The Atmel sample code disables USB clocking here (via the PMC
* CKGR_UCKR). However, we cannot really do that here because that
* clocking is also needed by the UHPHS host.
@@ -4161,9 +4179,9 @@ void up_usbinitialize(void)
sam_sw_setup(priv);
- /* Power up and initialize USB controller, but leave it in the reset
- * state. Interrupts from the UDPHS controller are initialized here,
- * but will not be enabled at the AIC until the class driver is installed.
+ /* Power up and initialize USB controller. Interrupts from the UDPHS
+ * controller are initialized here, but will not be enabled at the AIC
+ * until the class driver is installed (by sam_reset()).
*/
sam_hw_setup(priv);
@@ -4280,7 +4298,7 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
}
else
{
- /* Setup the USB controller -- enabling interrupts at the USB controller */
+ /* Reset the USB controller and configure endpoint 0 */
sam_reset(priv);
@@ -4335,7 +4353,6 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
*/
flags = irqsave();
- sam_reset(priv);
/* Unbind the class driver */
@@ -4346,8 +4363,8 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
up_disable_irq(SAM_IRQ_UDPHS);
/* Put the hardware in an inactive state. Then bring the hardware back up
- * in the reset state (this is probably not necessary, the sam_reset()
- * call above was probably sufficient).
+ * in the initial state. This is essentially the same state as we were
+ * in when up_usbinitialize() was first called.
*/
sam_hw_shutdown(priv);