Here is a solution for anyone still searching. FlushDataCacheRegion uses CPUSHL to flush only those data cache lines that could contain data from a specified memory region. I use this on the 5475 to flush tx buffers from the cache prior to setting the ready bit in the buffer descriptor and to flush rx buffers from the cache prior to setting the empty bit in the buffer descriptor. The buffers must be 16-byte aligned, and the size of the buffers must be evenly divisible by 16.
/**
* Flush and Invalidate specified memory from data cache
*
* Flushes (and invalidates by virtue of CACR[DDPI]=0) specified
* memory range from cache. This operation loops the memory range,
* calling CPUSHL for each 16 byte line to flush and invalidate for
* each of the 4 "ways" of the data cache.
*
* @param pMem points to the starting address of the region to be flushed
* from the data cache. If this address is not 16 byte aligned, this function
* will "back-up" to the nearest 16 byte boundary and start flushing from there.
*
* @param len_bytes specifies the size of the region in bytes.
*/
void FlushDataCacheRegion( void *pMem, unsigned long len_bytes )
{
asm{
MOVE.L pMem,D0 ;/* fetch start address */
MOVEA.L D0,A1 ;/* calculate stop address */
ADDA.L len_bytes,A1 ;
CLR.L D1 ;/* init way counter */
ANDI.L #0xFFFFFFF0,D0 ;/* calculate aligned start address */
FlushDataCacheRegion_wayloop:
MOVE D0,A0 ;/* initialize A0 */
ADDA.L D1,A0 ;/* set way index */
FlushDataCacheRegion_innerloop:
CPUSHL DC,(A0) ;/* flush and invalidate the cache line */
ADD.L #0x10,A0 ;/* increment to next cache line */
CMPA.L A0,A1 ;/* done with region? */
BGT FlushDataCacheRegion_innerloop;
ADDQ.L #1,D1 ;/* increment way counter */
ADDQ.L #1,A1 ;/* update stop address to reflect new way value */
CMPI.L #4,D1 ;/* check if all cache ways have been flushed */
BNE FlushDataCacheRegion_wayloop;
}
}