[U-Boot-Users] Regarding Dcache Flush in MPC85xx

Scott Wood scottwood at freescale.com
Fri Feb 29 18:42:40 CET 2008


On Fri, Feb 29, 2008 at 06:10:10PM +0100, Rafal Jaworowski wrote:
> Not really, unfortunatelly: the 85xx still lacks flushing the d-cache
> before disabling it. I was going to fix this by refactoring existing
> d-cache disabling/flushing routines into a common code that would sit in
> the lib_ppc/ppccache.S (as mostly exisiting implementations are just
> copy/paste of the same thing) and have 85xx use it too, but didn't have
> time yet to clean it up. If anyone is willing to do it sooner, I won't
> complain :)

The implementations for other CPUs such as 86xx are a bit questionable
(arbitrarily using the cache line times 65536 as the size to flush, and
inefficiently iterating 4 bytes at a time rather than a cache line).

Here's an 85xx implementation from an as-yet-unmerged Linux tree (replace
KERNELBASE with something appropriate for U-boot) that dynamically figures
out the cache and cache block sizes.  Note that it assumes at most 8 ways.

_GLOBAL(flush_disable_L1)
	mfspr	r3, SPRN_L1CFG0

	rlwinm	r5, r3, 9, 3	/* Extract cache block size */
	twlgti	r5, 1		/* Only 32 and 64 byte cache blocks
	                         * are currently defined.
	                         */
	li	r4, 32
	subfic	r6, r5, 2	/* r6 = log2(1KiB / cache block size) -
	                         *      log2(number of ways)
	                         */
	slw	r5, r4, r5	/* r5 = cache block size */

	rlwinm	r7, r3, 0, 0xff	/* Extract number of KiB in the cache */
	mulli	r7, r7, 13	/* An 8-way cache will require 13
	                         * loads per way.
	                         */
	slw	r7, r7, r6

	lis	r4, KERNELBASE at h
	mtctr	r7

1:	lwz	r0, 0(r4)	/* Load... */
	add	r4, r4, r5
	bdnz	1b

	msync
	lis	r4, KERNELBASE at h
	mtctr	r7

1:	dcbf	0, r4		/* ...and flush. */
	add	r4, r4, r5
	bdnz	1b

	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
	li	r5, 2
	rlwimi	r4, r5, 0, 3
	
	msync
	isync
	mtspr	SPRN_L1CSR0, r4
	isync

1:	mfspr	r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
	andi.	r4, r4, 2
	bne	1b

	rlwimi	r4, r3, 2, 3	/* Extract cache type */
	twlgti	r4, 1		/* Only 0 (Harvard) and 1 (Unified)
	                         * are currently defined.
	                         */

	andi.	r4, r4, 1	/* If it's unified, we're done. */
	bnelr

	mfspr	r4, SPRN_L1CSR1	/* Otherwise, invalidate the i-cache */
	li	r5, 2
	rlwimi	r4, r5, 0, 3
	
	msync
	isync
	mtspr	SPRN_L1CSR1, r4
	isync

1:	mfspr	r4, SPRN_L1CSR1 /* Wait for the invalidate to finish */
	andi.	r4, r4, 2
	bne	1b
	blr

_GLOBAL(invalidate_enable_L1)
	mfspr	r4, SPRN_L1CSR0 /* Invalidate d-cache */
	ori	r4, r4, 2
	
	msync
	isync
	mtspr	SPRN_L1CSR0, r4
	isync

1:	mfspr	r4, SPRN_L1CSR0 /* Wait for the invalidate to finish */
	andi.	r5, r4, 2
	bne	1b

	ori	r4, r4, 1	/* Enable d-cache */
	msync
	isync
	mtspr	SPRN_L1CSR0, r4
	isync

	mfspr	r3, SPRN_L1CFG0
	rlwimi	r4, r3, 2, 3	/* Extract cache type */
	twlgti	r4, 1		/* Only 0 (Harvard) and 1 (Unified)
	                         * are currently defined.
	                         */

	andi.	r4, r4, 1	/* If it's unified, we're done. */
	bnelr

	mfspr	r4, SPRN_L1CSR1	/* Otherwise, do the i-cache as well */
	ori	r5, r4, 2
	
	msync
	isync
	mtspr	SPRN_L1CSR1, r4
	isync

1:	mfspr	r4, SPRN_L1CSR1 /* Wait for the invalidate to finish */
	andi.	r4, r4, 2
	bne	1b

	ori	r4, r4, 1	/* Enable i-cache */
	msync
	isync
	mtspr	SPRN_L1CSR1, r4
	isync

	blr

	/* r3 = virtual address of L2 controller */
_GLOBAL(flush_disable_L2)
	/* It's a write-through cache, so only invalidation is needed. */
	lwz	r4, 0(r3)
	li	r5, 1
	rlwimi	r4, r5, 30, 0xc0000000
	stw	r4, 0(r3)

	/* Wait for the invalidate to finish */
1:	lwz	r4, 0(r3)
	andis.	r4, r4, 0x4000
	bne	1b

	blr

	/* r3 = virtual address of L2 controller */
_GLOBAL(invalidate_enable_L2)
	lwz	r4, 0(r3)
	li	r5, 3
	rlwimi	r4, r5, 30, 0xc0000000
	stw	r4, 0(r3)

	/* Wait for the invalidate to finish */
1:	lwz	r4, 0(r3)
	andis.	r4, r4, 0x4000
	bne	1b

	blr




More information about the U-Boot mailing list