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; | 	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) | void flush_cache(ulong start_addr, ulong size) | ||||||
| { | { | ||||||
| 	unsigned long ilsize = icache_line_size(); | 	unsigned long ilsize = icache_line_size(); | ||||||
| 	unsigned long dlsize = dcache_line_size(); | 	unsigned long dlsize = dcache_line_size(); | ||||||
| 	const void *addr, *aend; |  | ||||||
|  |  | ||||||
| 	/* aend will be miscalculated when size is zero, so we return here */ | 	/* aend will be miscalculated when size is zero, so we return here */ | ||||||
| 	if (size == 0) | 	if (size == 0) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	addr = (const void *)(start_addr & ~(dlsize - 1)); |  | ||||||
| 	aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1)); |  | ||||||
|  |  | ||||||
| 	if (ilsize == dlsize) { | 	if (ilsize == dlsize) { | ||||||
| 		/* flush I-cache & D-cache simultaneously */ | 		/* flush I-cache & D-cache simultaneously */ | ||||||
| 		while (1) { | 		cache_loop(start_addr, start_addr + size, ilsize, | ||||||
| 			mips_cache(HIT_WRITEBACK_INV_D, addr); | 			   HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); | ||||||
| 			mips_cache(HIT_INVALIDATE_I, addr); |  | ||||||
| 			if (addr == aend) |  | ||||||
| 				break; |  | ||||||
| 			addr += dlsize; |  | ||||||
| 		} |  | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* flush D-cache */ | 	/* flush D-cache */ | ||||||
| 	while (1) { | 	cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); | ||||||
| 		mips_cache(HIT_WRITEBACK_INV_D, addr); |  | ||||||
| 		if (addr == aend) |  | ||||||
| 			break; |  | ||||||
| 		addr += dlsize; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/* flush I-cache */ | 	/* flush I-cache */ | ||||||
| 	addr = (const void *)(start_addr & ~(ilsize - 1)); | 	cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); | ||||||
| 	aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1)); |  | ||||||
| 	while (1) { |  | ||||||
| 		mips_cache(HIT_INVALIDATE_I, addr); |  | ||||||
| 		if (addr == aend) |  | ||||||
| 			break; |  | ||||||
| 		addr += ilsize; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void flush_dcache_range(ulong start_addr, ulong stop) | void flush_dcache_range(ulong start_addr, ulong stop) | ||||||
| { | { | ||||||
| 	unsigned long lsize = dcache_line_size(); | 	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 */ | 	/* aend will be miscalculated when size is zero, so we return here */ | ||||||
| 	if (start_addr == stop) | 	if (start_addr == stop) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	while (1) { | 	cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); | ||||||
| 		mips_cache(HIT_WRITEBACK_INV_D, addr); |  | ||||||
| 		if (addr == aend) |  | ||||||
| 			break; |  | ||||||
| 		addr += lsize; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void invalidate_dcache_range(ulong start_addr, ulong stop) | void invalidate_dcache_range(ulong start_addr, ulong stop) | ||||||
| { | { | ||||||
| 	unsigned long lsize = dcache_line_size(); | 	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 */ | 	/* aend will be miscalculated when size is zero, so we return here */ | ||||||
| 	if (start_addr == stop) | 	if (start_addr == stop) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	while (1) { | 	cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_I); | ||||||
| 		mips_cache(HIT_INVALIDATE_D, addr); |  | ||||||
| 		if (addr == aend) |  | ||||||
| 			break; |  | ||||||
| 		addr += lsize; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user