SAMA5 OHCI: Driver is now basically functional
This commit is contained in:
parent
1fb80e0917
commit
11086f34d0
@ -5411,4 +5411,6 @@
|
|||||||
* arch/arm/src/stm32/stm32_spi.c: nbits() interface extended to
|
* arch/arm/src/stm32/stm32_spi.c: nbits() interface extended to
|
||||||
control bit order as well as bit width (from Teemu Pirinen)
|
control bit order as well as bit width (from Teemu Pirinen)
|
||||||
(2013-8-16)
|
(2013-8-16)
|
||||||
|
* arch/arm/src/sama5/sam_ohci.c: More to be tested, but the SAMA5
|
||||||
|
OHCI driver is now basically funtional (2013-8-16).
|
||||||
|
|
||||||
|
@ -756,24 +756,33 @@ static void sam_tbfree(uint8_t *buffer)
|
|||||||
static inline int sam_addbulked(struct sam_ed_s *ed)
|
static inline int sam_addbulked(struct sam_ed_s *ed)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USBHOST_BULK_DISABLE
|
#ifndef CONFIG_USBHOST_BULK_DISABLE
|
||||||
|
irqstate_t flags;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
uintptr_t physed;
|
uintptr_t physed;
|
||||||
|
|
||||||
|
/* Disable bulk list processing while we modify the list */
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
|
regval &= ~OHCI_CTRL_BLE;
|
||||||
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
|
|
||||||
/* Add the new bulk ED to the head of the bulk list */
|
/* Add the new bulk ED to the head of the bulk list */
|
||||||
|
|
||||||
ed->hw.nexted = sam_getreg(SAM_USBHOST_BULKHEADED);
|
ed->hw.nexted = sam_getreg(SAM_USBHOST_BULKHEADED);
|
||||||
|
cp15_coherent_dcache((uintptr_t)ed,
|
||||||
|
(uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
|
||||||
|
|
||||||
physed = sam_physramaddr((uintptr_t)ed);
|
physed = sam_physramaddr((uintptr_t)ed);
|
||||||
sam_putreg((uint32_t)physed, SAM_USBHOST_BULKHEADED);
|
sam_putreg((uint32_t)physed, SAM_USBHOST_BULKHEADED);
|
||||||
|
|
||||||
/* BulkListEnable. This bit is set to enable the processing of the
|
/* Re-enable bulk list processing. */
|
||||||
* Bulk list. Note: once enabled, it remains. We really should
|
|
||||||
* never modify the bulk list while BLE is set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
regval = sam_getreg(SAM_USBHOST_CTRL);
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
regval |= OHCI_CTRL_BLE;
|
regval |= OHCI_CTRL_BLE;
|
||||||
sam_putreg(regval, SAM_USBHOST_CTRL);
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
|
|
||||||
|
irqrestore(flags);
|
||||||
return OK;
|
return OK;
|
||||||
#else
|
#else
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
@ -793,9 +802,17 @@ static inline int sam_rembulked(struct sam_ed_s *ed)
|
|||||||
#ifndef CONFIG_USBHOST_BULK_DISABLE
|
#ifndef CONFIG_USBHOST_BULK_DISABLE
|
||||||
struct sam_ed_s *curr;
|
struct sam_ed_s *curr;
|
||||||
struct sam_ed_s *prev;
|
struct sam_ed_s *prev;
|
||||||
|
irqstate_t flags;
|
||||||
uintptr_t physed;
|
uintptr_t physed;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
|
||||||
|
/* Disable bulk list processing while we modify the list */
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
|
regval &= ~OHCI_CTRL_BLE;
|
||||||
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
|
|
||||||
/* Find the ED in the bulk list. NOTE: We really should never be mucking
|
/* Find the ED in the bulk list. NOTE: We really should never be mucking
|
||||||
* with the bulk list while BLE is set.
|
* with the bulk list while BLE is set.
|
||||||
*/
|
*/
|
||||||
@ -820,12 +837,6 @@ static inline int sam_rembulked(struct sam_ed_s *ed)
|
|||||||
/* Yes... set the head of the bulk list to skip over this ED */
|
/* Yes... set the head of the bulk list to skip over this ED */
|
||||||
|
|
||||||
sam_putreg(ed->hw.nexted, SAM_USBHOST_BULKHEADED);
|
sam_putreg(ed->hw.nexted, SAM_USBHOST_BULKHEADED);
|
||||||
|
|
||||||
/* If the bulk list is now empty, then disable it */
|
|
||||||
|
|
||||||
regval = sam_getreg(SAM_USBHOST_CTRL);
|
|
||||||
regval &= ~OHCI_CTRL_BLE;
|
|
||||||
sam_putreg(regval, SAM_USBHOST_CTRL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -834,9 +845,25 @@ static inline int sam_rembulked(struct sam_ed_s *ed)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
prev->hw.nexted = ed->hw.nexted;
|
prev->hw.nexted = ed->hw.nexted;
|
||||||
|
cp15_coherent_dcache((uintptr_t)prev,
|
||||||
|
(uintptr_t)prev + sizeof(struct sam_ed_s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Re-enable bulk list processing if the bulk list is still non-empty
|
||||||
|
* after removing the ED node.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (sam_getreg(SAM_USBHOST_BULKHEADED) != 0)
|
||||||
|
{
|
||||||
|
/* If the bulk list is now empty, then disable it */
|
||||||
|
|
||||||
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
|
regval |= OHCI_CTRL_BLE;
|
||||||
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
irqrestore(flags);
|
||||||
return OK;
|
return OK;
|
||||||
#else
|
#else
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
@ -897,7 +924,14 @@ static void sam_setinttab(uint32_t value, unsigned int interval, unsigned int of
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = offset; i < HCCA_INTTBL_WSIZE; i += interval)
|
for (i = offset; i < HCCA_INTTBL_WSIZE; i += interval)
|
||||||
{
|
{
|
||||||
|
/* Modify the table value */
|
||||||
|
|
||||||
g_hcca.inttbl[i] = value;
|
g_hcca.inttbl[i] = value;
|
||||||
|
|
||||||
|
/* Make sure that the modified table value is flushed to RAM */
|
||||||
|
|
||||||
|
cp15_coherent_dcache(&g_hcca.inttbl[i],
|
||||||
|
&g_hcca.inttbl[i] + sizeof(uint32_t) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -926,6 +960,7 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
|
|||||||
struct sam_ed_s *ed)
|
struct sam_ed_s *ed)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USBHOST_INT_DISABLE
|
#ifndef CONFIG_USBHOST_INT_DISABLE
|
||||||
|
irqstate_t flags;
|
||||||
unsigned int interval;
|
unsigned int interval;
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
uintptr_t physed;
|
uintptr_t physed;
|
||||||
@ -936,6 +971,7 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
|
|||||||
* at the next SOF... need to check.
|
* at the next SOF... need to check.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
regval = sam_getreg(SAM_USBHOST_CTRL);
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
regval &= ~OHCI_CTRL_PLE;
|
regval &= ~OHCI_CTRL_PLE;
|
||||||
sam_putreg(regval, SAM_USBHOST_CTRL);
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
@ -979,6 +1015,7 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
|
|||||||
interval = g_ohci.outinterval;
|
interval = g_ohci.outinterval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uvdbg("min interval: %d offset: %d\n", interval, offset);
|
uvdbg("min interval: %d offset: %d\n", interval, offset);
|
||||||
|
|
||||||
/* Get the (physical) head of the first of the duplicated entries. The
|
/* Get the (physical) head of the first of the duplicated entries. The
|
||||||
@ -998,15 +1035,21 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ed->hw.nexted = physhead;
|
ed->hw.nexted = physhead;
|
||||||
|
cp15_coherent_dcache((uintptr_t)ed,
|
||||||
|
(uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
|
||||||
|
|
||||||
physed = sam_physramaddr((uintptr_t)ed);
|
physed = sam_physramaddr((uintptr_t)ed);
|
||||||
sam_setinttab((uint32_t)physed, interval, offset);
|
sam_setinttab((uint32_t)physed, interval, offset);
|
||||||
|
|
||||||
uvdbg("head: %08x next: %08x\n", physed, physhead);
|
uvdbg("head: %08x next: %08x\n", physed, physhead);
|
||||||
|
|
||||||
/* Re-enabled periodic list processing */
|
/* Re-enable periodic list processing */
|
||||||
|
|
||||||
regval = sam_getreg(SAM_USBHOST_CTRL);
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
regval |= OHCI_CTRL_PLE;
|
regval |= OHCI_CTRL_PLE;
|
||||||
sam_putreg(regval, SAM_USBHOST_CTRL);
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
|
|
||||||
|
irqrestore(flags);
|
||||||
return OK;
|
return OK;
|
||||||
#else
|
#else
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
@ -1039,6 +1082,7 @@ static inline int sam_reminted(struct sam_ed_s *ed)
|
|||||||
struct sam_ed_s *head;
|
struct sam_ed_s *head;
|
||||||
struct sam_ed_s *curr;
|
struct sam_ed_s *curr;
|
||||||
struct sam_ed_s *prev;
|
struct sam_ed_s *prev;
|
||||||
|
irqstate_t flags;
|
||||||
uintptr_t physhead;
|
uintptr_t physhead;
|
||||||
unsigned int interval;
|
unsigned int interval;
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
@ -1048,6 +1092,7 @@ static inline int sam_reminted(struct sam_ed_s *ed)
|
|||||||
* at the next SOF... need to check.
|
* at the next SOF... need to check.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
flags = irqsave();
|
||||||
regval = sam_getreg(SAM_USBHOST_CTRL);
|
regval = sam_getreg(SAM_USBHOST_CTRL);
|
||||||
regval &= ~OHCI_CTRL_PLE;
|
regval &= ~OHCI_CTRL_PLE;
|
||||||
sam_putreg(regval, SAM_USBHOST_CTRL);
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
@ -1151,6 +1196,7 @@ static inline int sam_reminted(struct sam_ed_s *ed)
|
|||||||
sam_putreg(regval, SAM_USBHOST_CTRL);
|
sam_putreg(regval, SAM_USBHOST_CTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irqrestore(flags);
|
||||||
return OK;
|
return OK;
|
||||||
#else
|
#else
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
@ -2296,6 +2342,13 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
|
|||||||
ed->hw.headp = physaddr;
|
ed->hw.headp = physaddr;
|
||||||
ed->hw.tailp = physaddr;
|
ed->hw.tailp = physaddr;
|
||||||
|
|
||||||
|
/* Make sure these settings are flushed to RAM */
|
||||||
|
|
||||||
|
cp15_coherent_dcache((uintptr_t)ed,
|
||||||
|
(uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
|
||||||
|
cp15_coherent_dcache((uintptr_t)td,
|
||||||
|
(uintptr_t)td + sizeof(struct ohci_gtd_s) - 1);
|
||||||
|
|
||||||
/* Now add the endpoint descriptor to the appropriate list */
|
/* Now add the endpoint descriptor to the appropriate list */
|
||||||
|
|
||||||
switch (ed->xfrtype)
|
switch (ed->xfrtype)
|
||||||
@ -2797,9 +2850,12 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
|
|||||||
* TDs on the Bulk list.
|
* TDs on the Bulk list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (ed->xfrtype == USB_EP_ATTR_XFER_BULK)
|
||||||
|
{
|
||||||
regval = sam_getreg(SAM_USBHOST_CMDST);
|
regval = sam_getreg(SAM_USBHOST_CMDST);
|
||||||
regval |= OHCI_CMDST_BLF;
|
regval |= OHCI_CMDST_BLF;
|
||||||
sam_putreg(regval, SAM_USBHOST_CMDST);
|
sam_putreg(regval, SAM_USBHOST_CMDST);
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait for the Writeback Done Head interrupt Loop to handle any false
|
/* Wait for the Writeback Done Head interrupt Loop to handle any false
|
||||||
* alarm semaphore counts.
|
* alarm semaphore counts.
|
||||||
|
Loading…
Reference in New Issue
Block a user