summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-09-21 12:21:10 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-09-21 12:21:10 -0600
commit1ce725b615d98170bb21ba682d3fc97b2f2ead7d (patch)
tree1f581ac40d99b02ec30ce0b412f788e5b6c55fc8
parent3f1bd3bc5d4b8bd667c844a812b6f7bed96f5fd8 (diff)
downloadnuttx-1ce725b615d98170bb21ba682d3fc97b2f2ead7d.tar.gz
nuttx-1ce725b615d98170bb21ba682d3fc97b2f2ead7d.tar.bz2
nuttx-1ce725b615d98170bb21ba682d3fc97b2f2ead7d.zip
SAMA5 OHCI: Fix some strange Dcache problems that I still don't understand; end address on cache operations is end+1, not end
-rw-r--r--nuttx/arch/arm/src/sama5/sam_ohci.c60
1 files changed, 34 insertions, 26 deletions
diff --git a/nuttx/arch/arm/src/sama5/sam_ohci.c b/nuttx/arch/arm/src/sama5/sam_ohci.c
index 8c6907ba6..ca69a5934 100644
--- a/nuttx/arch/arm/src/sama5/sam_ohci.c
+++ b/nuttx/arch/arm/src/sama5/sam_ohci.c
@@ -792,8 +792,7 @@ static inline int sam_addbulked(struct sam_ed_s *ed)
/* Add the new bulk ED to the head of the bulk list */
ed->hw.nexted = sam_getreg(SAM_USBHOST_BULKHEADED);
- cp15_clean_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
+ cp15_clean_dcache((uintptr_t)ed, (uintptr_t)ed + sizeof(struct ohci_ed_s));
physed = sam_physramaddr((uintptr_t)ed);
sam_putreg((uint32_t)physed, SAM_USBHOST_BULKHEADED);
@@ -943,18 +942,20 @@ static unsigned int sam_getinterval(uint8_t interval)
#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
static void sam_setinttab(uint32_t value, unsigned int interval, unsigned int offset)
{
+ uintptr_t inttbl;
unsigned int i;
+
for (i = offset; i < HCCA_INTTBL_WSIZE; i += interval)
{
/* Modify the table value */
g_hcca.inttbl[i] = value;
+ }
- /* Make sure that the modified table value is flushed to RAM */
+ /* Make sure that the modified table value is flushed to RAM */
- cp15_clean_dcache((uintptr_t)&g_hcca.inttbl[i],
- (uintptr_t)&g_hcca.inttbl[i] + sizeof(uint32_t) - 1);
- }
+ inttbl = (uintptr_t)g_hcca.inttbl;
+ cp15_clean_dcache(inttbl, inttbl + sizeof(uint32_t)*HCCA_INTTBL_WSIZE);
}
#endif
@@ -1057,8 +1058,7 @@ static inline int sam_addinted(const FAR struct usbhost_epdesc_s *epdesc,
*/
ed->hw.nexted = physhead;
- cp15_clean_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
+ cp15_clean_dcache((uintptr_t)ed, (uintptr_t)ed + sizeof(struct ohci_ed_s));
physed = sam_physramaddr((uintptr_t)ed);
sam_setinttab((uint32_t)physed, interval, offset);
@@ -1296,7 +1296,7 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed,
ed->hw.ctrl |= ED_CONTROL_K;
cp15_clean_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)ed + sizeof(struct ohci_ed_s));
/* Get the tail ED for this root hub port */
@@ -1336,19 +1336,27 @@ static int sam_enqueuetd(struct sam_rhport_s *rhport, struct sam_ed_s *ed,
if (buffer && buflen > 0)
{
cp15_clean_dcache((uintptr_t)buffer,
- (uintptr_t)buffer + buflen - 1);
+ (uintptr_t)buffer + buflen);
+
+ /* REVISIT: This cache invalidation solves some transfer
+ * problems... but I don't understand why? Without this,
+ * the above clean seems to fail to flush all of the buffer.
+ */
+
+ cp15_invalidate_dcache((uintptr_t)buffer,
+ (uintptr_t)buffer + buflen);
}
cp15_clean_dcache((uintptr_t)tdtail,
- (uintptr_t)tdtail + sizeof(struct ohci_gtd_s) - 1);
+ (uintptr_t)tdtail + sizeof(struct ohci_gtd_s));
cp15_clean_dcache((uintptr_t)td,
- (uintptr_t)td + sizeof(struct ohci_gtd_s) - 1);
+ (uintptr_t)td + sizeof(struct ohci_gtd_s));
/* Resume processing of this ED */
ed->hw.ctrl &= ~ED_CONTROL_K;
cp15_clean_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)ed + sizeof(struct ohci_ed_s));
ret = OK;
}
@@ -1446,9 +1454,9 @@ static int sam_ep0enqueue(struct sam_rhport_s *rhport)
/* Flush the affected control ED and tail TD to RAM */
cp15_clean_dcache((uintptr_t)edctrl,
- (uintptr_t)edctrl + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)edctrl + sizeof(struct ohci_ed_s));
cp15_clean_dcache((uintptr_t)tdtail,
- (uintptr_t)tdtail + sizeof(struct ohci_gtd_s) - 1);
+ (uintptr_t)tdtail + sizeof(struct ohci_gtd_s));
/* ControlListEnable. This bit is set to (re-)enable the processing of the
* Control list. Note: once enabled, it remains enabled and we may even
@@ -1529,7 +1537,7 @@ static void sam_ep0dequeue(struct sam_rhport_s *rhport)
/* Flush the modified ED to RAM */
cp15_clean_dcache((uintptr_t)preved,
- (uintptr_t)preved + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)preved + sizeof(struct ohci_ed_s));
}
else
{
@@ -1882,10 +1890,10 @@ static void sam_wdh_bottomhalf(void)
# if 0 /* Apparently insufficient */
cp15_invalidate_dcache((uintptr_t)&g_hcca.donehead,
- (uintptr_t)&g_hcca.donehead + sizeof(uint32_t) - 1);
+ (uintptr_t)&g_hcca.donehead + sizeof(uint32_t));
#else
cp15_invalidate_dcache((uintptr_t)&g_hcca,
- (uintptr_t)&g_hcca + sizeof(struct ohci_hcca_s) - 1);
+ (uintptr_t)&g_hcca + sizeof(struct ohci_hcca_s));
#endif
/* Now read the done head */
@@ -1903,7 +1911,7 @@ static void sam_wdh_bottomhalf(void)
*/
cp15_invalidate_dcache((uintptr_t)td,
- (uintptr_t)td + sizeof( struct ohci_gtd_s) - 1);
+ (uintptr_t)td + sizeof( struct ohci_gtd_s));
/* Get the ED in which this TD was enqueued */
@@ -1920,7 +1928,7 @@ static void sam_wdh_bottomhalf(void)
*/
cp15_invalidate_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof( struct ohci_ed_s) - 1);
+ (uintptr_t)ed + sizeof( struct ohci_ed_s));
/* Save the condition code from the (single) TD status/control
* word.
@@ -2276,7 +2284,7 @@ static int sam_ep0configure(FAR struct usbhost_driver_s *drvr, uint8_t funcaddr,
/* Flush the modified control ED to RAM */
cp15_clean_dcache((uintptr_t)edctrl,
- (uintptr_t)edctrl + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)edctrl + sizeof(struct ohci_ed_s));
sam_givesem(&g_ohci.exclsem);
usbhost_vtrace2(OHCI_VTRACE2_EP0CONFIGURE,
@@ -2448,9 +2456,9 @@ static int sam_epalloc(FAR struct usbhost_driver_s *drvr,
/* Make sure these settings are flushed to RAM */
cp15_clean_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)ed + sizeof(struct ohci_ed_s));
cp15_clean_dcache((uintptr_t)td,
- (uintptr_t)td + sizeof(struct ohci_gtd_s) - 1);
+ (uintptr_t)td + sizeof(struct ohci_gtd_s));
/* Now add the endpoint descriptor to the appropriate list */
@@ -2816,7 +2824,7 @@ static int sam_ctrlin(FAR struct usbhost_driver_s *drvr,
*/
sam_givesem(&g_ohci.exclsem);
- cp15_invalidate_dcache((uintptr_t)buffer, (uintptr_t)buffer + len - 1);
+ cp15_invalidate_dcache((uintptr_t)buffer, (uintptr_t)buffer + len);
return ret;
}
@@ -3005,7 +3013,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
/* Invalidate the D cache to force the ED to be reloaded from RAM */
cp15_invalidate_dcache((uintptr_t)ed,
- (uintptr_t)ed + sizeof(struct ohci_ed_s) - 1);
+ (uintptr_t)ed + sizeof(struct ohci_ed_s));
/* Check the TD completion status bits */
@@ -3018,7 +3026,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
if (in)
{
cp15_invalidate_dcache((uintptr_t)buffer,
- (uintptr_t)buffer + buflen - 1);
+ (uintptr_t)buffer + buflen);
}
ret = OK;