|  | /* | 
|  | * This file contains miscellaneous low-level functions. | 
|  | *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 
|  | * | 
|  | * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) | 
|  | * and Paul Mackerras. | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License | 
|  | * as published by the Free Software Foundation; either version | 
|  | * 2 of the License, or (at your option) any later version. | 
|  | * | 
|  | */ | 
|  |  | 
|  | #include <config.h> | 
|  | #include <config.h> | 
|  | #include <asm/ppc4xx.h> | 
|  | #include <ppc_asm.tmpl> | 
|  | #include <ppc_defs.h> | 
|  | #include <asm/cache.h> | 
|  | #include <asm/mmu.h> | 
|  |  | 
|  | /* | 
|  | * Flush instruction cache. | 
|  | */ | 
|  | _GLOBAL(invalidate_icache) | 
|  | iccci	r0,r0 | 
|  | isync | 
|  | blr | 
|  |  | 
|  | /* | 
|  | * Write any modified data cache blocks out to memory | 
|  | * and invalidate the corresponding instruction cache blocks. | 
|  | * | 
|  | * flush_icache_range(unsigned long start, unsigned long stop) | 
|  | */ | 
|  | _GLOBAL(flush_icache_range) | 
|  | li	r5,L1_CACHE_BYTES-1 | 
|  | andc	r3,r3,r5 | 
|  | subf	r4,r3,r4 | 
|  | add	r4,r4,r5 | 
|  | srwi.	r4,r4,L1_CACHE_SHIFT | 
|  | beqlr | 
|  | mtctr	r4 | 
|  | mr	r6,r3 | 
|  | 1:	dcbst	0,r3 | 
|  | addi	r3,r3,L1_CACHE_BYTES | 
|  | bdnz	1b | 
|  | sync				/* wait for dcbst's to get to ram */ | 
|  | mtctr	r4 | 
|  | 2:	icbi	0,r6 | 
|  | addi	r6,r6,L1_CACHE_BYTES | 
|  | bdnz	2b | 
|  | sync				/* additional sync needed on g4 */ | 
|  | isync | 
|  | blr | 
|  |  | 
|  | /* | 
|  | * Write any modified data cache blocks out to memory. | 
|  | * Does not invalidate the corresponding cache lines (especially for | 
|  | * any corresponding instruction cache). | 
|  | * | 
|  | * clean_dcache_range(unsigned long start, unsigned long stop) | 
|  | */ | 
|  | _GLOBAL(clean_dcache_range) | 
|  | li	r5,L1_CACHE_BYTES-1 | 
|  | andc	r3,r3,r5 | 
|  | subf	r4,r3,r4 | 
|  | add	r4,r4,r5 | 
|  | srwi.	r4,r4,L1_CACHE_SHIFT | 
|  | beqlr | 
|  | mtctr	r4 | 
|  |  | 
|  | 1:	dcbst	0,r3 | 
|  | addi	r3,r3,L1_CACHE_BYTES | 
|  | bdnz	1b | 
|  | sync				/* wait for dcbst's to get to ram */ | 
|  | blr | 
|  |  | 
|  | /* | 
|  | * Write any modified data cache blocks out to memory and invalidate them. | 
|  | * Does not invalidate the corresponding instruction cache blocks. | 
|  | * | 
|  | * flush_dcache_range(unsigned long start, unsigned long stop) | 
|  | */ | 
|  | _GLOBAL(flush_dcache_range) | 
|  | li	r5,L1_CACHE_BYTES-1 | 
|  | andc	r3,r3,r5 | 
|  | subf	r4,r3,r4 | 
|  | add	r4,r4,r5 | 
|  | srwi.	r4,r4,L1_CACHE_SHIFT | 
|  | beqlr | 
|  | mtctr	r4 | 
|  |  | 
|  | 1:	dcbf	0,r3 | 
|  | addi	r3,r3,L1_CACHE_BYTES | 
|  | bdnz	1b | 
|  | sync				/* wait for dcbst's to get to ram */ | 
|  | blr | 
|  |  | 
|  | /* | 
|  | * Like above, but invalidate the D-cache.  This is used by the 8xx | 
|  | * to invalidate the cache so the PPC core doesn't get stale data | 
|  | * from the CPM (no cache snooping here :-). | 
|  | * | 
|  | * invalidate_dcache_range(unsigned long start, unsigned long stop) | 
|  | */ | 
|  | _GLOBAL(invalidate_dcache_range) | 
|  | li	r5,L1_CACHE_BYTES-1 | 
|  | andc	r3,r3,r5 | 
|  | subf	r4,r3,r4 | 
|  | add	r4,r4,r5 | 
|  | srwi.	r4,r4,L1_CACHE_SHIFT | 
|  | beqlr | 
|  | mtctr	r4 | 
|  |  | 
|  | 1:	dcbi	0,r3 | 
|  | addi	r3,r3,L1_CACHE_BYTES | 
|  | bdnz	1b | 
|  | sync				/* wait for dcbi's to get to ram */ | 
|  | blr | 
|  |  | 
|  | /* | 
|  | * 40x cores have 8K or 16K dcache and 32 byte line size. | 
|  | * 44x has a 32K dcache and 32 byte line size. | 
|  | * 8xx has 1, 2, 4, 8K variants. | 
|  | * For now, cover the worst case of the 44x. | 
|  | * Must be called with external interrupts disabled. | 
|  | */ | 
|  | #define CACHE_NWAYS     64 | 
|  | #define CACHE_NLINES    32 | 
|  |  | 
|  | _GLOBAL(flush_dcache) | 
|  | li	r4,(2 * CACHE_NWAYS * CACHE_NLINES) | 
|  | mtctr	r4 | 
|  | lis	r5,0 | 
|  | 1:	lwz	r3,0(r5)		/* Load one word from every line */ | 
|  | addi	r5,r5,L1_CACHE_BYTES | 
|  | bdnz	1b | 
|  | sync | 
|  | blr | 
|  |  | 
|  | _GLOBAL(invalidate_dcache) | 
|  | addi	r6,0,0x0000		/* clear GPR 6 */ | 
|  | /* Do loop for # of dcache congruence classes. */ | 
|  | lis	r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@ha	/* TBS for large sized cache */ | 
|  | ori	r7,r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@l | 
|  | /* NOTE: dccci invalidates both */ | 
|  | mtctr	r7			/* ways in the D cache */ | 
|  | ..dcloop: | 
|  | dccci	0,r6			/* invalidate line */ | 
|  | addi	r6,r6,L1_CACHE_BYTES	/* bump to next line */ | 
|  | bdnz	..dcloop | 
|  | sync | 
|  | blr | 
|  |  | 
|  | /* | 
|  | * Cache functions. | 
|  | * | 
|  | * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM, | 
|  | * although for some cache-ralated calls stubs have to be provided to satisfy | 
|  | * symbols resolution. | 
|  | * Icache-related functions are used in POST framework. | 
|  | * | 
|  | */ | 
|  | #ifdef CONFIG_440 | 
|  |  | 
|  | .globl  dcache_disable | 
|  | .globl  dcache_enable | 
|  | .globl  icache_disable | 
|  | .globl  icache_enable | 
|  | dcache_disable: | 
|  | dcache_enable: | 
|  | icache_disable: | 
|  | icache_enable: | 
|  | blr | 
|  |  | 
|  | .globl	dcache_status | 
|  | .globl	icache_status | 
|  | dcache_status: | 
|  | icache_status: | 
|  | mr	r3,  0 | 
|  | blr | 
|  |  | 
|  | #else /* CONFIG_440 */ | 
|  |  | 
|  | .globl	icache_enable | 
|  | icache_enable: | 
|  | mflr	r8 | 
|  | bl	invalidate_icache | 
|  | mtlr	r8 | 
|  | isync | 
|  | addis	r3,r0, 0xc000	      /* set bit 0 */ | 
|  | mticcr	r3 | 
|  | blr | 
|  |  | 
|  | .globl	icache_disable | 
|  | icache_disable: | 
|  | addis	r3,r0, 0x0000	      /* clear bit 0 */ | 
|  | mticcr	r3 | 
|  | isync | 
|  | blr | 
|  |  | 
|  | .globl	icache_status | 
|  | icache_status: | 
|  | mficcr	r3 | 
|  | srwi	r3, r3, 31	/* >>31 => select bit 0 */ | 
|  | blr | 
|  |  | 
|  | .globl	dcache_enable | 
|  | dcache_enable: | 
|  | mflr	r8 | 
|  | bl	invalidate_dcache | 
|  | mtlr	r8 | 
|  | isync | 
|  | addis	r3,r0, 0x8000	      /* set bit 0 */ | 
|  | mtdccr	r3 | 
|  | blr | 
|  |  | 
|  | .globl	dcache_disable | 
|  | dcache_disable: | 
|  | mflr	r8 | 
|  | bl	flush_dcache | 
|  | mtlr	r8 | 
|  | addis	r3,r0, 0x0000	      /* clear bit 0 */ | 
|  | mtdccr	r3 | 
|  | blr | 
|  |  | 
|  | .globl	dcache_status | 
|  | dcache_status: | 
|  | mfdccr	r3 | 
|  | srwi	r3, r3, 31	/* >>31 => select bit 0 */ | 
|  | blr | 
|  |  | 
|  | #endif /* CONFIG_440 */ |