Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41700e73 authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Ralf Baechle
Browse files

[MIPS] Add protected_blast_icache_range, blast_icache_range, etc.


    
Add blast_xxx_range(), protected_blast_xxx_range() etc. for common
use.  They are built by __BUILD_BLAST_CACHE_RANGE().
Use protected_cache_op() macro for various protected_ routines.
Output code should be logically same.
    
Signed-off-by: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 63077519
Loading
Loading
Loading
Loading
+14 −90
Original line number Diff line number Diff line
@@ -471,61 +471,29 @@ struct flush_icache_range_args {
static inline void local_r4k_flush_icache_range(void *args)
{
	struct flush_icache_range_args *fir_args = args;
	unsigned long dc_lsize = cpu_dcache_line_size();
	unsigned long ic_lsize = cpu_icache_line_size();
	unsigned long sc_lsize = cpu_scache_line_size();
	unsigned long start = fir_args->start;
	unsigned long end = fir_args->end;
	unsigned long addr, aend;

	if (!cpu_has_ic_fills_f_dc) {
		if (end - start > dcache_size) {
			r4k_blast_dcache();
		} else {
			R4600_HIT_CACHEOP_WAR_IMPL;
			addr = start & ~(dc_lsize - 1);
			aend = (end - 1) & ~(dc_lsize - 1);

			while (1) {
				/* Hit_Writeback_Inv_D */
				protected_writeback_dcache_line(addr);
				if (addr == aend)
					break;
				addr += dc_lsize;
			}
			protected_blast_dcache_range(start, end);
		}

		if (!cpu_icache_snoops_remote_store) {
			if (end - start > scache_size) {
			if (end - start > scache_size)
				r4k_blast_scache();
			} else {
				addr = start & ~(sc_lsize - 1);
				aend = (end - 1) & ~(sc_lsize - 1);

				while (1) {
					/* Hit_Writeback_Inv_SD */
					protected_writeback_scache_line(addr);
					if (addr == aend)
						break;
					addr += sc_lsize;
				}
			}
			else
				protected_blast_scache_range(start, end);
		}
	}

	if (end - start > icache_size)
		r4k_blast_icache();
	else {
		addr = start & ~(ic_lsize - 1);
		aend = (end - 1) & ~(ic_lsize - 1);
		while (1) {
			/* Hit_Invalidate_I */
			protected_flush_icache_line(addr);
			if (addr == aend)
				break;
			addr += ic_lsize;
		}
	}
	else
		protected_blast_icache_range(start, end);
}

static void r4k_flush_icache_range(unsigned long start, unsigned long end)
@@ -619,27 +587,14 @@ static void r4k_flush_icache_page(struct vm_area_struct *vma,

static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
	unsigned long end, a;

	/* Catch bad driver code */
	BUG_ON(size == 0);

	if (cpu_has_subset_pcaches) {
		unsigned long sc_lsize = cpu_scache_line_size();

		if (size >= scache_size) {
		if (size >= scache_size)
			r4k_blast_scache();
			return;
		}

		a = addr & ~(sc_lsize - 1);
		end = (addr + size - 1) & ~(sc_lsize - 1);
		while (1) {
			flush_scache_line(a);	/* Hit_Writeback_Inv_SD */
			if (a == end)
				break;
			a += sc_lsize;
		}
		else
			blast_scache_range(addr, addr + size);
		return;
	}

@@ -651,17 +606,8 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
	if (size >= dcache_size) {
		r4k_blast_dcache();
	} else {
		unsigned long dc_lsize = cpu_dcache_line_size();

		R4600_HIT_CACHEOP_WAR_IMPL;
		a = addr & ~(dc_lsize - 1);
		end = (addr + size - 1) & ~(dc_lsize - 1);
		while (1) {
			flush_dcache_line(a);	/* Hit_Writeback_Inv_D */
			if (a == end)
				break;
			a += dc_lsize;
		}
		blast_dcache_range(addr, addr + size);
	}

	bc_wback_inv(addr, size);
@@ -669,44 +615,22 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)

static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
{
	unsigned long end, a;

	/* Catch bad driver code */
	BUG_ON(size == 0);

	if (cpu_has_subset_pcaches) {
		unsigned long sc_lsize = cpu_scache_line_size();

		if (size >= scache_size) {
		if (size >= scache_size)
			r4k_blast_scache();
			return;
		}

		a = addr & ~(sc_lsize - 1);
		end = (addr + size - 1) & ~(sc_lsize - 1);
		while (1) {
			flush_scache_line(a);	/* Hit_Writeback_Inv_SD */
			if (a == end)
				break;
			a += sc_lsize;
		}
		else
			blast_scache_range(addr, addr + size);
		return;
	}

	if (size >= dcache_size) {
		r4k_blast_dcache();
	} else {
		unsigned long dc_lsize = cpu_dcache_line_size();

		R4600_HIT_CACHEOP_WAR_IMPL;
		a = addr & ~(dc_lsize - 1);
		end = (addr + size - 1) & ~(dc_lsize - 1);
		while (1) {
			flush_dcache_line(a);	/* Hit_Writeback_Inv_D */
			if (a == end)
				break;
			a += dc_lsize;
		}
		blast_dcache_range(addr, addr + size);
	}

	bc_inv(addr, size);
+9 −61
Original line number Diff line number Diff line
@@ -44,8 +44,6 @@ __asm__ __volatile__( \
/* TX39H-style cache flush routines. */
static void tx39h_flush_icache_all(void)
{
	unsigned long start = KSEG0;
	unsigned long end = (start + icache_size);
	unsigned long flags, config;

	/* disable icache (set ICE#) */
@@ -53,33 +51,18 @@ static void tx39h_flush_icache_all(void)
	config = read_c0_conf();
	write_c0_conf(config & ~TX39_CONF_ICE);
	TX39_STOP_STREAMING();

	/* invalidate icache */
	while (start < end) {
		cache16_unroll32(start, Index_Invalidate_I);
		start += 0x200;
	}

	blast_icache16();
	write_c0_conf(config);
	local_irq_restore(flags);
}

static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
	unsigned long end, a;
	unsigned long dc_lsize = current_cpu_data.dcache.linesz;

	/* Catch bad driver code */
	BUG_ON(size == 0);

	iob();
	a = addr & ~(dc_lsize - 1);
	end = (addr + size - 1) & ~(dc_lsize - 1);
	while (1) {
		invalidate_dcache_line(a); /* Hit_Invalidate_D */
		if (a == end) break;
		a += dc_lsize;
	}
	blast_inv_dcache_range(addr, addr + size);
}


@@ -241,42 +224,21 @@ static void tx39_flush_data_cache_page(unsigned long addr)

static void tx39_flush_icache_range(unsigned long start, unsigned long end)
{
	unsigned long dc_lsize = current_cpu_data.dcache.linesz;
	unsigned long addr, aend;

	if (end - start > dcache_size)
		tx39_blast_dcache();
	else {
		addr = start & ~(dc_lsize - 1);
		aend = (end - 1) & ~(dc_lsize - 1);

		while (1) {
			/* Hit_Writeback_Inv_D */
			protected_writeback_dcache_line(addr);
			if (addr == aend)
				break;
			addr += dc_lsize;
		}
	}
	else
		protected_blast_dcache_range(start, end);

	if (end - start > icache_size)
		tx39_blast_icache();
	else {
		unsigned long flags, config;
		addr = start & ~(dc_lsize - 1);
		aend = (end - 1) & ~(dc_lsize - 1);
		/* disable icache (set ICE#) */
		local_irq_save(flags);
		config = read_c0_conf();
		write_c0_conf(config & ~TX39_CONF_ICE);
		TX39_STOP_STREAMING();
		while (1) {
			/* Hit_Invalidate_I */
			protected_flush_icache_line(addr);
			if (addr == aend)
				break;
			addr += dc_lsize;
		}
		protected_blast_icache_range(start, end);
		write_c0_conf(config);
		local_irq_restore(flags);
	}
@@ -311,7 +273,7 @@ static void tx39_flush_icache_page(struct vm_area_struct *vma, struct page *page

static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
	unsigned long end, a;
	unsigned long end;

	if (((size | addr) & (PAGE_SIZE - 1)) == 0) {
		end = addr + size;
@@ -322,20 +284,13 @@ static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size)
	} else if (size > dcache_size) {
		tx39_blast_dcache();
	} else {
		unsigned long dc_lsize = current_cpu_data.dcache.linesz;
		a = addr & ~(dc_lsize - 1);
		end = (addr + size - 1) & ~(dc_lsize - 1);
		while (1) {
			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
			if (a == end) break;
			a += dc_lsize;
		}
		blast_dcache_range(addr, addr + size);
	}
}

static void tx39_dma_cache_inv(unsigned long addr, unsigned long size)
{
	unsigned long end, a;
	unsigned long end;

	if (((size | addr) & (PAGE_SIZE - 1)) == 0) {
		end = addr + size;
@@ -346,14 +301,7 @@ static void tx39_dma_cache_inv(unsigned long addr, unsigned long size)
	} else if (size > dcache_size) {
		tx39_blast_dcache();
	} else {
		unsigned long dc_lsize = current_cpu_data.dcache.linesz;
		a = addr & ~(dc_lsize - 1);
		end = (addr + size - 1) & ~(dc_lsize - 1);
		while (1) {
			invalidate_dcache_line(a); /* Hit_Invalidate_D */
			if (a == end) break;
			a += dc_lsize;
		}
		blast_inv_dcache_range(addr, addr + size);
	}
}

+41 −33
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#include <asm/asm.h>
#include <asm/cacheops.h>
#include <asm/cpu-features.h>

/*
 * This macro return a properly sign-extended address suitable as base address
@@ -78,22 +79,25 @@ static inline void flush_scache_line(unsigned long addr)
	cache_op(Hit_Writeback_Inv_SD, addr);
}

#define protected_cache_op(op,addr)				\
	__asm__ __volatile__(					\
	"	.set	push			\n"		\
	"	.set	noreorder		\n"		\
	"	.set	mips3			\n"		\
	"1:	cache	%0, (%1)		\n"		\
	"2:	.set	pop			\n"		\
	"	.section __ex_table,\"a\"	\n"		\
	"	"STR(PTR)" 1b, 2b		\n"		\
	"	.previous"					\
	:							\
	: "i" (op), "r" (addr))

/*
 * The next two are for badland addresses like signal trampolines.
 */
static inline void protected_flush_icache_line(unsigned long addr)
{
	__asm__ __volatile__(
		"	.set	push			\n"
		"	.set	noreorder		\n"
		"	.set	mips3			\n"
		"1:	cache	%0, (%1)		\n"
		"2:	.set	pop			\n"
		"	.section __ex_table,\"a\"	\n"
		"	"STR(PTR)" 1b, 2b		\n"
		"	.previous"
		:
		: "i" (Hit_Invalidate_I), "r" (addr));
	protected_cache_op(Hit_Invalidate_I, addr);
}

/*
@@ -104,32 +108,12 @@ static inline void protected_flush_icache_line(unsigned long addr)
 */
static inline void protected_writeback_dcache_line(unsigned long addr)
{
	__asm__ __volatile__(
		"	.set	push			\n"
		"	.set	noreorder		\n"
		"	.set	mips3			\n"
		"1:	cache	%0, (%1)		\n"
		"2:	.set	pop			\n"
		"	.section __ex_table,\"a\"	\n"
		"	"STR(PTR)" 1b, 2b		\n"
		"	.previous"
		:
		: "i" (Hit_Writeback_Inv_D), "r" (addr));
	protected_cache_op(Hit_Writeback_Inv_D, addr);
}

static inline void protected_writeback_scache_line(unsigned long addr)
{
	__asm__ __volatile__(
		"	.set	push			\n"
		"	.set	noreorder		\n"
		"	.set	mips3			\n"
		"1:	cache	%0, (%1)		\n"
		"2:	.set	pop			\n"
		"	.section __ex_table,\"a\"	\n"
		"	"STR(PTR)" 1b, 2b		\n"
		"	.previous"
		:
		: "i" (Hit_Writeback_Inv_SD), "r" (addr));
	protected_cache_op(Hit_Writeback_Inv_SD, addr);
}

/*
@@ -295,4 +279,28 @@ __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)

/* build blast_xxx_range, protected_blast_xxx_range */
#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
						    unsigned long end)	\
{									\
	unsigned long lsize = cpu_##desc##_line_size();			\
	unsigned long addr = start & ~(lsize - 1);			\
	unsigned long aend = (end - 1) & ~(lsize - 1);			\
	while (1) {							\
		prot##cache_op(hitop, addr);				\
		if (addr == aend)					\
			break;						\
		addr += lsize;						\
	}								\
}

__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
/* blast_inv_dcache_range */
__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )

#endif /* _ASM_R4KCACHE_H */