mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 18:35:42 +01:00 
			
		
		
		
	MIPS: Abstract cache op loops with a macro
The various cache maintenance routines perform a number of loops over cache lines. Rather than duplicate the code for performing such loops, abstract it out into a new cache_loop macro which performs an arbitrary number of cache ops on a range of addresses. This reduces duplication in the existing L1 cache maintenance code & will allow for not adding further duplication when introducing L2 cache support. Signed-off-by: Paul Burton <paul.burton@imgtec.com>
This commit is contained in:
		
				
					committed by
					
						 Daniel Schwierzeck
						Daniel Schwierzeck
					
				
			
			
				
	
			
			
			
						parent
						
							372286217f
						
					
				
				
					commit
					fb64cda579
				
			| @@ -37,82 +37,59 @@ static inline unsigned long dcache_line_size(void) | ||||
| 	return 2 << dl; | ||||
| } | ||||
|  | ||||
| #define cache_loop(start, end, lsize, ops...) do {			\ | ||||
| 	const void *addr = (const void *)(start & ~(lsize - 1));	\ | ||||
| 	const void *aend = (const void *)((end - 1) & ~(lsize - 1));	\ | ||||
| 	const unsigned int cache_ops[] = { ops };			\ | ||||
| 	unsigned int i;							\ | ||||
| 									\ | ||||
| 	for (; addr <= aend; addr += lsize) {				\ | ||||
| 		for (i = 0; i < ARRAY_SIZE(cache_ops); i++)		\ | ||||
| 			mips_cache(cache_ops[i], addr);			\ | ||||
| 	}								\ | ||||
| } while (0) | ||||
|  | ||||
| void flush_cache(ulong start_addr, ulong size) | ||||
| { | ||||
| 	unsigned long ilsize = icache_line_size(); | ||||
| 	unsigned long dlsize = dcache_line_size(); | ||||
| 	const void *addr, *aend; | ||||
|  | ||||
| 	/* aend will be miscalculated when size is zero, so we return here */ | ||||
| 	if (size == 0) | ||||
| 		return; | ||||
|  | ||||
| 	addr = (const void *)(start_addr & ~(dlsize - 1)); | ||||
| 	aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1)); | ||||
|  | ||||
| 	if (ilsize == dlsize) { | ||||
| 		/* flush I-cache & D-cache simultaneously */ | ||||
| 		while (1) { | ||||
| 			mips_cache(HIT_WRITEBACK_INV_D, addr); | ||||
| 			mips_cache(HIT_INVALIDATE_I, addr); | ||||
| 			if (addr == aend) | ||||
| 				break; | ||||
| 			addr += dlsize; | ||||
| 		} | ||||
| 		cache_loop(start_addr, start_addr + size, ilsize, | ||||
| 			   HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* flush D-cache */ | ||||
| 	while (1) { | ||||
| 		mips_cache(HIT_WRITEBACK_INV_D, addr); | ||||
| 		if (addr == aend) | ||||
| 			break; | ||||
| 		addr += dlsize; | ||||
| 	} | ||||
| 	cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); | ||||
|  | ||||
| 	/* flush I-cache */ | ||||
| 	addr = (const void *)(start_addr & ~(ilsize - 1)); | ||||
| 	aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1)); | ||||
| 	while (1) { | ||||
| 		mips_cache(HIT_INVALIDATE_I, addr); | ||||
| 		if (addr == aend) | ||||
| 			break; | ||||
| 		addr += ilsize; | ||||
| 	} | ||||
| 	cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); | ||||
| } | ||||
|  | ||||
| void flush_dcache_range(ulong start_addr, ulong stop) | ||||
| { | ||||
| 	unsigned long lsize = dcache_line_size(); | ||||
| 	const void *addr = (const void *)(start_addr & ~(lsize - 1)); | ||||
| 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); | ||||
|  | ||||
| 	/* aend will be miscalculated when size is zero, so we return here */ | ||||
| 	if (start_addr == stop) | ||||
| 		return; | ||||
|  | ||||
| 	while (1) { | ||||
| 		mips_cache(HIT_WRITEBACK_INV_D, addr); | ||||
| 		if (addr == aend) | ||||
| 			break; | ||||
| 		addr += lsize; | ||||
| 	} | ||||
| 	cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); | ||||
| } | ||||
|  | ||||
| void invalidate_dcache_range(ulong start_addr, ulong stop) | ||||
| { | ||||
| 	unsigned long lsize = dcache_line_size(); | ||||
| 	const void *addr = (const void *)(start_addr & ~(lsize - 1)); | ||||
| 	const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); | ||||
|  | ||||
| 	/* aend will be miscalculated when size is zero, so we return here */ | ||||
| 	if (start_addr == stop) | ||||
| 		return; | ||||
|  | ||||
| 	while (1) { | ||||
| 		mips_cache(HIT_INVALIDATE_D, addr); | ||||
| 		if (addr == aend) | ||||
| 			break; | ||||
| 		addr += lsize; | ||||
| 	} | ||||
| 	cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_I); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user